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 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); 55 int ret; 56 57 ret = snd_soc_dapm_new_controls(dapm, dmic_widgets, 58 ARRAY_SIZE(dmic_widgets)); 59 if (ret) { 60 dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret); 61 return ret; 62 } 63 64 ret = snd_soc_dapm_add_routes(dapm, dmic_routes, 65 ARRAY_SIZE(dmic_routes)); 66 if (ret) { 67 dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret); 68 return ret; 69 } 70 71 return 0; 72 } 73 74 /* 75 * HDA External Codec DAI Link 76 */ 77 static const struct snd_soc_dapm_widget hda_widgets[] = { 78 SND_SOC_DAPM_MIC("Analog In", NULL), 79 SND_SOC_DAPM_MIC("Digital In", NULL), 80 SND_SOC_DAPM_MIC("Alt Analog In", NULL), 81 82 SND_SOC_DAPM_HP("Analog Out", NULL), 83 SND_SOC_DAPM_SPK("Digital Out", NULL), 84 SND_SOC_DAPM_HP("Alt Analog Out", NULL), 85 }; 86 87 static const struct snd_soc_dapm_route hda_routes[] = { 88 { "Codec Input Pin1", NULL, "Analog In" }, 89 { "Codec Input Pin2", NULL, "Digital In" }, 90 { "Codec Input Pin3", NULL, "Alt Analog In" }, 91 92 { "Analog Out", NULL, "Codec Output Pin1" }, 93 { "Digital Out", NULL, "Codec Output Pin2" }, 94 { "Alt Analog Out", NULL, "Codec Output Pin3" }, 95 96 /* CODEC BE connections */ 97 { "codec0_in", NULL, "Analog CPU Capture" }, 98 { "Analog CPU Capture", NULL, "Analog Codec Capture" }, 99 { "codec1_in", NULL, "Digital CPU Capture" }, 100 { "Digital CPU Capture", NULL, "Digital Codec Capture" }, 101 { "codec2_in", NULL, "Alt Analog CPU Capture" }, 102 { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" }, 103 104 { "Analog Codec Playback", NULL, "Analog CPU Playback" }, 105 { "Analog CPU Playback", NULL, "codec0_out" }, 106 { "Digital Codec Playback", NULL, "Digital CPU Playback" }, 107 { "Digital CPU Playback", NULL, "codec1_out" }, 108 { "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" }, 109 { "Alt Analog CPU Playback", NULL, "codec2_out" }, 110 }; 111 112 static int hda_init(struct snd_soc_pcm_runtime *rtd) 113 { 114 struct snd_soc_card *card = rtd->card; 115 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); 116 int ret; 117 118 ret = snd_soc_dapm_new_controls(dapm, hda_widgets, 119 ARRAY_SIZE(hda_widgets)); 120 if (ret) { 121 dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret); 122 return ret; 123 } 124 125 ret = snd_soc_dapm_add_routes(dapm, hda_routes, 126 ARRAY_SIZE(hda_routes)); 127 if (ret) 128 dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret); 129 130 return ret; 131 } 132 133 /* 134 * DAI Link Helpers 135 */ 136 137 enum sof_dmic_be_type { 138 SOF_DMIC_01, 139 SOF_DMIC_16K, 140 }; 141 142 enum sof_hda_be_type { 143 SOF_HDA_ANALOG, 144 SOF_HDA_DIGITAL, 145 }; 146 147 /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */ 148 #define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \ 149 SOF_LINK_DMIC01, \ 150 SOF_LINK_DMIC16K, \ 151 SOF_LINK_IDISP_HDMI, \ 152 SOF_LINK_AMP, \ 153 SOF_LINK_BT_OFFLOAD, \ 154 SOF_LINK_HDMI_IN) 155 156 static struct snd_soc_dai_link_component dmic_component[] = { 157 { 158 .name = "dmic-codec", 159 .dai_name = "dmic-hifi", 160 } 161 }; 162 163 SND_SOC_DAILINK_DEF(hda_analog_cpus, 164 DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI"))); 165 SND_SOC_DAILINK_DEF(hda_analog_codecs, 166 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI"))); 167 168 SND_SOC_DAILINK_DEF(hda_digital_cpus, 169 DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI"))); 170 SND_SOC_DAILINK_DEF(hda_digital_codecs, 171 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI"))); 172 173 static struct snd_soc_dai_link_component platform_component[] = { 174 { 175 /* name might be overridden during probe */ 176 .name = "0000:00:1f.3" 177 } 178 }; 179 180 static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link, 181 int be_id, enum snd_soc_acpi_intel_codec codec_type, 182 int ssp_codec) 183 { 184 struct snd_soc_dai_link_component *cpus; 185 186 dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id, 187 snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec); 188 189 /* link name */ 190 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec); 191 if (!link->name) 192 return -ENOMEM; 193 194 /* cpus */ 195 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 196 GFP_KERNEL); 197 if (!cpus) 198 return -ENOMEM; 199 200 if (soc_intel_is_byt() || soc_intel_is_cht()) { 201 /* backward-compatibility for BYT/CHT boards */ 202 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port", 203 ssp_codec); 204 } else { 205 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", 206 ssp_codec); 207 } 208 if (!cpus->dai_name) 209 return -ENOMEM; 210 211 link->cpus = cpus; 212 link->num_cpus = 1; 213 214 /* codecs - caller to handle */ 215 216 /* platforms */ 217 link->platforms = platform_component; 218 link->num_platforms = ARRAY_SIZE(platform_component); 219 220 link->id = be_id; 221 link->no_pcm = 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->capture_only = 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->playback_only = 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 /* feedback stream or firmware-generated echo reference */ 365 link->platforms = platform_component; 366 link->num_platforms = ARRAY_SIZE(platform_component); 367 368 link->id = be_id; 369 link->no_pcm = 1; 370 371 return 0; 372 } 373 374 static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link, 375 int be_id, int ssp_bt) 376 { 377 struct snd_soc_dai_link_component *cpus; 378 379 dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt); 380 381 /* link name */ 382 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt); 383 if (!link->name) 384 return -ENOMEM; 385 386 /* cpus */ 387 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 388 GFP_KERNEL); 389 if (!cpus) 390 return -ENOMEM; 391 392 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt); 393 if (!cpus->dai_name) 394 return -ENOMEM; 395 396 link->cpus = cpus; 397 link->num_cpus = 1; 398 399 /* codecs */ 400 link->codecs = &snd_soc_dummy_dlc; 401 link->num_codecs = 1; 402 403 /* platforms */ 404 link->platforms = platform_component; 405 link->num_platforms = ARRAY_SIZE(platform_component); 406 407 link->id = be_id; 408 link->no_pcm = 1; 409 410 return 0; 411 } 412 413 static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link, 414 int be_id, int ssp_hdmi) 415 { 416 struct snd_soc_dai_link_component *cpus; 417 418 dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi); 419 420 /* link name */ 421 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi); 422 if (!link->name) 423 return -ENOMEM; 424 425 /* cpus */ 426 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), 427 GFP_KERNEL); 428 if (!cpus) 429 return -ENOMEM; 430 431 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi); 432 if (!cpus->dai_name) 433 return -ENOMEM; 434 435 link->cpus = cpus; 436 link->num_cpus = 1; 437 438 /* codecs */ 439 link->codecs = &snd_soc_dummy_dlc; 440 link->num_codecs = 1; 441 442 /* platforms */ 443 link->platforms = platform_component; 444 link->num_platforms = ARRAY_SIZE(platform_component); 445 446 link->id = be_id; 447 link->no_pcm = 1; 448 link->capture_only = 1; 449 450 return 0; 451 } 452 453 static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link, 454 int be_id, enum sof_hda_be_type be_type) 455 { 456 switch (be_type) { 457 case SOF_HDA_ANALOG: 458 dev_dbg(dev, "link %d: hda analog\n", be_id); 459 460 link->name = "Analog Playback and Capture"; 461 462 /* cpus */ 463 link->cpus = hda_analog_cpus; 464 link->num_cpus = ARRAY_SIZE(hda_analog_cpus); 465 466 /* codecs */ 467 link->codecs = hda_analog_codecs; 468 link->num_codecs = ARRAY_SIZE(hda_analog_codecs); 469 break; 470 case SOF_HDA_DIGITAL: 471 dev_dbg(dev, "link %d: hda digital\n", be_id); 472 473 link->name = "Digital Playback and Capture"; 474 475 /* cpus */ 476 link->cpus = hda_digital_cpus; 477 link->num_cpus = ARRAY_SIZE(hda_digital_cpus); 478 479 /* codecs */ 480 link->codecs = hda_digital_codecs; 481 link->num_codecs = ARRAY_SIZE(hda_digital_codecs); 482 break; 483 default: 484 dev_err(dev, "invalid be type %d\n", be_type); 485 return -EINVAL; 486 } 487 488 /* platforms */ 489 link->platforms = platform_component; 490 link->num_platforms = ARRAY_SIZE(platform_component); 491 492 link->id = be_id; 493 if (be_type == SOF_HDA_ANALOG) 494 link->init = hda_init; 495 link->no_pcm = 1; 496 497 return 0; 498 } 499 500 static int calculate_num_links(struct sof_card_private *ctx) 501 { 502 int num_links = 0; 503 504 /* headphone codec */ 505 if (ctx->codec_type != CODEC_NONE) 506 num_links++; 507 508 /* dmic01 and dmic16k */ 509 if (ctx->dmic_be_num > 0) 510 num_links++; 511 512 if (ctx->dmic_be_num > 1) 513 num_links++; 514 515 /* idisp HDMI */ 516 num_links += ctx->hdmi_num; 517 518 /* speaker amp */ 519 if (ctx->amp_type != CODEC_NONE) 520 num_links++; 521 522 /* BT audio offload */ 523 if (ctx->bt_offload_present) 524 num_links++; 525 526 /* HDMI-In */ 527 num_links += hweight32(ctx->ssp_mask_hdmi_in); 528 529 /* HDA external codec */ 530 if (ctx->hda_codec_present) 531 num_links += 2; 532 533 return num_links; 534 } 535 536 int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, 537 struct sof_card_private *ctx) 538 { 539 struct snd_soc_dai_link *links; 540 int num_links; 541 int i; 542 int idx = 0; 543 int ret; 544 int ssp_hdmi_in = 0; 545 unsigned long link_order, link; 546 unsigned long link_ids, be_id; 547 548 num_links = calculate_num_links(ctx); 549 550 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), 551 GFP_KERNEL); 552 if (!links) 553 return -ENOMEM; 554 555 if (ctx->link_order_overwrite) 556 link_order = ctx->link_order_overwrite; 557 else 558 link_order = DEFAULT_LINK_ORDER; 559 560 if (ctx->link_id_overwrite) 561 link_ids = ctx->link_id_overwrite; 562 else 563 link_ids = 0; 564 565 dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n", 566 link_order, link_ids); 567 568 while (link_order) { 569 link = link_order & SOF_LINK_ORDER_MASK; 570 link_order >>= SOF_LINK_ORDER_SHIFT; 571 572 if (ctx->link_id_overwrite) { 573 be_id = link_ids & SOF_LINK_IDS_MASK; 574 link_ids >>= SOF_LINK_IDS_SHIFT; 575 } else { 576 /* use array index as link id */ 577 be_id = idx; 578 } 579 580 switch (link) { 581 case SOF_LINK_CODEC: 582 /* headphone codec */ 583 if (ctx->codec_type == CODEC_NONE) 584 continue; 585 586 ret = set_ssp_codec_link(dev, &links[idx], be_id, 587 ctx->codec_type, ctx->ssp_codec); 588 if (ret) { 589 dev_err(dev, "fail to set codec link, ret %d\n", 590 ret); 591 return ret; 592 } 593 594 ctx->codec_link = &links[idx]; 595 idx++; 596 break; 597 case SOF_LINK_DMIC01: 598 /* dmic01 */ 599 if (ctx->dmic_be_num == 0) 600 continue; 601 602 /* at least we have dmic01 */ 603 ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01); 604 if (ret) { 605 dev_err(dev, "fail to set dmic01 link, ret %d\n", 606 ret); 607 return ret; 608 } 609 610 idx++; 611 break; 612 case SOF_LINK_DMIC16K: 613 /* dmic16k */ 614 if (ctx->dmic_be_num <= 1) 615 continue; 616 617 /* set up 2 BE links at most */ 618 ret = set_dmic_link(dev, &links[idx], be_id, 619 SOF_DMIC_16K); 620 if (ret) { 621 dev_err(dev, "fail to set dmic16k link, ret %d\n", 622 ret); 623 return ret; 624 } 625 626 idx++; 627 break; 628 case SOF_LINK_IDISP_HDMI: 629 /* idisp HDMI */ 630 for (i = 1; i <= ctx->hdmi_num; i++) { 631 ret = set_idisp_hdmi_link(dev, &links[idx], 632 be_id, i, 633 ctx->hdmi.idisp_codec); 634 if (ret) { 635 dev_err(dev, "fail to set hdmi link, ret %d\n", 636 ret); 637 return ret; 638 } 639 640 idx++; 641 be_id++; 642 } 643 break; 644 case SOF_LINK_AMP: 645 /* speaker amp */ 646 if (ctx->amp_type == CODEC_NONE) 647 continue; 648 649 ret = set_ssp_amp_link(dev, &links[idx], be_id, 650 ctx->amp_type, ctx->ssp_amp); 651 if (ret) { 652 dev_err(dev, "fail to set amp link, ret %d\n", 653 ret); 654 return ret; 655 } 656 657 ctx->amp_link = &links[idx]; 658 idx++; 659 break; 660 case SOF_LINK_BT_OFFLOAD: 661 /* BT audio offload */ 662 if (!ctx->bt_offload_present) 663 continue; 664 665 ret = set_bt_offload_link(dev, &links[idx], be_id, 666 ctx->ssp_bt); 667 if (ret) { 668 dev_err(dev, "fail to set bt link, ret %d\n", 669 ret); 670 return ret; 671 } 672 673 idx++; 674 break; 675 case SOF_LINK_HDMI_IN: 676 /* HDMI-In */ 677 for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) { 678 ret = set_hdmi_in_link(dev, &links[idx], be_id, 679 ssp_hdmi_in); 680 if (ret) { 681 dev_err(dev, "fail to set hdmi-in link, ret %d\n", 682 ret); 683 return ret; 684 } 685 686 idx++; 687 be_id++; 688 } 689 break; 690 case SOF_LINK_HDA: 691 /* HDA external codec */ 692 if (!ctx->hda_codec_present) 693 continue; 694 695 ret = set_hda_codec_link(dev, &links[idx], be_id, 696 SOF_HDA_ANALOG); 697 if (ret) { 698 dev_err(dev, "fail to set hda analog link, ret %d\n", 699 ret); 700 return ret; 701 } 702 703 idx++; 704 be_id++; 705 706 ret = set_hda_codec_link(dev, &links[idx], be_id, 707 SOF_HDA_DIGITAL); 708 if (ret) { 709 dev_err(dev, "fail to set hda digital link, ret %d\n", 710 ret); 711 return ret; 712 } 713 714 idx++; 715 break; 716 case SOF_LINK_NONE: 717 /* caught here if it's not used as terminator in macro */ 718 fallthrough; 719 default: 720 dev_err(dev, "invalid link type %ld\n", link); 721 return -EINVAL; 722 } 723 } 724 725 if (idx != num_links) { 726 dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx, 727 num_links); 728 return -EINVAL; 729 } 730 731 card->dai_link = links; 732 card->num_links = num_links; 733 734 return 0; 735 } 736 EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, "SND_SOC_INTEL_SOF_BOARD_HELPERS"); 737 738 struct sof_card_private * 739 sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) 740 { 741 struct sof_card_private *ctx; 742 743 dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk); 744 745 ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL); 746 if (!ctx) 747 return NULL; 748 749 ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev); 750 ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev); 751 752 ctx->dmic_be_num = 2; 753 ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >> 754 SOF_NUM_IDISP_HDMI_SHIFT; 755 /* default number of HDMI DAI's */ 756 if (!ctx->hdmi_num) 757 ctx->hdmi_num = 3; 758 759 /* port number/mask of peripherals attached to ssp interface */ 760 if (ctx->codec_type != CODEC_NONE) 761 ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >> 762 SOF_SSP_PORT_CODEC_SHIFT; 763 764 if (ctx->amp_type != CODEC_NONE) 765 ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >> 766 SOF_SSP_PORT_AMP_SHIFT; 767 768 if (board_quirk & SOF_BT_OFFLOAD_PRESENT) { 769 ctx->bt_offload_present = true; 770 ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >> 771 SOF_SSP_PORT_BT_OFFLOAD_SHIFT; 772 } 773 774 ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >> 775 SOF_SSP_MASK_HDMI_CAPTURE_SHIFT; 776 777 return ctx; 778 } 779 EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, "SND_SOC_INTEL_SOF_BOARD_HELPERS"); 780 781 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); 782 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 783 MODULE_LICENSE("GPL"); 784 MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON"); 785 MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH"); 786