1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright(c) 2019 Intel Corporation. 3 4 /* 5 * Intel SOF Machine driver for Dialog headphone codec 6 */ 7 8 #include <linux/input.h> 9 #include <linux/module.h> 10 #include <sound/jack.h> 11 #include <sound/pcm.h> 12 #include <sound/pcm_params.h> 13 #include <linux/platform_device.h> 14 #include <sound/soc.h> 15 #include <sound/soc-acpi.h> 16 #include <sound/sof.h> 17 #include "../../codecs/da7219.h" 18 #include "hda_dsp_common.h" 19 #include "sof_maxim_common.h" 20 #include "sof_ssp_common.h" 21 22 /* Board Quirks */ 23 #define SOF_DA7219_JSL_BOARD BIT(2) 24 25 #define DIALOG_CODEC_DAI "da7219-hifi" 26 27 struct hdmi_pcm { 28 struct list_head head; 29 struct snd_soc_dai *codec_dai; 30 int device; 31 }; 32 33 struct card_private { 34 struct snd_soc_jack headset_jack; 35 struct list_head hdmi_pcm_list; 36 struct snd_soc_jack hdmi[3]; 37 enum sof_ssp_codec codec_type; 38 enum sof_ssp_codec amp_type; 39 40 unsigned int pll_bypass:1; 41 }; 42 43 static int platform_clock_control(struct snd_soc_dapm_widget *w, 44 struct snd_kcontrol *k, int event) 45 { 46 struct snd_soc_dapm_context *dapm = w->dapm; 47 struct snd_soc_card *card = dapm->card; 48 struct card_private *ctx = snd_soc_card_get_drvdata(card); 49 struct snd_soc_dai *codec_dai; 50 int ret = 0; 51 52 if (ctx->pll_bypass) 53 return ret; 54 55 /* PLL SRM mode */ 56 codec_dai = snd_soc_card_get_codec_dai(card, DIALOG_CODEC_DAI); 57 if (!codec_dai) { 58 dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n"); 59 return -EIO; 60 } 61 62 if (SND_SOC_DAPM_EVENT_OFF(event)) { 63 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 64 0, 0); 65 if (ret) 66 dev_err(card->dev, "failed to stop PLL: %d\n", ret); 67 } else if (SND_SOC_DAPM_EVENT_ON(event)) { 68 dev_dbg(card->dev, "pll srm mode\n"); 69 70 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, 71 0, DA7219_PLL_FREQ_OUT_98304); 72 if (ret) 73 dev_err(card->dev, "failed to start PLL: %d\n", ret); 74 } 75 76 return ret; 77 } 78 79 static const struct snd_kcontrol_new controls[] = { 80 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 81 SOC_DAPM_PIN_SWITCH("Headset Mic"), 82 SOC_DAPM_PIN_SWITCH("Line Out"), 83 SOC_DAPM_PIN_SWITCH("Left Spk"), 84 SOC_DAPM_PIN_SWITCH("Right Spk"), 85 }; 86 87 static const struct snd_soc_dapm_widget widgets[] = { 88 SND_SOC_DAPM_HP("Headphone Jack", NULL), 89 SND_SOC_DAPM_MIC("Headset Mic", NULL), 90 SND_SOC_DAPM_LINE("Line Out", NULL), 91 92 SND_SOC_DAPM_SPK("Left Spk", NULL), 93 SND_SOC_DAPM_SPK("Right Spk", NULL), 94 95 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 96 platform_clock_control, SND_SOC_DAPM_POST_PMD | 97 SND_SOC_DAPM_PRE_PMU), 98 99 SND_SOC_DAPM_MIC("SoC DMIC", NULL), 100 }; 101 102 static const struct snd_soc_dapm_route audio_map[] = { 103 { "Headphone Jack", NULL, "HPL" }, 104 { "Headphone Jack", NULL, "HPR" }, 105 106 { "MIC", NULL, "Headset Mic" }, 107 108 { "Headphone Jack", NULL, "Platform Clock" }, 109 { "Headset Mic", NULL, "Platform Clock" }, 110 { "Line Out", NULL, "Platform Clock" }, 111 112 /* digital mics */ 113 {"DMic", NULL, "SoC DMIC"}, 114 }; 115 116 static struct snd_soc_jack_pin jack_pins[] = { 117 { 118 .pin = "Headphone Jack", 119 .mask = SND_JACK_HEADPHONE, 120 }, 121 { 122 .pin = "Headset Mic", 123 .mask = SND_JACK_MICROPHONE, 124 }, 125 { 126 .pin = "Line Out", 127 .mask = SND_JACK_LINEOUT, 128 }, 129 }; 130 131 static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) 132 { 133 struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 134 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 135 struct snd_soc_component *component = codec_dai->component; 136 struct snd_soc_jack *jack = &ctx->headset_jack; 137 int mclk_rate, ret; 138 139 mclk_rate = sof_dai_get_mclk(rtd); 140 if (mclk_rate <= 0) { 141 dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_rate); 142 return -EINVAL; 143 } 144 145 ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, mclk_rate, 146 SND_SOC_CLOCK_IN); 147 if (ret) { 148 dev_err(rtd->dev, "fail to set sysclk, ret %d\n", ret); 149 return ret; 150 } 151 152 /* 153 * Use PLL bypass mode if MCLK is available, be sure to set the 154 * frequency of MCLK to 12.288 or 24.576MHz on topology side. 155 */ 156 if (mclk_rate == 12288000 || mclk_rate == 24576000) { 157 /* PLL bypass mode */ 158 dev_dbg(rtd->dev, "pll bypass mode, mclk rate %d\n", mclk_rate); 159 160 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); 161 if (ret) { 162 dev_err(rtd->dev, "fail to set pll, ret %d\n", ret); 163 return ret; 164 } 165 166 ctx->pll_bypass = 1; 167 } 168 169 /* 170 * Headset buttons map to the google Reference headset. 171 * These can be configured by userspace. 172 */ 173 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 174 SND_JACK_HEADSET | SND_JACK_BTN_0 | 175 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 176 SND_JACK_BTN_3 | SND_JACK_LINEOUT, 177 jack, jack_pins, ARRAY_SIZE(jack_pins)); 178 if (ret) { 179 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 180 return ret; 181 } 182 183 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 184 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); 185 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); 186 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); 187 188 ret = snd_soc_component_set_jack(component, jack, NULL); 189 if (ret) { 190 dev_err(rtd->dev, "fail to set component jack, ret %d\n", ret); 191 return ret; 192 } 193 194 return ret; 195 } 196 197 static int max98373_hw_params(struct snd_pcm_substream *substream, 198 struct snd_pcm_hw_params *params) 199 { 200 struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); 201 int ret, j; 202 203 for (j = 0; j < runtime->dai_link->num_codecs; j++) { 204 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, j); 205 206 if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { 207 /* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */ 208 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16); 209 if (ret < 0) { 210 dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); 211 return ret; 212 } 213 } 214 if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { 215 /* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */ 216 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16); 217 if (ret < 0) { 218 dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret); 219 return ret; 220 } 221 } 222 } 223 224 return 0; 225 } 226 227 static const struct snd_soc_ops max98373_ops = { 228 .hw_params = max98373_hw_params, 229 }; 230 231 static int hdmi_init(struct snd_soc_pcm_runtime *rtd) 232 { 233 struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 234 struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); 235 struct hdmi_pcm *pcm; 236 237 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 238 if (!pcm) 239 return -ENOMEM; 240 241 pcm->device = dai->id; 242 pcm->codec_dai = dai; 243 244 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 245 246 return 0; 247 } 248 249 static int card_late_probe(struct snd_soc_card *card) 250 { 251 struct card_private *ctx = snd_soc_card_get_drvdata(card); 252 struct snd_soc_acpi_mach *mach = (card->dev)->platform_data; 253 struct hdmi_pcm *pcm; 254 255 if (mach->mach_params.common_hdmi_codec_drv) { 256 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, 257 head); 258 return hda_dsp_hdmi_build_controls(card, 259 pcm->codec_dai->component); 260 } 261 262 return -EINVAL; 263 } 264 265 SND_SOC_DAILINK_DEF(ssp0_pin, 266 DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); 267 SND_SOC_DAILINK_DEF(ssp0_codec, 268 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", DIALOG_CODEC_DAI))); 269 270 SND_SOC_DAILINK_DEF(ssp1_pin, 271 DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); 272 273 SND_SOC_DAILINK_DEF(ssp2_pin, 274 DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin"))); 275 SND_SOC_DAILINK_DEF(dummy_codec, 276 DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai"))); 277 278 SND_SOC_DAILINK_DEF(dmic_pin, 279 DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); 280 SND_SOC_DAILINK_DEF(dmic_codec, 281 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 282 283 SND_SOC_DAILINK_DEF(dmic16k_pin, 284 DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); 285 286 SND_SOC_DAILINK_DEF(idisp1_pin, 287 DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); 288 SND_SOC_DAILINK_DEF(idisp1_codec, 289 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); 290 291 SND_SOC_DAILINK_DEF(idisp2_pin, 292 DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); 293 SND_SOC_DAILINK_DEF(idisp2_codec, 294 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); 295 296 SND_SOC_DAILINK_DEF(idisp3_pin, 297 DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); 298 SND_SOC_DAILINK_DEF(idisp3_codec, 299 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); 300 301 SND_SOC_DAILINK_DEF(idisp4_pin, 302 DAILINK_COMP_ARRAY(COMP_CPU("iDisp4 Pin"))); 303 SND_SOC_DAILINK_DEF(idisp4_codec, 304 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi4"))); 305 306 SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */ 307 DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); 308 309 static struct snd_soc_dai_link jsl_dais[] = { 310 /* Back End DAI links */ 311 { 312 .name = "SSP1-Codec", 313 .id = 0, 314 .ignore_pmdown_time = 1, 315 .no_pcm = 1, 316 .dpcm_playback = 1, 317 .dpcm_capture = 1, /* IV feedback */ 318 SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform), 319 }, 320 { 321 .name = "SSP0-Codec", 322 .id = 1, 323 .no_pcm = 1, 324 .init = da7219_codec_init, 325 .ignore_pmdown_time = 1, 326 .dpcm_playback = 1, 327 .dpcm_capture = 1, 328 SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), 329 }, 330 { 331 .name = "dmic01", 332 .id = 2, 333 .ignore_suspend = 1, 334 .dpcm_capture = 1, 335 .no_pcm = 1, 336 SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), 337 }, 338 { 339 .name = "iDisp1", 340 .id = 3, 341 .init = hdmi_init, 342 .dpcm_playback = 1, 343 .no_pcm = 1, 344 SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), 345 }, 346 { 347 .name = "iDisp2", 348 .id = 4, 349 .init = hdmi_init, 350 .dpcm_playback = 1, 351 .no_pcm = 1, 352 SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), 353 }, 354 { 355 .name = "iDisp3", 356 .id = 5, 357 .init = hdmi_init, 358 .dpcm_playback = 1, 359 .no_pcm = 1, 360 SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), 361 }, 362 { 363 .name = "dmic16k", 364 .id = 6, 365 .ignore_suspend = 1, 366 .dpcm_capture = 1, 367 .no_pcm = 1, 368 SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), 369 } 370 }; 371 372 static struct snd_soc_dai_link adl_dais[] = { 373 /* Back End DAI links */ 374 { 375 .name = "SSP0-Codec", 376 .id = 0, 377 .no_pcm = 1, 378 .init = da7219_codec_init, 379 .ignore_pmdown_time = 1, 380 .dpcm_playback = 1, 381 .dpcm_capture = 1, 382 SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), 383 }, 384 { 385 .name = "dmic01", 386 .id = 1, 387 .ignore_suspend = 1, 388 .dpcm_capture = 1, 389 .no_pcm = 1, 390 SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), 391 }, 392 { 393 .name = "dmic16k", 394 .id = 2, 395 .ignore_suspend = 1, 396 .dpcm_capture = 1, 397 .no_pcm = 1, 398 SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), 399 }, 400 { 401 .name = "iDisp1", 402 .id = 3, 403 .init = hdmi_init, 404 .dpcm_playback = 1, 405 .no_pcm = 1, 406 SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), 407 }, 408 { 409 .name = "iDisp2", 410 .id = 4, 411 .init = hdmi_init, 412 .dpcm_playback = 1, 413 .no_pcm = 1, 414 SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), 415 }, 416 { 417 .name = "iDisp3", 418 .id = 5, 419 .init = hdmi_init, 420 .dpcm_playback = 1, 421 .no_pcm = 1, 422 SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), 423 }, 424 { 425 .name = "iDisp4", 426 .id = 6, 427 .init = hdmi_init, 428 .dpcm_playback = 1, 429 .no_pcm = 1, 430 SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform), 431 }, 432 { 433 .name = "SSP1-Codec", 434 .id = 7, 435 .no_pcm = 1, 436 .dpcm_playback = 1, 437 /* feedback stream or firmware-generated echo reference */ 438 .dpcm_capture = 1, 439 SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform), 440 }, 441 { 442 .name = "SSP2-BT", 443 .id = 8, 444 .no_pcm = 1, 445 .dpcm_playback = 1, 446 .dpcm_capture = 1, 447 SND_SOC_DAILINK_REG(ssp2_pin, dummy_codec, platform), 448 }, 449 }; 450 451 static struct snd_soc_card card_da7219 = { 452 .name = "da7219", /* the sof- prefix is added by the core */ 453 .owner = THIS_MODULE, 454 .controls = controls, 455 .num_controls = ARRAY_SIZE(controls), 456 .dapm_widgets = widgets, 457 .num_dapm_widgets = ARRAY_SIZE(widgets), 458 .dapm_routes = audio_map, 459 .num_dapm_routes = ARRAY_SIZE(audio_map), 460 .fully_routed = true, 461 .late_probe = card_late_probe, 462 }; 463 464 static int audio_probe(struct platform_device *pdev) 465 { 466 struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; 467 struct snd_soc_dai_link *dai_links; 468 struct card_private *ctx; 469 unsigned long board_quirk = 0; 470 int ret, amp_idx; 471 472 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 473 if (!ctx) 474 return -ENOMEM; 475 476 if (pdev->id_entry && pdev->id_entry->driver_data) 477 board_quirk = (unsigned long)pdev->id_entry->driver_data; 478 479 ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); 480 ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); 481 482 if (board_quirk & SOF_DA7219_JSL_BOARD) { 483 /* backward-compatible with existing devices */ 484 switch (ctx->amp_type) { 485 case CODEC_MAX98360A: 486 card_da7219.name = devm_kstrdup(&pdev->dev, 487 "da7219max98360a", 488 GFP_KERNEL); 489 break; 490 case CODEC_MAX98373: 491 card_da7219.name = devm_kstrdup(&pdev->dev, "da7219max", 492 GFP_KERNEL); 493 break; 494 default: 495 break; 496 } 497 498 dai_links = jsl_dais; 499 amp_idx = 0; 500 501 card_da7219.num_links = ARRAY_SIZE(jsl_dais); 502 } else { 503 dai_links = adl_dais; 504 amp_idx = 7; 505 506 card_da7219.num_links = ARRAY_SIZE(adl_dais); 507 } 508 509 dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk); 510 511 /* speaker amp */ 512 switch (ctx->amp_type) { 513 case CODEC_MAX98360A: 514 max_98360a_dai_link(&dai_links[amp_idx]); 515 break; 516 case CODEC_MAX98373: 517 dai_links[amp_idx].codecs = max_98373_components; 518 dai_links[amp_idx].num_codecs = ARRAY_SIZE(max_98373_components); 519 dai_links[amp_idx].init = max_98373_spk_codec_init; 520 if (board_quirk & SOF_DA7219_JSL_BOARD) { 521 dai_links[amp_idx].ops = &max98373_ops; /* use local ops */ 522 } else { 523 /* TBD: implement the amp for later platform */ 524 dev_err(&pdev->dev, "max98373 not support yet\n"); 525 return -EINVAL; 526 } 527 528 max_98373_set_codec_conf(&card_da7219); 529 break; 530 default: 531 dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type); 532 return -EINVAL; 533 } 534 535 card_da7219.dai_link = dai_links; 536 537 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 538 539 card_da7219.dev = &pdev->dev; 540 541 ret = snd_soc_fixup_dai_links_platform_name(&card_da7219, 542 mach->mach_params.platform); 543 if (ret) 544 return ret; 545 546 snd_soc_card_set_drvdata(&card_da7219, ctx); 547 548 return devm_snd_soc_register_card(&pdev->dev, &card_da7219); 549 } 550 551 static const struct platform_device_id board_ids[] = { 552 { 553 .name = "jsl_mx98373_da7219", 554 .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD), 555 }, 556 { 557 .name = "jsl_mx98360_da7219", 558 .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD), 559 }, 560 { 561 .name = "adl_mx98360_da7219", 562 /* no quirk needed for this board */ 563 }, 564 { } 565 }; 566 MODULE_DEVICE_TABLE(platform, board_ids); 567 568 static struct platform_driver audio = { 569 .probe = audio_probe, 570 .driver = { 571 .name = "sof_da7219", 572 .pm = &snd_soc_pm_ops, 573 }, 574 .id_table = board_ids, 575 }; 576 module_platform_driver(audio) 577 578 /* Module information */ 579 MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver for Dialog codec"); 580 MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); 581 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 582 MODULE_LICENSE("GPL v2"); 583 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 584 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 585 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); 586