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