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 221 return 0; 222 } 223 224 static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link, 225 int be_id, enum sof_dmic_be_type be_type) 226 { 227 struct snd_soc_dai_link_component *cpus; 228 229 /* cpus */ 230 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 231 GFP_KERNEL); 232 if (!cpus) 233 return -ENOMEM; 234 235 switch (be_type) { 236 case SOF_DMIC_01: 237 dev_dbg(dev, "link %d: dmic01\n", be_id); 238 239 link->name = "dmic01"; 240 cpus->dai_name = "DMIC01 Pin"; 241 break; 242 case SOF_DMIC_16K: 243 dev_dbg(dev, "link %d: dmic16k\n", be_id); 244 245 link->name = "dmic16k"; 246 cpus->dai_name = "DMIC16k Pin"; 247 break; 248 default: 249 dev_err(dev, "invalid be type %d\n", be_type); 250 return -EINVAL; 251 } 252 253 link->cpus = cpus; 254 link->num_cpus = 1; 255 256 /* codecs */ 257 link->codecs = dmic_component; 258 link->num_codecs = ARRAY_SIZE(dmic_component); 259 260 /* platforms */ 261 link->platforms = platform_component; 262 link->num_platforms = ARRAY_SIZE(platform_component); 263 264 link->id = be_id; 265 if (be_type == SOF_DMIC_01) 266 link->init = dmic_init; 267 link->ignore_suspend = 1; 268 link->no_pcm = 1; 269 link->capture_only = 1; 270 271 return 0; 272 } 273 274 static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link, 275 int be_id, int hdmi_id, bool idisp_codec) 276 { 277 struct snd_soc_dai_link_component *cpus, *codecs; 278 279 dev_dbg(dev, "link %d: idisp hdmi %d, idisp codec %d\n", be_id, hdmi_id, 280 idisp_codec); 281 282 /* link name */ 283 link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id); 284 if (!link->name) 285 return -ENOMEM; 286 287 /* cpus */ 288 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 289 GFP_KERNEL); 290 if (!cpus) 291 return -ENOMEM; 292 293 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id); 294 if (!cpus->dai_name) 295 return -ENOMEM; 296 297 link->cpus = cpus; 298 link->num_cpus = 1; 299 300 /* codecs */ 301 if (idisp_codec) { 302 codecs = devm_kzalloc(dev, 303 sizeof(struct snd_soc_dai_link_component), 304 GFP_KERNEL); 305 if (!codecs) 306 return -ENOMEM; 307 308 codecs->name = "ehdaudio0D2"; 309 codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, 310 "intel-hdmi-hifi%d", hdmi_id); 311 if (!codecs->dai_name) 312 return -ENOMEM; 313 314 link->codecs = codecs; 315 } else { 316 link->codecs = &snd_soc_dummy_dlc; 317 } 318 link->num_codecs = 1; 319 320 /* platforms */ 321 link->platforms = platform_component; 322 link->num_platforms = ARRAY_SIZE(platform_component); 323 324 link->id = be_id; 325 link->init = (hdmi_id == 1) ? hdmi_init : NULL; 326 link->no_pcm = 1; 327 link->playback_only = 1; 328 329 return 0; 330 } 331 332 static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link, 333 int be_id, enum snd_soc_acpi_intel_codec amp_type, 334 int ssp_amp) 335 { 336 struct snd_soc_dai_link_component *cpus; 337 338 dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id, 339 snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp); 340 341 /* link name */ 342 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp); 343 if (!link->name) 344 return -ENOMEM; 345 346 /* cpus */ 347 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 348 GFP_KERNEL); 349 if (!cpus) 350 return -ENOMEM; 351 352 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_amp); 353 if (!cpus->dai_name) 354 return -ENOMEM; 355 356 link->cpus = cpus; 357 link->num_cpus = 1; 358 359 /* codecs - caller to handle */ 360 361 /* platforms */ 362 /* feedback stream or firmware-generated echo reference */ 363 link->platforms = platform_component; 364 link->num_platforms = ARRAY_SIZE(platform_component); 365 366 link->id = be_id; 367 link->no_pcm = 1; 368 369 return 0; 370 } 371 372 static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link, 373 int be_id, int ssp_bt) 374 { 375 struct snd_soc_dai_link_component *cpus; 376 377 dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt); 378 379 /* link name */ 380 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt); 381 if (!link->name) 382 return -ENOMEM; 383 384 /* cpus */ 385 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 386 GFP_KERNEL); 387 if (!cpus) 388 return -ENOMEM; 389 390 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt); 391 if (!cpus->dai_name) 392 return -ENOMEM; 393 394 link->cpus = cpus; 395 link->num_cpus = 1; 396 397 /* codecs */ 398 link->codecs = &snd_soc_dummy_dlc; 399 link->num_codecs = 1; 400 401 /* platforms */ 402 link->platforms = platform_component; 403 link->num_platforms = ARRAY_SIZE(platform_component); 404 405 link->id = be_id; 406 link->no_pcm = 1; 407 408 return 0; 409 } 410 411 static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link, 412 int be_id, int ssp_hdmi) 413 { 414 struct snd_soc_dai_link_component *cpus; 415 416 dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi); 417 418 /* link name */ 419 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi); 420 if (!link->name) 421 return -ENOMEM; 422 423 /* cpus */ 424 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 425 GFP_KERNEL); 426 if (!cpus) 427 return -ENOMEM; 428 429 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi); 430 if (!cpus->dai_name) 431 return -ENOMEM; 432 433 link->cpus = cpus; 434 link->num_cpus = 1; 435 436 /* codecs */ 437 link->codecs = &snd_soc_dummy_dlc; 438 link->num_codecs = 1; 439 440 /* platforms */ 441 link->platforms = platform_component; 442 link->num_platforms = ARRAY_SIZE(platform_component); 443 444 link->id = be_id; 445 link->no_pcm = 1; 446 link->capture_only = 1; 447 448 return 0; 449 } 450 451 static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link, 452 int be_id, enum sof_hda_be_type be_type) 453 { 454 switch (be_type) { 455 case SOF_HDA_ANALOG: 456 dev_dbg(dev, "link %d: hda analog\n", be_id); 457 458 link->name = "Analog Playback and Capture"; 459 460 /* cpus */ 461 link->cpus = hda_analog_cpus; 462 link->num_cpus = ARRAY_SIZE(hda_analog_cpus); 463 464 /* codecs */ 465 link->codecs = hda_analog_codecs; 466 link->num_codecs = ARRAY_SIZE(hda_analog_codecs); 467 break; 468 case SOF_HDA_DIGITAL: 469 dev_dbg(dev, "link %d: hda digital\n", be_id); 470 471 link->name = "Digital Playback and Capture"; 472 473 /* cpus */ 474 link->cpus = hda_digital_cpus; 475 link->num_cpus = ARRAY_SIZE(hda_digital_cpus); 476 477 /* codecs */ 478 link->codecs = hda_digital_codecs; 479 link->num_codecs = ARRAY_SIZE(hda_digital_codecs); 480 break; 481 default: 482 dev_err(dev, "invalid be type %d\n", be_type); 483 return -EINVAL; 484 } 485 486 /* platforms */ 487 link->platforms = platform_component; 488 link->num_platforms = ARRAY_SIZE(platform_component); 489 490 link->id = be_id; 491 if (be_type == SOF_HDA_ANALOG) 492 link->init = hda_init; 493 link->no_pcm = 1; 494 495 return 0; 496 } 497 498 static int calculate_num_links(struct sof_card_private *ctx) 499 { 500 int num_links = 0; 501 502 /* headphone codec */ 503 if (ctx->codec_type != CODEC_NONE) 504 num_links++; 505 506 /* dmic01 and dmic16k */ 507 if (ctx->dmic_be_num > 0) 508 num_links++; 509 510 if (ctx->dmic_be_num > 1) 511 num_links++; 512 513 /* idisp HDMI */ 514 num_links += ctx->hdmi_num; 515 516 /* speaker amp */ 517 if (ctx->amp_type != CODEC_NONE) 518 num_links++; 519 520 /* BT audio offload */ 521 if (ctx->bt_offload_present) 522 num_links++; 523 524 /* HDMI-In */ 525 num_links += hweight32(ctx->ssp_mask_hdmi_in); 526 527 /* HDA external codec */ 528 if (ctx->hda_codec_present) 529 num_links += 2; 530 531 return num_links; 532 } 533 534 int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, 535 struct sof_card_private *ctx) 536 { 537 struct snd_soc_dai_link *links; 538 int num_links; 539 int i; 540 int idx = 0; 541 int ret; 542 int ssp_hdmi_in = 0; 543 unsigned long link_order, link; 544 unsigned long link_ids, be_id; 545 546 num_links = calculate_num_links(ctx); 547 548 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), 549 GFP_KERNEL); 550 if (!links) 551 return -ENOMEM; 552 553 if (ctx->link_order_overwrite) 554 link_order = ctx->link_order_overwrite; 555 else 556 link_order = DEFAULT_LINK_ORDER; 557 558 if (ctx->link_id_overwrite) 559 link_ids = ctx->link_id_overwrite; 560 else 561 link_ids = 0; 562 563 dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n", 564 link_order, link_ids); 565 566 while (link_order) { 567 link = link_order & SOF_LINK_ORDER_MASK; 568 link_order >>= SOF_LINK_ORDER_SHIFT; 569 570 if (ctx->link_id_overwrite) { 571 be_id = link_ids & SOF_LINK_IDS_MASK; 572 link_ids >>= SOF_LINK_IDS_SHIFT; 573 } else { 574 /* use array index as link id */ 575 be_id = idx; 576 } 577 578 switch (link) { 579 case SOF_LINK_CODEC: 580 /* headphone codec */ 581 if (ctx->codec_type == CODEC_NONE) 582 continue; 583 584 ret = set_ssp_codec_link(dev, &links[idx], be_id, 585 ctx->codec_type, ctx->ssp_codec); 586 if (ret) { 587 dev_err(dev, "fail to set codec link, ret %d\n", 588 ret); 589 return ret; 590 } 591 592 ctx->codec_link = &links[idx]; 593 idx++; 594 break; 595 case SOF_LINK_DMIC01: 596 /* dmic01 */ 597 if (ctx->dmic_be_num == 0) 598 continue; 599 600 /* at least we have dmic01 */ 601 ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01); 602 if (ret) { 603 dev_err(dev, "fail to set dmic01 link, ret %d\n", 604 ret); 605 return ret; 606 } 607 608 idx++; 609 break; 610 case SOF_LINK_DMIC16K: 611 /* dmic16k */ 612 if (ctx->dmic_be_num <= 1) 613 continue; 614 615 /* set up 2 BE links at most */ 616 ret = set_dmic_link(dev, &links[idx], be_id, 617 SOF_DMIC_16K); 618 if (ret) { 619 dev_err(dev, "fail to set dmic16k link, ret %d\n", 620 ret); 621 return ret; 622 } 623 624 idx++; 625 break; 626 case SOF_LINK_IDISP_HDMI: 627 /* idisp HDMI */ 628 for (i = 1; i <= ctx->hdmi_num; i++) { 629 ret = set_idisp_hdmi_link(dev, &links[idx], 630 be_id, i, 631 ctx->hdmi.idisp_codec); 632 if (ret) { 633 dev_err(dev, "fail to set hdmi link, ret %d\n", 634 ret); 635 return ret; 636 } 637 638 idx++; 639 be_id++; 640 } 641 break; 642 case SOF_LINK_AMP: 643 /* speaker amp */ 644 if (ctx->amp_type == CODEC_NONE) 645 continue; 646 647 ret = set_ssp_amp_link(dev, &links[idx], be_id, 648 ctx->amp_type, ctx->ssp_amp); 649 if (ret) { 650 dev_err(dev, "fail to set amp link, ret %d\n", 651 ret); 652 return ret; 653 } 654 655 ctx->amp_link = &links[idx]; 656 idx++; 657 break; 658 case SOF_LINK_BT_OFFLOAD: 659 /* BT audio offload */ 660 if (!ctx->bt_offload_present) 661 continue; 662 663 ret = set_bt_offload_link(dev, &links[idx], be_id, 664 ctx->ssp_bt); 665 if (ret) { 666 dev_err(dev, "fail to set bt link, ret %d\n", 667 ret); 668 return ret; 669 } 670 671 idx++; 672 break; 673 case SOF_LINK_HDMI_IN: 674 /* HDMI-In */ 675 for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) { 676 ret = set_hdmi_in_link(dev, &links[idx], be_id, 677 ssp_hdmi_in); 678 if (ret) { 679 dev_err(dev, "fail to set hdmi-in link, ret %d\n", 680 ret); 681 return ret; 682 } 683 684 idx++; 685 be_id++; 686 } 687 break; 688 case SOF_LINK_HDA: 689 /* HDA external codec */ 690 if (!ctx->hda_codec_present) 691 continue; 692 693 ret = set_hda_codec_link(dev, &links[idx], be_id, 694 SOF_HDA_ANALOG); 695 if (ret) { 696 dev_err(dev, "fail to set hda analog link, ret %d\n", 697 ret); 698 return ret; 699 } 700 701 idx++; 702 be_id++; 703 704 ret = set_hda_codec_link(dev, &links[idx], be_id, 705 SOF_HDA_DIGITAL); 706 if (ret) { 707 dev_err(dev, "fail to set hda digital link, ret %d\n", 708 ret); 709 return ret; 710 } 711 712 idx++; 713 break; 714 case SOF_LINK_NONE: 715 /* caught here if it's not used as terminator in macro */ 716 fallthrough; 717 default: 718 dev_err(dev, "invalid link type %ld\n", link); 719 return -EINVAL; 720 } 721 } 722 723 if (idx != num_links) { 724 dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx, 725 num_links); 726 return -EINVAL; 727 } 728 729 card->dai_link = links; 730 card->num_links = num_links; 731 732 return 0; 733 } 734 EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); 735 736 struct sof_card_private * 737 sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) 738 { 739 struct sof_card_private *ctx; 740 741 dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk); 742 743 ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL); 744 if (!ctx) 745 return NULL; 746 747 ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev); 748 ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev); 749 750 ctx->dmic_be_num = 2; 751 ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >> 752 SOF_NUM_IDISP_HDMI_SHIFT; 753 /* default number of HDMI DAI's */ 754 if (!ctx->hdmi_num) 755 ctx->hdmi_num = 3; 756 757 /* port number/mask of peripherals attached to ssp interface */ 758 if (ctx->codec_type != CODEC_NONE) 759 ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >> 760 SOF_SSP_PORT_CODEC_SHIFT; 761 762 if (ctx->amp_type != CODEC_NONE) 763 ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >> 764 SOF_SSP_PORT_AMP_SHIFT; 765 766 if (board_quirk & SOF_BT_OFFLOAD_PRESENT) { 767 ctx->bt_offload_present = true; 768 ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >> 769 SOF_SSP_PORT_BT_OFFLOAD_SHIFT; 770 } 771 772 ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >> 773 SOF_SSP_MASK_HDMI_CAPTURE_SHIFT; 774 775 return ctx; 776 } 777 EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); 778 779 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); 780 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 781 MODULE_LICENSE("GPL"); 782 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 783 MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH); 784