1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // mt8183-da7219-max98357.c 4 // -- MT8183-DA7219-MAX98357 ALSA SoC machine driver 5 // 6 // Copyright (c) 2018 MediaTek Inc. 7 // Author: Shunli Wang <shunli.wang@mediatek.com> 8 9 #include <linux/module.h> 10 #include <sound/pcm_params.h> 11 #include <sound/soc.h> 12 #include <sound/jack.h> 13 #include <linux/pinctrl/consumer.h> 14 15 #include "mt8183-afe-common.h" 16 #include "../../codecs/da7219-aad.h" 17 #include "../../codecs/da7219.h" 18 19 struct mt8183_da7219_max98357_priv { 20 struct snd_soc_jack headset_jack; 21 }; 22 23 static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, 24 struct snd_pcm_hw_params *params) 25 { 26 struct snd_soc_pcm_runtime *rtd = substream->private_data; 27 unsigned int rate = params_rate(params); 28 unsigned int mclk_fs_ratio = 128; 29 unsigned int mclk_fs = rate * mclk_fs_ratio; 30 31 return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 32 0, mclk_fs, SND_SOC_CLOCK_OUT); 33 } 34 35 static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { 36 .hw_params = mt8183_mt6358_i2s_hw_params, 37 }; 38 39 static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, 40 struct snd_pcm_hw_params *params) 41 { 42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 43 struct snd_soc_dai *codec_dai; 44 unsigned int rate = params_rate(params); 45 unsigned int mclk_fs_ratio = 256; 46 unsigned int mclk_fs = rate * mclk_fs_ratio; 47 unsigned int freq; 48 int ret = 0, j; 49 50 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, 51 mclk_fs, SND_SOC_CLOCK_OUT); 52 if (ret < 0) 53 dev_err(rtd->dev, "failed to set cpu dai sysclk\n"); 54 55 for_each_rtd_codec_dais(rtd, j, codec_dai) { 56 57 if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { 58 ret = snd_soc_dai_set_sysclk(codec_dai, 59 DA7219_CLKSRC_MCLK, 60 mclk_fs, 61 SND_SOC_CLOCK_IN); 62 if (ret < 0) 63 dev_err(rtd->dev, "failed to set sysclk\n"); 64 65 if ((rate % 8000) == 0) 66 freq = DA7219_PLL_FREQ_OUT_98304; 67 else 68 freq = DA7219_PLL_FREQ_OUT_90316; 69 70 ret = snd_soc_dai_set_pll(codec_dai, 0, 71 DA7219_SYSCLK_PLL_SRM, 72 0, freq); 73 if (ret) 74 dev_err(rtd->dev, "failed to start PLL: %d\n", 75 ret); 76 } 77 } 78 79 return ret; 80 } 81 82 static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) 83 { 84 struct snd_soc_pcm_runtime *rtd = substream->private_data; 85 struct snd_soc_dai *codec_dai; 86 int ret = 0, j; 87 88 for_each_rtd_codec_dais(rtd, j, codec_dai) { 89 90 if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { 91 ret = snd_soc_dai_set_pll(codec_dai, 92 0, DA7219_SYSCLK_MCLK, 0, 0); 93 if (ret < 0) { 94 dev_err(rtd->dev, "failed to stop PLL: %d\n", 95 ret); 96 break; 97 } 98 } 99 } 100 101 return ret; 102 } 103 104 static const struct snd_soc_ops mt8183_da7219_i2s_ops = { 105 .hw_params = mt8183_da7219_i2s_hw_params, 106 .hw_free = mt8183_da7219_hw_free, 107 }; 108 109 static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 110 struct snd_pcm_hw_params *params) 111 { 112 /* fix BE i2s format to 32bit, clean param mask first */ 113 snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 114 0, SNDRV_PCM_FORMAT_LAST); 115 116 params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 117 118 return 0; 119 } 120 121 static int 122 mt8183_da7219_max98357_bt_sco_startup( 123 struct snd_pcm_substream *substream) 124 { 125 static const unsigned int rates[] = { 126 8000, 16000 127 }; 128 static const struct snd_pcm_hw_constraint_list constraints_rates = { 129 .count = ARRAY_SIZE(rates), 130 .list = rates, 131 .mask = 0, 132 }; 133 static const unsigned int channels[] = { 134 1, 135 }; 136 static const struct snd_pcm_hw_constraint_list constraints_channels = { 137 .count = ARRAY_SIZE(channels), 138 .list = channels, 139 .mask = 0, 140 }; 141 142 struct snd_pcm_runtime *runtime = substream->runtime; 143 144 snd_pcm_hw_constraint_list(runtime, 0, 145 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 146 runtime->hw.channels_max = 1; 147 snd_pcm_hw_constraint_list(runtime, 0, 148 SNDRV_PCM_HW_PARAM_CHANNELS, 149 &constraints_channels); 150 151 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 152 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 153 154 return 0; 155 } 156 157 static const struct snd_soc_ops mt8183_da7219_max98357_bt_sco_ops = { 158 .startup = mt8183_da7219_max98357_bt_sco_startup, 159 }; 160 161 /* FE */ 162 SND_SOC_DAILINK_DEFS(playback1, 163 DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 164 DAILINK_COMP_ARRAY(COMP_DUMMY()), 165 DAILINK_COMP_ARRAY(COMP_EMPTY())); 166 167 SND_SOC_DAILINK_DEFS(playback2, 168 DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 169 DAILINK_COMP_ARRAY(COMP_DUMMY()), 170 DAILINK_COMP_ARRAY(COMP_EMPTY())); 171 172 SND_SOC_DAILINK_DEFS(playback3, 173 DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 174 DAILINK_COMP_ARRAY(COMP_DUMMY()), 175 DAILINK_COMP_ARRAY(COMP_EMPTY())); 176 177 SND_SOC_DAILINK_DEFS(capture1, 178 DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 179 DAILINK_COMP_ARRAY(COMP_DUMMY()), 180 DAILINK_COMP_ARRAY(COMP_EMPTY())); 181 182 SND_SOC_DAILINK_DEFS(capture2, 183 DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 184 DAILINK_COMP_ARRAY(COMP_DUMMY()), 185 DAILINK_COMP_ARRAY(COMP_EMPTY())); 186 187 SND_SOC_DAILINK_DEFS(capture3, 188 DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 189 DAILINK_COMP_ARRAY(COMP_DUMMY()), 190 DAILINK_COMP_ARRAY(COMP_EMPTY())); 191 192 SND_SOC_DAILINK_DEFS(capture_mono, 193 DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), 194 DAILINK_COMP_ARRAY(COMP_DUMMY()), 195 DAILINK_COMP_ARRAY(COMP_EMPTY())); 196 197 SND_SOC_DAILINK_DEFS(playback_hdmi, 198 DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), 199 DAILINK_COMP_ARRAY(COMP_DUMMY()), 200 DAILINK_COMP_ARRAY(COMP_EMPTY())); 201 202 /* BE */ 203 SND_SOC_DAILINK_DEFS(primary_codec, 204 DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), 205 DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")), 206 DAILINK_COMP_ARRAY(COMP_EMPTY())); 207 208 SND_SOC_DAILINK_DEFS(pcm1, 209 DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), 210 DAILINK_COMP_ARRAY(COMP_DUMMY()), 211 DAILINK_COMP_ARRAY(COMP_EMPTY())); 212 213 SND_SOC_DAILINK_DEFS(pcm2, 214 DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), 215 DAILINK_COMP_ARRAY(COMP_DUMMY()), 216 DAILINK_COMP_ARRAY(COMP_EMPTY())); 217 218 SND_SOC_DAILINK_DEFS(i2s0, 219 DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), 220 DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 221 DAILINK_COMP_ARRAY(COMP_EMPTY())); 222 223 SND_SOC_DAILINK_DEFS(i2s1, 224 DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), 225 DAILINK_COMP_ARRAY(COMP_DUMMY()), 226 DAILINK_COMP_ARRAY(COMP_EMPTY())); 227 228 SND_SOC_DAILINK_DEFS(i2s2, 229 DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), 230 DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")), 231 DAILINK_COMP_ARRAY(COMP_EMPTY())); 232 233 SND_SOC_DAILINK_DEFS(i2s3, 234 DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 235 DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"), 236 COMP_CODEC("da7219.5-001a", "da7219-hifi")), 237 DAILINK_COMP_ARRAY(COMP_EMPTY())); 238 239 SND_SOC_DAILINK_DEFS(i2s5, 240 DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), 241 DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 242 DAILINK_COMP_ARRAY(COMP_EMPTY())); 243 244 SND_SOC_DAILINK_DEFS(tdm, 245 DAILINK_COMP_ARRAY(COMP_CPU("TDM")), 246 DAILINK_COMP_ARRAY(COMP_DUMMY()), 247 DAILINK_COMP_ARRAY(COMP_EMPTY())); 248 249 static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { 250 /* FE */ 251 { 252 .name = "Playback_1", 253 .stream_name = "Playback_1", 254 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 255 SND_SOC_DPCM_TRIGGER_PRE}, 256 .dynamic = 1, 257 .dpcm_playback = 1, 258 SND_SOC_DAILINK_REG(playback1), 259 }, 260 { 261 .name = "Playback_2", 262 .stream_name = "Playback_2", 263 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 264 SND_SOC_DPCM_TRIGGER_PRE}, 265 .dynamic = 1, 266 .dpcm_playback = 1, 267 .ops = &mt8183_da7219_max98357_bt_sco_ops, 268 SND_SOC_DAILINK_REG(playback2), 269 }, 270 { 271 .name = "Playback_3", 272 .stream_name = "Playback_3", 273 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 274 SND_SOC_DPCM_TRIGGER_PRE}, 275 .dynamic = 1, 276 .dpcm_playback = 1, 277 SND_SOC_DAILINK_REG(playback3), 278 }, 279 { 280 .name = "Capture_1", 281 .stream_name = "Capture_1", 282 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 283 SND_SOC_DPCM_TRIGGER_PRE}, 284 .dynamic = 1, 285 .dpcm_capture = 1, 286 .ops = &mt8183_da7219_max98357_bt_sco_ops, 287 SND_SOC_DAILINK_REG(capture1), 288 }, 289 { 290 .name = "Capture_2", 291 .stream_name = "Capture_2", 292 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 293 SND_SOC_DPCM_TRIGGER_PRE}, 294 .dynamic = 1, 295 .dpcm_capture = 1, 296 SND_SOC_DAILINK_REG(capture2), 297 }, 298 { 299 .name = "Capture_3", 300 .stream_name = "Capture_3", 301 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 302 SND_SOC_DPCM_TRIGGER_PRE}, 303 .dynamic = 1, 304 .dpcm_capture = 1, 305 SND_SOC_DAILINK_REG(capture3), 306 }, 307 { 308 .name = "Capture_Mono_1", 309 .stream_name = "Capture_Mono_1", 310 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 311 SND_SOC_DPCM_TRIGGER_PRE}, 312 .dynamic = 1, 313 .dpcm_capture = 1, 314 SND_SOC_DAILINK_REG(capture_mono), 315 }, 316 { 317 .name = "Playback_HDMI", 318 .stream_name = "Playback_HDMI", 319 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 320 SND_SOC_DPCM_TRIGGER_PRE}, 321 .dynamic = 1, 322 .dpcm_playback = 1, 323 SND_SOC_DAILINK_REG(playback_hdmi), 324 }, 325 /* BE */ 326 { 327 .name = "Primary Codec", 328 .no_pcm = 1, 329 .dpcm_playback = 1, 330 .dpcm_capture = 1, 331 .ignore_suspend = 1, 332 SND_SOC_DAILINK_REG(primary_codec), 333 }, 334 { 335 .name = "PCM 1", 336 .no_pcm = 1, 337 .dpcm_playback = 1, 338 .dpcm_capture = 1, 339 .ignore_suspend = 1, 340 SND_SOC_DAILINK_REG(pcm1), 341 }, 342 { 343 .name = "PCM 2", 344 .no_pcm = 1, 345 .dpcm_playback = 1, 346 .dpcm_capture = 1, 347 .ignore_suspend = 1, 348 SND_SOC_DAILINK_REG(pcm2), 349 }, 350 { 351 .name = "I2S0", 352 .no_pcm = 1, 353 .dpcm_capture = 1, 354 .ignore_suspend = 1, 355 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 356 .ops = &mt8183_mt6358_i2s_ops, 357 SND_SOC_DAILINK_REG(i2s0), 358 }, 359 { 360 .name = "I2S1", 361 .no_pcm = 1, 362 .dpcm_playback = 1, 363 .ignore_suspend = 1, 364 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 365 .ops = &mt8183_mt6358_i2s_ops, 366 SND_SOC_DAILINK_REG(i2s1), 367 }, 368 { 369 .name = "I2S2", 370 .no_pcm = 1, 371 .dpcm_capture = 1, 372 .ignore_suspend = 1, 373 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 374 .ops = &mt8183_da7219_i2s_ops, 375 SND_SOC_DAILINK_REG(i2s2), 376 }, 377 { 378 .name = "I2S3", 379 .no_pcm = 1, 380 .dpcm_playback = 1, 381 .ignore_suspend = 1, 382 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 383 .ops = &mt8183_da7219_i2s_ops, 384 SND_SOC_DAILINK_REG(i2s3), 385 }, 386 { 387 .name = "I2S5", 388 .no_pcm = 1, 389 .dpcm_playback = 1, 390 .ignore_suspend = 1, 391 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 392 .ops = &mt8183_mt6358_i2s_ops, 393 SND_SOC_DAILINK_REG(i2s5), 394 }, 395 { 396 .name = "TDM", 397 .no_pcm = 1, 398 .dai_fmt = SND_SOC_DAIFMT_I2S | 399 SND_SOC_DAIFMT_IB_IF | 400 SND_SOC_DAIFMT_CBM_CFM, 401 .dpcm_playback = 1, 402 .ignore_suspend = 1, 403 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 404 SND_SOC_DAILINK_REG(tdm), 405 }, 406 }; 407 408 static int 409 mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); 410 411 static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { 412 .dlc = COMP_EMPTY(), 413 .init = mt8183_da7219_max98357_headset_init, 414 }; 415 416 static struct snd_soc_codec_conf mt6358_codec_conf[] = { 417 { 418 .dlc = COMP_CODEC_CONF("mt6358-sound"), 419 .name_prefix = "Mt6358", 420 }, 421 }; 422 423 static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = { 424 SOC_DAPM_PIN_SWITCH("Speakers"), 425 }; 426 427 static const 428 struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = { 429 SND_SOC_DAPM_SPK("Speakers", NULL), 430 SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL", 431 "aud_tdm_out_on", "aud_tdm_out_off"), 432 }; 433 434 static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = { 435 {"Speakers", NULL, "Speaker"}, 436 {"I2S Playback", NULL, "TDM_OUT_PINCTRL"}, 437 }; 438 439 static struct snd_soc_card mt8183_da7219_max98357_card = { 440 .name = "mt8183_da7219_max98357", 441 .owner = THIS_MODULE, 442 .controls = mt8183_da7219_max98357_snd_controls, 443 .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls), 444 .dapm_widgets = mt8183_da7219_max98357_dapm_widgets, 445 .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), 446 .dapm_routes = mt8183_da7219_max98357_dapm_routes, 447 .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), 448 .dai_link = mt8183_da7219_max98357_dai_links, 449 .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links), 450 .aux_dev = &mt8183_da7219_max98357_headset_dev, 451 .num_aux_devs = 1, 452 .codec_conf = mt6358_codec_conf, 453 .num_configs = ARRAY_SIZE(mt6358_codec_conf), 454 }; 455 456 static int 457 mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) 458 { 459 int ret; 460 struct mt8183_da7219_max98357_priv *priv = 461 snd_soc_card_get_drvdata(component->card); 462 463 /* Enable Headset and 4 Buttons Jack detection */ 464 ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card, 465 "Headset Jack", 466 SND_JACK_HEADSET | 467 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 468 SND_JACK_BTN_2 | SND_JACK_BTN_3, 469 &priv->headset_jack, 470 NULL, 0); 471 if (ret) 472 return ret; 473 474 da7219_aad_jack_det(component, &priv->headset_jack); 475 476 return ret; 477 } 478 479 static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) 480 { 481 struct snd_soc_card *card = &mt8183_da7219_max98357_card; 482 struct device_node *platform_node; 483 struct snd_soc_dai_link *dai_link; 484 struct mt8183_da7219_max98357_priv *priv; 485 struct pinctrl *pinctrl; 486 int ret, i; 487 488 card->dev = &pdev->dev; 489 490 platform_node = of_parse_phandle(pdev->dev.of_node, 491 "mediatek,platform", 0); 492 if (!platform_node) { 493 dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); 494 return -EINVAL; 495 } 496 497 for_each_card_prelinks(card, i, dai_link) { 498 if (dai_link->platforms->name) 499 continue; 500 dai_link->platforms->of_node = platform_node; 501 } 502 503 mt8183_da7219_max98357_headset_dev.dlc.of_node = 504 of_parse_phandle(pdev->dev.of_node, 505 "mediatek,headset-codec", 0); 506 if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) { 507 dev_err(&pdev->dev, 508 "Property 'mediatek,headset-codec' missing/invalid\n"); 509 return -EINVAL; 510 } 511 512 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 513 if (!priv) 514 return -ENOMEM; 515 516 snd_soc_card_set_drvdata(card, priv); 517 518 pinctrl = devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); 519 if (IS_ERR(pinctrl)) { 520 ret = PTR_ERR(pinctrl); 521 dev_err(&pdev->dev, "%s failed to select default state %d\n", 522 __func__, ret); 523 return ret; 524 } 525 526 return devm_snd_soc_register_card(&pdev->dev, card); 527 } 528 529 #ifdef CONFIG_OF 530 static const struct of_device_id mt8183_da7219_max98357_dt_match[] = { 531 {.compatible = "mediatek,mt8183_da7219_max98357",}, 532 {} 533 }; 534 #endif 535 536 static struct platform_driver mt8183_da7219_max98357_driver = { 537 .driver = { 538 .name = "mt8183_da7219_max98357", 539 #ifdef CONFIG_OF 540 .of_match_table = mt8183_da7219_max98357_dt_match, 541 #endif 542 }, 543 .probe = mt8183_da7219_max98357_dev_probe, 544 }; 545 546 module_platform_driver(mt8183_da7219_max98357_driver); 547 548 /* Module information */ 549 MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver"); 550 MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>"); 551 MODULE_LICENSE("GPL v2"); 552 MODULE_ALIAS("mt8183_da7219_max98357 soc card"); 553