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