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