1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2023 Intel Corporation 4 5 #include <sound/soc.h> 6 #include "../common/soc-intel-quirks.h" 7 #include "hda_dsp_common.h" 8 #include "sof_board_helpers.h" 9 10 /* 11 * Intel HDMI DAI Link 12 */ 13 static int hdmi_init(struct snd_soc_pcm_runtime *rtd) 14 { 15 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 16 struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); 17 18 ctx->hdmi.hdmi_comp = dai->component; 19 20 return 0; 21 } 22 23 int sof_intel_board_card_late_probe(struct snd_soc_card *card) 24 { 25 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); 26 27 if (!ctx->hdmi_num) 28 return 0; 29 30 if (!ctx->hdmi.idisp_codec) 31 return 0; 32 33 if (!ctx->hdmi.hdmi_comp) 34 return -EINVAL; 35 36 return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp); 37 } 38 EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS); 39 40 /* 41 * DMIC DAI Link 42 */ 43 static const struct snd_soc_dapm_widget dmic_widgets[] = { 44 SND_SOC_DAPM_MIC("SoC DMIC", NULL), 45 }; 46 47 static const struct snd_soc_dapm_route dmic_routes[] = { 48 {"DMic", NULL, "SoC DMIC"}, 49 }; 50 51 static int dmic_init(struct snd_soc_pcm_runtime *rtd) 52 { 53 struct snd_soc_card *card = rtd->card; 54 int ret; 55 56 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, 57 ARRAY_SIZE(dmic_widgets)); 58 if (ret) { 59 dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret); 60 return ret; 61 } 62 63 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_routes, 64 ARRAY_SIZE(dmic_routes)); 65 if (ret) { 66 dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret); 67 return ret; 68 } 69 70 return 0; 71 } 72 73 /* 74 * HDA External Codec DAI Link 75 */ 76 static const struct snd_soc_dapm_widget hda_widgets[] = { 77 SND_SOC_DAPM_MIC("Analog In", NULL), 78 SND_SOC_DAPM_MIC("Digital In", NULL), 79 SND_SOC_DAPM_MIC("Alt Analog In", NULL), 80 81 SND_SOC_DAPM_HP("Analog Out", NULL), 82 SND_SOC_DAPM_SPK("Digital Out", NULL), 83 SND_SOC_DAPM_HP("Alt Analog Out", NULL), 84 }; 85 86 static const struct snd_soc_dapm_route hda_routes[] = { 87 { "Codec Input Pin1", NULL, "Analog In" }, 88 { "Codec Input Pin2", NULL, "Digital In" }, 89 { "Codec Input Pin3", NULL, "Alt Analog In" }, 90 91 { "Analog Out", NULL, "Codec Output Pin1" }, 92 { "Digital Out", NULL, "Codec Output Pin2" }, 93 { "Alt Analog Out", NULL, "Codec Output Pin3" }, 94 95 /* CODEC BE connections */ 96 { "codec0_in", NULL, "Analog CPU Capture" }, 97 { "Analog CPU Capture", NULL, "Analog Codec Capture" }, 98 { "codec1_in", NULL, "Digital CPU Capture" }, 99 { "Digital CPU Capture", NULL, "Digital Codec Capture" }, 100 { "codec2_in", NULL, "Alt Analog CPU Capture" }, 101 { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" }, 102 103 { "Analog Codec Playback", NULL, "Analog CPU Playback" }, 104 { "Analog CPU Playback", NULL, "codec0_out" }, 105 { "Digital Codec Playback", NULL, "Digital CPU Playback" }, 106 { "Digital CPU Playback", NULL, "codec1_out" }, 107 { "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" }, 108 { "Alt Analog CPU Playback", NULL, "codec2_out" }, 109 }; 110 111 static int hda_init(struct snd_soc_pcm_runtime *rtd) 112 { 113 struct snd_soc_card *card = rtd->card; 114 int ret; 115 116 ret = snd_soc_dapm_new_controls(&card->dapm, hda_widgets, 117 ARRAY_SIZE(hda_widgets)); 118 if (ret) { 119 dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret); 120 return ret; 121 } 122 123 ret = snd_soc_dapm_add_routes(&card->dapm, hda_routes, 124 ARRAY_SIZE(hda_routes)); 125 if (ret) 126 dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret); 127 128 return ret; 129 } 130 131 /* 132 * DAI Link Helpers 133 */ 134 135 enum sof_dmic_be_type { 136 SOF_DMIC_01, 137 SOF_DMIC_16K, 138 }; 139 140 enum sof_hda_be_type { 141 SOF_HDA_ANALOG, 142 SOF_HDA_DIGITAL, 143 }; 144 145 /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */ 146 #define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \ 147 SOF_LINK_DMIC01, \ 148 SOF_LINK_DMIC16K, \ 149 SOF_LINK_IDISP_HDMI, \ 150 SOF_LINK_AMP, \ 151 SOF_LINK_BT_OFFLOAD, \ 152 SOF_LINK_HDMI_IN) 153 154 static struct snd_soc_dai_link_component dmic_component[] = { 155 { 156 .name = "dmic-codec", 157 .dai_name = "dmic-hifi", 158 } 159 }; 160 161 SND_SOC_DAILINK_DEF(hda_analog_cpus, 162 DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI"))); 163 SND_SOC_DAILINK_DEF(hda_analog_codecs, 164 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI"))); 165 166 SND_SOC_DAILINK_DEF(hda_digital_cpus, 167 DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI"))); 168 SND_SOC_DAILINK_DEF(hda_digital_codecs, 169 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI"))); 170 171 static struct snd_soc_dai_link_component platform_component[] = { 172 { 173 /* name might be overridden during probe */ 174 .name = "0000:00:1f.3" 175 } 176 }; 177 178 static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link, 179 int be_id, enum snd_soc_acpi_intel_codec codec_type, 180 int ssp_codec) 181 { 182 struct snd_soc_dai_link_component *cpus; 183 184 dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id, 185 snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec); 186 187 /* link name */ 188 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec); 189 if (!link->name) 190 return -ENOMEM; 191 192 /* cpus */ 193 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 194 GFP_KERNEL); 195 if (!cpus) 196 return -ENOMEM; 197 198 if (soc_intel_is_byt() || soc_intel_is_cht()) { 199 /* backward-compatibility for BYT/CHT boards */ 200 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port", 201 ssp_codec); 202 } else { 203 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", 204 ssp_codec); 205 } 206 if (!cpus->dai_name) 207 return -ENOMEM; 208 209 link->cpus = cpus; 210 link->num_cpus = 1; 211 212 /* codecs - caller to handle */ 213 214 /* platforms */ 215 link->platforms = platform_component; 216 link->num_platforms = ARRAY_SIZE(platform_component); 217 218 link->id = be_id; 219 link->no_pcm = 1; 220 link->dpcm_capture = 1; 221 link->dpcm_playback = 1; 222 223 return 0; 224 } 225 226 static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link, 227 int be_id, enum sof_dmic_be_type be_type) 228 { 229 struct snd_soc_dai_link_component *cpus; 230 231 /* cpus */ 232 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 233 GFP_KERNEL); 234 if (!cpus) 235 return -ENOMEM; 236 237 switch (be_type) { 238 case SOF_DMIC_01: 239 dev_dbg(dev, "link %d: dmic01\n", be_id); 240 241 link->name = "dmic01"; 242 cpus->dai_name = "DMIC01 Pin"; 243 break; 244 case SOF_DMIC_16K: 245 dev_dbg(dev, "link %d: dmic16k\n", be_id); 246 247 link->name = "dmic16k"; 248 cpus->dai_name = "DMIC16k Pin"; 249 break; 250 default: 251 dev_err(dev, "invalid be type %d\n", be_type); 252 return -EINVAL; 253 } 254 255 link->cpus = cpus; 256 link->num_cpus = 1; 257 258 /* codecs */ 259 link->codecs = dmic_component; 260 link->num_codecs = ARRAY_SIZE(dmic_component); 261 262 /* platforms */ 263 link->platforms = platform_component; 264 link->num_platforms = ARRAY_SIZE(platform_component); 265 266 link->id = be_id; 267 if (be_type == SOF_DMIC_01) 268 link->init = dmic_init; 269 link->ignore_suspend = 1; 270 link->no_pcm = 1; 271 link->dpcm_capture = 1; 272 273 return 0; 274 } 275 276 static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link, 277 int be_id, int hdmi_id, bool idisp_codec) 278 { 279 struct snd_soc_dai_link_component *cpus, *codecs; 280 281 dev_dbg(dev, "link %d: idisp hdmi %d, idisp codec %d\n", be_id, hdmi_id, 282 idisp_codec); 283 284 /* link name */ 285 link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id); 286 if (!link->name) 287 return -ENOMEM; 288 289 /* cpus */ 290 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 291 GFP_KERNEL); 292 if (!cpus) 293 return -ENOMEM; 294 295 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id); 296 if (!cpus->dai_name) 297 return -ENOMEM; 298 299 link->cpus = cpus; 300 link->num_cpus = 1; 301 302 /* codecs */ 303 if (idisp_codec) { 304 codecs = devm_kzalloc(dev, 305 sizeof(struct snd_soc_dai_link_component), 306 GFP_KERNEL); 307 if (!codecs) 308 return -ENOMEM; 309 310 codecs->name = "ehdaudio0D2"; 311 codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, 312 "intel-hdmi-hifi%d", hdmi_id); 313 if (!codecs->dai_name) 314 return -ENOMEM; 315 316 link->codecs = codecs; 317 } else { 318 link->codecs = &snd_soc_dummy_dlc; 319 } 320 link->num_codecs = 1; 321 322 /* platforms */ 323 link->platforms = platform_component; 324 link->num_platforms = ARRAY_SIZE(platform_component); 325 326 link->id = be_id; 327 link->init = (hdmi_id == 1) ? hdmi_init : NULL; 328 link->no_pcm = 1; 329 link->dpcm_playback = 1; 330 331 return 0; 332 } 333 334 static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link, 335 int be_id, enum snd_soc_acpi_intel_codec amp_type, 336 int ssp_amp) 337 { 338 struct snd_soc_dai_link_component *cpus; 339 340 dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id, 341 snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp); 342 343 /* link name */ 344 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp); 345 if (!link->name) 346 return -ENOMEM; 347 348 /* cpus */ 349 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 350 GFP_KERNEL); 351 if (!cpus) 352 return -ENOMEM; 353 354 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_amp); 355 if (!cpus->dai_name) 356 return -ENOMEM; 357 358 link->cpus = cpus; 359 link->num_cpus = 1; 360 361 /* codecs - caller to handle */ 362 363 /* platforms */ 364 link->platforms = platform_component; 365 link->num_platforms = ARRAY_SIZE(platform_component); 366 367 link->id = be_id; 368 link->no_pcm = 1; 369 link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */ 370 link->dpcm_playback = 1; 371 372 return 0; 373 } 374 375 static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link, 376 int be_id, int ssp_bt) 377 { 378 struct snd_soc_dai_link_component *cpus; 379 380 dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt); 381 382 /* link name */ 383 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt); 384 if (!link->name) 385 return -ENOMEM; 386 387 /* cpus */ 388 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 389 GFP_KERNEL); 390 if (!cpus) 391 return -ENOMEM; 392 393 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt); 394 if (!cpus->dai_name) 395 return -ENOMEM; 396 397 link->cpus = cpus; 398 link->num_cpus = 1; 399 400 /* codecs */ 401 link->codecs = &snd_soc_dummy_dlc; 402 link->num_codecs = 1; 403 404 /* platforms */ 405 link->platforms = platform_component; 406 link->num_platforms = ARRAY_SIZE(platform_component); 407 408 link->id = be_id; 409 link->no_pcm = 1; 410 link->dpcm_capture = 1; 411 link->dpcm_playback = 1; 412 413 return 0; 414 } 415 416 static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link, 417 int be_id, int ssp_hdmi) 418 { 419 struct snd_soc_dai_link_component *cpus; 420 421 dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi); 422 423 /* link name */ 424 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi); 425 if (!link->name) 426 return -ENOMEM; 427 428 /* cpus */ 429 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 430 GFP_KERNEL); 431 if (!cpus) 432 return -ENOMEM; 433 434 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi); 435 if (!cpus->dai_name) 436 return -ENOMEM; 437 438 link->cpus = cpus; 439 link->num_cpus = 1; 440 441 /* codecs */ 442 link->codecs = &snd_soc_dummy_dlc; 443 link->num_codecs = 1; 444 445 /* platforms */ 446 link->platforms = platform_component; 447 link->num_platforms = ARRAY_SIZE(platform_component); 448 449 link->id = be_id; 450 link->no_pcm = 1; 451 link->dpcm_capture = 1; 452 453 return 0; 454 } 455 456 static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link, 457 int be_id, enum sof_hda_be_type be_type) 458 { 459 switch (be_type) { 460 case SOF_HDA_ANALOG: 461 dev_dbg(dev, "link %d: hda analog\n", be_id); 462 463 link->name = "Analog Playback and Capture"; 464 465 /* cpus */ 466 link->cpus = hda_analog_cpus; 467 link->num_cpus = ARRAY_SIZE(hda_analog_cpus); 468 469 /* codecs */ 470 link->codecs = hda_analog_codecs; 471 link->num_codecs = ARRAY_SIZE(hda_analog_codecs); 472 break; 473 case SOF_HDA_DIGITAL: 474 dev_dbg(dev, "link %d: hda digital\n", be_id); 475 476 link->name = "Digital Playback and Capture"; 477 478 /* cpus */ 479 link->cpus = hda_digital_cpus; 480 link->num_cpus = ARRAY_SIZE(hda_digital_cpus); 481 482 /* codecs */ 483 link->codecs = hda_digital_codecs; 484 link->num_codecs = ARRAY_SIZE(hda_digital_codecs); 485 break; 486 default: 487 dev_err(dev, "invalid be type %d\n", be_type); 488 return -EINVAL; 489 } 490 491 /* platforms */ 492 link->platforms = platform_component; 493 link->num_platforms = ARRAY_SIZE(platform_component); 494 495 link->id = be_id; 496 if (be_type == SOF_HDA_ANALOG) 497 link->init = hda_init; 498 link->no_pcm = 1; 499 link->dpcm_capture = 1; 500 link->dpcm_playback = 1; 501 502 return 0; 503 } 504 505 static int calculate_num_links(struct sof_card_private *ctx) 506 { 507 int num_links = 0; 508 509 /* headphone codec */ 510 if (ctx->codec_type != CODEC_NONE) 511 num_links++; 512 513 /* dmic01 and dmic16k */ 514 if (ctx->dmic_be_num > 0) 515 num_links++; 516 517 if (ctx->dmic_be_num > 1) 518 num_links++; 519 520 /* idisp HDMI */ 521 num_links += ctx->hdmi_num; 522 523 /* speaker amp */ 524 if (ctx->amp_type != CODEC_NONE) 525 num_links++; 526 527 /* BT audio offload */ 528 if (ctx->bt_offload_present) 529 num_links++; 530 531 /* HDMI-In */ 532 num_links += hweight32(ctx->ssp_mask_hdmi_in); 533 534 /* HDA external codec */ 535 if (ctx->hda_codec_present) 536 num_links += 2; 537 538 return num_links; 539 } 540 541 int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, 542 struct sof_card_private *ctx) 543 { 544 struct snd_soc_dai_link *links; 545 int num_links; 546 int i; 547 int idx = 0; 548 int ret; 549 int ssp_hdmi_in = 0; 550 unsigned long link_order, link; 551 unsigned long link_ids, be_id; 552 553 num_links = calculate_num_links(ctx); 554 555 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), 556 GFP_KERNEL); 557 if (!links) 558 return -ENOMEM; 559 560 if (ctx->link_order_overwrite) 561 link_order = ctx->link_order_overwrite; 562 else 563 link_order = DEFAULT_LINK_ORDER; 564 565 if (ctx->link_id_overwrite) 566 link_ids = ctx->link_id_overwrite; 567 else 568 link_ids = 0; 569 570 dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n", 571 link_order, link_ids); 572 573 while (link_order) { 574 link = link_order & SOF_LINK_ORDER_MASK; 575 link_order >>= SOF_LINK_ORDER_SHIFT; 576 577 if (ctx->link_id_overwrite) { 578 be_id = link_ids & SOF_LINK_IDS_MASK; 579 link_ids >>= SOF_LINK_IDS_SHIFT; 580 } else { 581 /* use array index as link id */ 582 be_id = idx; 583 } 584 585 switch (link) { 586 case SOF_LINK_CODEC: 587 /* headphone codec */ 588 if (ctx->codec_type == CODEC_NONE) 589 continue; 590 591 ret = set_ssp_codec_link(dev, &links[idx], be_id, 592 ctx->codec_type, ctx->ssp_codec); 593 if (ret) { 594 dev_err(dev, "fail to set codec link, ret %d\n", 595 ret); 596 return ret; 597 } 598 599 ctx->codec_link = &links[idx]; 600 idx++; 601 break; 602 case SOF_LINK_DMIC01: 603 /* dmic01 */ 604 if (ctx->dmic_be_num == 0) 605 continue; 606 607 /* at least we have dmic01 */ 608 ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01); 609 if (ret) { 610 dev_err(dev, "fail to set dmic01 link, ret %d\n", 611 ret); 612 return ret; 613 } 614 615 idx++; 616 break; 617 case SOF_LINK_DMIC16K: 618 /* dmic16k */ 619 if (ctx->dmic_be_num <= 1) 620 continue; 621 622 /* set up 2 BE links at most */ 623 ret = set_dmic_link(dev, &links[idx], be_id, 624 SOF_DMIC_16K); 625 if (ret) { 626 dev_err(dev, "fail to set dmic16k link, ret %d\n", 627 ret); 628 return ret; 629 } 630 631 idx++; 632 break; 633 case SOF_LINK_IDISP_HDMI: 634 /* idisp HDMI */ 635 for (i = 1; i <= ctx->hdmi_num; i++) { 636 ret = set_idisp_hdmi_link(dev, &links[idx], 637 be_id, i, 638 ctx->hdmi.idisp_codec); 639 if (ret) { 640 dev_err(dev, "fail to set hdmi link, ret %d\n", 641 ret); 642 return ret; 643 } 644 645 idx++; 646 be_id++; 647 } 648 break; 649 case SOF_LINK_AMP: 650 /* speaker amp */ 651 if (ctx->amp_type == CODEC_NONE) 652 continue; 653 654 ret = set_ssp_amp_link(dev, &links[idx], be_id, 655 ctx->amp_type, ctx->ssp_amp); 656 if (ret) { 657 dev_err(dev, "fail to set amp link, ret %d\n", 658 ret); 659 return ret; 660 } 661 662 ctx->amp_link = &links[idx]; 663 idx++; 664 break; 665 case SOF_LINK_BT_OFFLOAD: 666 /* BT audio offload */ 667 if (!ctx->bt_offload_present) 668 continue; 669 670 ret = set_bt_offload_link(dev, &links[idx], be_id, 671 ctx->ssp_bt); 672 if (ret) { 673 dev_err(dev, "fail to set bt link, ret %d\n", 674 ret); 675 return ret; 676 } 677 678 idx++; 679 break; 680 case SOF_LINK_HDMI_IN: 681 /* HDMI-In */ 682 for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) { 683 ret = set_hdmi_in_link(dev, &links[idx], be_id, 684 ssp_hdmi_in); 685 if (ret) { 686 dev_err(dev, "fail to set hdmi-in link, ret %d\n", 687 ret); 688 return ret; 689 } 690 691 idx++; 692 be_id++; 693 } 694 break; 695 case SOF_LINK_HDA: 696 /* HDA external codec */ 697 if (!ctx->hda_codec_present) 698 continue; 699 700 ret = set_hda_codec_link(dev, &links[idx], be_id, 701 SOF_HDA_ANALOG); 702 if (ret) { 703 dev_err(dev, "fail to set hda analog link, ret %d\n", 704 ret); 705 return ret; 706 } 707 708 idx++; 709 be_id++; 710 711 ret = set_hda_codec_link(dev, &links[idx], be_id, 712 SOF_HDA_DIGITAL); 713 if (ret) { 714 dev_err(dev, "fail to set hda digital link, ret %d\n", 715 ret); 716 return ret; 717 } 718 719 idx++; 720 break; 721 case SOF_LINK_NONE: 722 /* caught here if it's not used as terminator in macro */ 723 fallthrough; 724 default: 725 dev_err(dev, "invalid link type %ld\n", link); 726 return -EINVAL; 727 } 728 } 729 730 if (idx != num_links) { 731 dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx, 732 num_links); 733 return -EINVAL; 734 } 735 736 card->dai_link = links; 737 card->num_links = num_links; 738 739 return 0; 740 } 741 EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); 742 743 struct sof_card_private * 744 sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) 745 { 746 struct sof_card_private *ctx; 747 748 dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk); 749 750 ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL); 751 if (!ctx) 752 return NULL; 753 754 ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev); 755 ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev); 756 757 ctx->dmic_be_num = 2; 758 ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >> 759 SOF_NUM_IDISP_HDMI_SHIFT; 760 /* default number of HDMI DAI's */ 761 if (!ctx->hdmi_num) 762 ctx->hdmi_num = 3; 763 764 /* port number/mask of peripherals attached to ssp interface */ 765 if (ctx->codec_type != CODEC_NONE) 766 ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >> 767 SOF_SSP_PORT_CODEC_SHIFT; 768 769 if (ctx->amp_type != CODEC_NONE) 770 ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >> 771 SOF_SSP_PORT_AMP_SHIFT; 772 773 if (board_quirk & SOF_BT_OFFLOAD_PRESENT) { 774 ctx->bt_offload_present = true; 775 ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >> 776 SOF_SSP_PORT_BT_OFFLOAD_SHIFT; 777 } 778 779 ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >> 780 SOF_SSP_MASK_HDMI_CAPTURE_SHIFT; 781 782 return ctx; 783 } 784 EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); 785 786 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); 787 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 788 MODULE_LICENSE("GPL"); 789 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 790 MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH); 791