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