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