1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz> 3 4 #include <linux/acpi.h> 5 #include <linux/bits.h> 6 #include <linux/dmi.h> 7 #include <linux/module.h> 8 #include <linux/pci.h> 9 #include <linux/soundwire/sdw.h> 10 #include <linux/soundwire/sdw_intel.h> 11 #include <sound/core.h> 12 #include <sound/intel-dsp-config.h> 13 #include <sound/intel-nhlt.h> 14 #include <sound/soc-acpi.h> 15 16 #include <acpi/nhlt.h> 17 18 static int dsp_driver; 19 20 module_param(dsp_driver, int, 0444); 21 MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF, 4=AVS)"); 22 23 #define FLAG_SST BIT(0) 24 #define FLAG_SOF BIT(1) 25 #define FLAG_SST_ONLY_IF_DMIC BIT(15) 26 #define FLAG_SOF_ONLY_IF_DMIC BIT(16) 27 #define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) 28 29 #define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ 30 FLAG_SOF_ONLY_IF_SOUNDWIRE) 31 32 struct config_entry { 33 u32 flags; 34 u16 device; 35 u8 acpi_hid[ACPI_ID_LEN]; 36 const struct dmi_system_id *dmi_table; 37 const struct snd_soc_acpi_codecs *codec_hid; 38 }; 39 40 static const struct snd_soc_acpi_codecs __maybe_unused essx_83x6 = { 41 .num_codecs = 3, 42 .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, 43 }; 44 45 /* 46 * configuration table 47 * - the order of similar PCI ID entries is important! 48 * - the first successful match will win 49 */ 50 static const struct config_entry config_table[] = { 51 /* Merrifield */ 52 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 53 { 54 .flags = FLAG_SOF, 55 .device = PCI_DEVICE_ID_INTEL_SST_TNG, 56 }, 57 #endif 58 /* 59 * Skylake, Kabylake, Apollolake 60 * the legacy HDAudio driver is used except on Up Squared (SOF) and 61 * Chromebooks (SST), as well as devices based on the ES8336 codec 62 */ 63 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_AVS) 64 { 65 .flags = FLAG_SST, 66 .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, 67 .dmi_table = (const struct dmi_system_id []) { 68 { 69 .ident = "Google Chromebooks", 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 72 } 73 }, 74 {} 75 } 76 }, 77 { 78 .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 79 .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, 80 }, 81 { 82 .flags = FLAG_SST, 83 .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, 84 .dmi_table = (const struct dmi_system_id []) { 85 { 86 .ident = "Google Chromebooks", 87 .matches = { 88 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 89 } 90 }, 91 {} 92 } 93 }, 94 { 95 .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 96 .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, 97 }, 98 { 99 .flags = FLAG_SST, 100 .device = PCI_DEVICE_ID_INTEL_HDA_APL, 101 .dmi_table = (const struct dmi_system_id []) { 102 { 103 .ident = "Google Chromebooks", 104 .matches = { 105 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 106 } 107 }, 108 {} 109 } 110 }, 111 { 112 .flags = FLAG_SST, 113 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_M, 114 }, 115 { 116 .flags = FLAG_SST, 117 .device = PCI_DEVICE_ID_INTEL_HDA_FCL, 118 }, 119 #else /* AVS disabled; force to legacy as SOF doesn't work for SKL or KBL */ 120 { 121 .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, 122 }, 123 { 124 .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, 125 }, 126 #endif 127 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 128 { 129 .flags = FLAG_SOF, 130 .device = PCI_DEVICE_ID_INTEL_HDA_APL, 131 .dmi_table = (const struct dmi_system_id []) { 132 { 133 .ident = "Up Squared", 134 .matches = { 135 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 136 DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), 137 } 138 }, 139 {} 140 } 141 }, 142 { 143 .flags = FLAG_SOF, 144 .device = PCI_DEVICE_ID_INTEL_HDA_APL, 145 .codec_hid = &essx_83x6, 146 }, 147 #endif 148 149 /* 150 * Geminilake uses legacy HDAudio driver except for Google 151 * Chromebooks and devices based on the ES8336 codec 152 */ 153 /* Geminilake */ 154 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 155 { 156 .flags = FLAG_SOF, 157 .device = PCI_DEVICE_ID_INTEL_HDA_GLK, 158 .dmi_table = (const struct dmi_system_id []) { 159 { 160 .ident = "Google Chromebooks", 161 .matches = { 162 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 163 } 164 }, 165 {} 166 } 167 }, 168 { 169 .flags = FLAG_SOF, 170 .device = PCI_DEVICE_ID_INTEL_HDA_GLK, 171 .codec_hid = &essx_83x6, 172 }, 173 #endif 174 175 /* 176 * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake, AlderLake, 177 * RaptorLake, MeteorLake use legacy HDAudio driver except for Google 178 * Chromebooks and when DMICs are present. Two cases are required since 179 * Coreboot does not expose NHLT tables. 180 * 181 * When the Chromebook quirk is not present, it's based on information 182 * that no such device exists. When the quirk is present, it could be 183 * either based on product information or a placeholder. 184 */ 185 186 /* Cannonlake */ 187 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 188 { 189 .flags = FLAG_SOF, 190 .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 191 .dmi_table = (const struct dmi_system_id []) { 192 { 193 .ident = "Google Chromebooks", 194 .matches = { 195 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 196 } 197 }, 198 { 199 .ident = "UP-WHL", 200 .matches = { 201 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 202 } 203 }, 204 {} 205 } 206 }, 207 { 208 .flags = FLAG_SOF, 209 .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 210 .codec_hid = &essx_83x6, 211 }, 212 { 213 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 214 .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 215 }, 216 #endif 217 218 /* Coffelake */ 219 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 220 { 221 .flags = FLAG_SOF, 222 .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, 223 .dmi_table = (const struct dmi_system_id []) { 224 { 225 .ident = "Google Chromebooks", 226 .matches = { 227 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 228 } 229 }, 230 {} 231 } 232 }, 233 { 234 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 235 .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, 236 }, 237 #endif 238 239 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 240 /* Cometlake-LP */ 241 { 242 .flags = FLAG_SOF, 243 .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 244 .dmi_table = (const struct dmi_system_id []) { 245 { 246 .ident = "Google Chromebooks", 247 .matches = { 248 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 249 } 250 }, 251 { 252 .matches = { 253 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 254 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 255 }, 256 }, 257 { 258 /* early version of SKU 09C6 */ 259 .matches = { 260 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 261 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 262 }, 263 }, 264 {} 265 } 266 }, 267 { 268 .flags = FLAG_SOF, 269 .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 270 .codec_hid = &essx_83x6, 271 }, 272 { 273 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 274 .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 275 }, 276 /* Cometlake-H */ 277 { 278 .flags = FLAG_SOF, 279 .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 280 .dmi_table = (const struct dmi_system_id []) { 281 { 282 .matches = { 283 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 284 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 285 }, 286 }, 287 { 288 .matches = { 289 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 290 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 291 }, 292 }, 293 {} 294 } 295 }, 296 { 297 .flags = FLAG_SOF, 298 .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 299 .codec_hid = &essx_83x6, 300 }, 301 { 302 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 303 .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 304 }, 305 #endif 306 307 /* Icelake */ 308 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 309 { 310 .flags = FLAG_SOF, 311 .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, 312 .dmi_table = (const struct dmi_system_id []) { 313 { 314 .ident = "Google Chromebooks", 315 .matches = { 316 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 317 } 318 }, 319 {} 320 } 321 }, 322 { 323 .flags = FLAG_SOF, 324 .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, 325 .codec_hid = &essx_83x6, 326 }, 327 { 328 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 329 .device = PCI_DEVICE_ID_INTEL_HDA_ICL_LP, 330 }, 331 #endif 332 333 /* Jasper Lake */ 334 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) 335 { 336 .flags = FLAG_SOF, 337 .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, 338 .dmi_table = (const struct dmi_system_id []) { 339 { 340 .ident = "Google Chromebooks", 341 .matches = { 342 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 343 } 344 }, 345 { 346 .ident = "Google firmware", 347 .matches = { 348 DMI_MATCH(DMI_BIOS_VERSION, "Google"), 349 } 350 }, 351 {} 352 } 353 }, 354 { 355 .flags = FLAG_SOF, 356 .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, 357 .codec_hid = &essx_83x6, 358 }, 359 { 360 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 361 .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N, 362 }, 363 #endif 364 365 /* Tigerlake */ 366 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 367 { 368 .flags = FLAG_SOF, 369 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, 370 .dmi_table = (const struct dmi_system_id []) { 371 { 372 .ident = "Google Chromebooks", 373 .matches = { 374 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 375 } 376 }, 377 { 378 .ident = "UPX-TGL", 379 .matches = { 380 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 381 } 382 }, 383 {} 384 } 385 }, 386 { 387 .flags = FLAG_SOF, 388 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, 389 .codec_hid = &essx_83x6, 390 }, 391 { 392 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 393 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP, 394 }, 395 { 396 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 397 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_H, 398 }, 399 #endif 400 401 /* Elkhart Lake */ 402 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 403 { 404 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 405 .device = PCI_DEVICE_ID_INTEL_HDA_EHL_0, 406 }, 407 { 408 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 409 .device = PCI_DEVICE_ID_INTEL_HDA_EHL_3, 410 }, 411 #endif 412 413 /* Alder Lake / Raptor Lake */ 414 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 415 { 416 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 417 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_S, 418 }, 419 { 420 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 421 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_S, 422 }, 423 { 424 .flags = FLAG_SOF, 425 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, 426 .dmi_table = (const struct dmi_system_id []) { 427 { 428 .ident = "Google Chromebooks", 429 .matches = { 430 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 431 } 432 }, 433 {} 434 } 435 }, 436 { 437 .flags = FLAG_SOF, 438 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, 439 .codec_hid = &essx_83x6, 440 }, 441 { 442 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 443 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P, 444 }, 445 { 446 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 447 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PX, 448 }, 449 { 450 .flags = FLAG_SOF, 451 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS, 452 .codec_hid = &essx_83x6, 453 }, 454 { 455 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 456 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS, 457 }, 458 { 459 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 460 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_M, 461 }, 462 { 463 .flags = FLAG_SOF, 464 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N, 465 .dmi_table = (const struct dmi_system_id []) { 466 { 467 .ident = "Google Chromebooks", 468 .matches = { 469 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 470 } 471 }, 472 {} 473 } 474 }, 475 { 476 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 477 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N, 478 }, 479 { 480 .flags = FLAG_SOF, 481 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0, 482 .dmi_table = (const struct dmi_system_id []) { 483 { 484 .ident = "Google Chromebooks", 485 .matches = { 486 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 487 } 488 }, 489 {} 490 } 491 }, 492 { 493 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 494 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0, 495 }, 496 { 497 .flags = FLAG_SOF, 498 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1, 499 .dmi_table = (const struct dmi_system_id []) { 500 { 501 .ident = "Google Chromebooks", 502 .matches = { 503 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 504 } 505 }, 506 {} 507 } 508 }, 509 { 510 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 511 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1, 512 }, 513 { 514 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 515 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_M, 516 }, 517 { 518 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 519 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_PX, 520 }, 521 #endif 522 523 /* Meteor Lake */ 524 #if IS_ENABLED(CONFIG_SND_SOC_SOF_METEORLAKE) 525 /* Meteorlake-P */ 526 { 527 .flags = FLAG_SOF, 528 .device = PCI_DEVICE_ID_INTEL_HDA_MTL, 529 .dmi_table = (const struct dmi_system_id []) { 530 { 531 .ident = "Google Chromebooks", 532 .matches = { 533 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 534 } 535 }, 536 {} 537 } 538 }, 539 { 540 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 541 .device = PCI_DEVICE_ID_INTEL_HDA_MTL, 542 }, 543 /* ArrowLake-S */ 544 { 545 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 546 .device = PCI_DEVICE_ID_INTEL_HDA_ARL_S, 547 }, 548 /* ArrowLake */ 549 { 550 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 551 .device = PCI_DEVICE_ID_INTEL_HDA_ARL, 552 }, 553 #endif 554 555 /* Lunar Lake */ 556 #if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE) 557 /* Lunarlake-P */ 558 { 559 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 560 .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P, 561 }, 562 #endif 563 564 /* Panther Lake, Wildcat Lake */ 565 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PANTHERLAKE) 566 { 567 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 568 .device = PCI_DEVICE_ID_INTEL_HDA_PTL, 569 }, 570 { 571 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 572 .device = PCI_DEVICE_ID_INTEL_HDA_PTL_H, 573 }, 574 { 575 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 576 .device = PCI_DEVICE_ID_INTEL_HDA_WCL, 577 }, 578 579 #endif 580 581 /* Nova Lake */ 582 #if IS_ENABLED(CONFIG_SND_SOC_SOF_NOVALAKE) 583 { 584 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 585 .device = PCI_DEVICE_ID_INTEL_HDA_NVL, 586 }, 587 { 588 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 589 .device = PCI_DEVICE_ID_INTEL_HDA_NVL_S, 590 }, 591 #endif 592 593 }; 594 595 static const struct config_entry *snd_intel_dsp_find_config 596 (struct pci_dev *pci, const struct config_entry *table, u32 len) 597 { 598 u16 device; 599 600 device = pci->device; 601 for (; len > 0; len--, table++) { 602 if (table->device != device) 603 continue; 604 if (table->dmi_table && !dmi_check_system(table->dmi_table)) 605 continue; 606 if (table->codec_hid) { 607 int i; 608 609 for (i = 0; i < table->codec_hid->num_codecs; i++) { 610 struct nhlt_acpi_table *nhlt; 611 bool ssp_found = false; 612 613 if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) 614 continue; 615 616 nhlt = intel_nhlt_init(&pci->dev); 617 if (!nhlt) { 618 dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n", 619 __func__, table->codec_hid->codecs[i]); 620 continue; 621 } 622 623 if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) && 624 intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S)) 625 ssp_found = true; 626 627 intel_nhlt_free(nhlt); 628 629 if (ssp_found) 630 break; 631 632 dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n", 633 __func__, table->codec_hid->codecs[i]); 634 } 635 if (i == table->codec_hid->num_codecs) 636 continue; 637 } 638 return table; 639 } 640 return NULL; 641 } 642 643 static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 644 { 645 int ret = 0; 646 647 acpi_nhlt_get_gbl_table(); 648 649 if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) 650 ret = 1; 651 652 acpi_nhlt_put_gbl_table(); 653 654 return ret; 655 } 656 657 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 658 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 659 { 660 struct sdw_intel_acpi_info info; 661 acpi_handle handle; 662 int ret; 663 664 handle = ACPI_HANDLE(&pci->dev); 665 if (!handle) 666 return -ENODEV; 667 668 ret = sdw_intel_acpi_scan(handle, &info); 669 if (ret < 0) 670 return ret; 671 672 return info.link_mask; 673 } 674 #else 675 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 676 { 677 return 0; 678 } 679 #endif 680 681 int snd_intel_dsp_driver_probe(struct pci_dev *pci) 682 { 683 const struct config_entry *cfg; 684 685 /* Intel vendor only */ 686 if (pci->vendor != PCI_VENDOR_ID_INTEL) 687 return SND_INTEL_DSP_DRIVER_ANY; 688 689 /* 690 * Legacy devices don't have a PCI-based DSP and use HDaudio 691 * for HDMI/DP support, ignore kernel parameter 692 */ 693 switch (pci->device) { 694 case PCI_DEVICE_ID_INTEL_HDA_BDW: 695 case PCI_DEVICE_ID_INTEL_HDA_HSW_0: 696 case PCI_DEVICE_ID_INTEL_HDA_HSW_2: 697 case PCI_DEVICE_ID_INTEL_HDA_HSW_3: 698 case PCI_DEVICE_ID_INTEL_HDA_BYT: 699 case PCI_DEVICE_ID_INTEL_HDA_BSW: 700 return SND_INTEL_DSP_DRIVER_ANY; 701 } 702 703 if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 704 return dsp_driver; 705 706 /* 707 * detect DSP by checking class/subclass/prog-id information 708 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 709 * class=04 subclass 01 prog-if 00: DSP is present 710 * (and may be required e.g. for DMIC or SSP support) 711 * class=04 subclass 03 prog-if 80: use DSP or legacy mode 712 */ 713 if (pci->class == 0x040300) 714 return SND_INTEL_DSP_DRIVER_LEGACY; 715 if (pci->class != 0x040100 && pci->class != 0x040380) { 716 dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 717 return SND_INTEL_DSP_DRIVER_LEGACY; 718 } 719 720 dev_dbg(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 721 722 /* find the configuration for the specific device */ 723 cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 724 if (!cfg) 725 return IS_ENABLED(CONFIG_SND_HDA_INTEL) ? 726 SND_INTEL_DSP_DRIVER_LEGACY : SND_INTEL_DSP_DRIVER_ANY; 727 728 if (cfg->flags & FLAG_SOF) { 729 if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 730 snd_intel_dsp_check_soundwire(pci) > 0) { 731 dev_info_once(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 732 return SND_INTEL_DSP_DRIVER_SOF; 733 } 734 if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 735 snd_intel_dsp_check_dmic(pci)) { 736 dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 737 return SND_INTEL_DSP_DRIVER_SOF; 738 } 739 if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 740 return SND_INTEL_DSP_DRIVER_SOF; 741 } 742 743 744 if (cfg->flags & FLAG_SST) { 745 if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 746 if (snd_intel_dsp_check_dmic(pci)) { 747 dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 748 return SND_INTEL_DSP_DRIVER_SST; 749 } 750 } else { 751 return SND_INTEL_DSP_DRIVER_SST; 752 } 753 } 754 755 return SND_INTEL_DSP_DRIVER_LEGACY; 756 } 757 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 758 759 /* Should we default to SOF or SST for BYT/CHT ? */ 760 #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ 761 !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 762 #define FLAG_SST_OR_SOF_BYT FLAG_SOF 763 #else 764 #define FLAG_SST_OR_SOF_BYT FLAG_SST 765 #endif 766 767 /* 768 * configuration table 769 * - the order of similar ACPI ID entries is important! 770 * - the first successful match will win 771 */ 772 static const struct config_entry acpi_config_table[] = { 773 #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ 774 IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 775 /* BayTrail */ 776 { 777 .flags = FLAG_SST_OR_SOF_BYT, 778 .acpi_hid = "LPE0F28", 779 }, 780 { 781 .flags = FLAG_SST_OR_SOF_BYT, 782 .acpi_hid = "80860F28", 783 }, 784 /* CherryTrail */ 785 { 786 .flags = FLAG_SST_OR_SOF_BYT, 787 .acpi_hid = "808622A8", 788 }, 789 #endif 790 /* Broadwell */ 791 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 792 { 793 .flags = FLAG_SST, 794 .acpi_hid = "INT3438" 795 }, 796 #endif 797 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) 798 { 799 .flags = FLAG_SOF, 800 .acpi_hid = "INT3438" 801 }, 802 #endif 803 /* Haswell - not supported by SOF but added for consistency */ 804 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 805 { 806 .flags = FLAG_SST, 807 .acpi_hid = "INT33C8" 808 }, 809 #endif 810 }; 811 812 static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 813 const struct config_entry *table, 814 u32 len) 815 { 816 for (; len > 0; len--, table++) { 817 if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 818 continue; 819 if (table->dmi_table && !dmi_check_system(table->dmi_table)) 820 continue; 821 return table; 822 } 823 return NULL; 824 } 825 826 int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 827 { 828 const struct config_entry *cfg; 829 830 if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 831 return dsp_driver; 832 833 if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 834 dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 835 SND_INTEL_DSP_DRIVER_LEGACY); 836 } 837 838 /* find the configuration for the specific device */ 839 cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 840 ARRAY_SIZE(acpi_config_table)); 841 if (!cfg) 842 return SND_INTEL_DSP_DRIVER_ANY; 843 844 if (cfg->flags & FLAG_SST) 845 return SND_INTEL_DSP_DRIVER_SST; 846 847 if (cfg->flags & FLAG_SOF) 848 return SND_INTEL_DSP_DRIVER_SOF; 849 850 return SND_INTEL_DSP_DRIVER_SST; 851 } 852 EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 853 854 MODULE_LICENSE("GPL v2"); 855 MODULE_DESCRIPTION("Intel DSP config driver"); 856 MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI"); 857