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 * 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 /* Panther Lake */ 548 #if IS_ENABLED(CONFIG_SND_SOC_SOF_PANTHERLAKE) 549 { 550 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 551 .device = PCI_DEVICE_ID_INTEL_HDA_PTL, 552 }, 553 #endif 554 555 }; 556 557 static const struct config_entry *snd_intel_dsp_find_config 558 (struct pci_dev *pci, const struct config_entry *table, u32 len) 559 { 560 u16 device; 561 562 device = pci->device; 563 for (; len > 0; len--, table++) { 564 if (table->device != device) 565 continue; 566 if (table->dmi_table && !dmi_check_system(table->dmi_table)) 567 continue; 568 if (table->codec_hid) { 569 int i; 570 571 for (i = 0; i < table->codec_hid->num_codecs; i++) { 572 struct nhlt_acpi_table *nhlt; 573 bool ssp_found = false; 574 575 if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) 576 continue; 577 578 nhlt = intel_nhlt_init(&pci->dev); 579 if (!nhlt) { 580 dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n", 581 __func__, table->codec_hid->codecs[i]); 582 continue; 583 } 584 585 if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) && 586 intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S)) 587 ssp_found = true; 588 589 intel_nhlt_free(nhlt); 590 591 if (ssp_found) 592 break; 593 594 dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n", 595 __func__, table->codec_hid->codecs[i]); 596 } 597 if (i == table->codec_hid->num_codecs) 598 continue; 599 } 600 return table; 601 } 602 return NULL; 603 } 604 605 static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 606 { 607 int ret = 0; 608 609 acpi_nhlt_get_gbl_table(); 610 611 if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) 612 ret = 1; 613 614 acpi_nhlt_put_gbl_table(); 615 616 return ret; 617 } 618 619 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 620 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 621 { 622 struct sdw_intel_acpi_info info; 623 acpi_handle handle; 624 int ret; 625 626 handle = ACPI_HANDLE(&pci->dev); 627 628 ret = sdw_intel_acpi_scan(handle, &info); 629 if (ret < 0) 630 return ret; 631 632 return info.link_mask; 633 } 634 #else 635 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 636 { 637 return 0; 638 } 639 #endif 640 641 int snd_intel_dsp_driver_probe(struct pci_dev *pci) 642 { 643 const struct config_entry *cfg; 644 645 /* Intel vendor only */ 646 if (pci->vendor != PCI_VENDOR_ID_INTEL) 647 return SND_INTEL_DSP_DRIVER_ANY; 648 649 /* 650 * Legacy devices don't have a PCI-based DSP and use HDaudio 651 * for HDMI/DP support, ignore kernel parameter 652 */ 653 switch (pci->device) { 654 case PCI_DEVICE_ID_INTEL_HDA_BDW: 655 case PCI_DEVICE_ID_INTEL_HDA_HSW_0: 656 case PCI_DEVICE_ID_INTEL_HDA_HSW_2: 657 case PCI_DEVICE_ID_INTEL_HDA_HSW_3: 658 case PCI_DEVICE_ID_INTEL_HDA_BYT: 659 case PCI_DEVICE_ID_INTEL_HDA_BSW: 660 return SND_INTEL_DSP_DRIVER_ANY; 661 } 662 663 if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 664 return dsp_driver; 665 666 /* 667 * detect DSP by checking class/subclass/prog-id information 668 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 669 * class=04 subclass 01 prog-if 00: DSP is present 670 * (and may be required e.g. for DMIC or SSP support) 671 * class=04 subclass 03 prog-if 80: use DSP or legacy mode 672 */ 673 if (pci->class == 0x040300) 674 return SND_INTEL_DSP_DRIVER_LEGACY; 675 if (pci->class != 0x040100 && pci->class != 0x040380) { 676 dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 677 return SND_INTEL_DSP_DRIVER_LEGACY; 678 } 679 680 dev_dbg(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 681 682 /* find the configuration for the specific device */ 683 cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 684 if (!cfg) 685 return SND_INTEL_DSP_DRIVER_ANY; 686 687 if (cfg->flags & FLAG_SOF) { 688 if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 689 snd_intel_dsp_check_soundwire(pci) > 0) { 690 dev_info_once(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 691 return SND_INTEL_DSP_DRIVER_SOF; 692 } 693 if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 694 snd_intel_dsp_check_dmic(pci)) { 695 dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 696 return SND_INTEL_DSP_DRIVER_SOF; 697 } 698 if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 699 return SND_INTEL_DSP_DRIVER_SOF; 700 } 701 702 703 if (cfg->flags & FLAG_SST) { 704 if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 705 if (snd_intel_dsp_check_dmic(pci)) { 706 dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 707 return SND_INTEL_DSP_DRIVER_SST; 708 } 709 } else { 710 return SND_INTEL_DSP_DRIVER_SST; 711 } 712 } 713 714 return SND_INTEL_DSP_DRIVER_LEGACY; 715 } 716 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 717 718 /* Should we default to SOF or SST for BYT/CHT ? */ 719 #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ 720 !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 721 #define FLAG_SST_OR_SOF_BYT FLAG_SOF 722 #else 723 #define FLAG_SST_OR_SOF_BYT FLAG_SST 724 #endif 725 726 /* 727 * configuration table 728 * - the order of similar ACPI ID entries is important! 729 * - the first successful match will win 730 */ 731 static const struct config_entry acpi_config_table[] = { 732 #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ 733 IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 734 /* BayTrail */ 735 { 736 .flags = FLAG_SST_OR_SOF_BYT, 737 .acpi_hid = "80860F28", 738 }, 739 /* CherryTrail */ 740 { 741 .flags = FLAG_SST_OR_SOF_BYT, 742 .acpi_hid = "808622A8", 743 }, 744 #endif 745 /* Broadwell */ 746 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 747 { 748 .flags = FLAG_SST, 749 .acpi_hid = "INT3438" 750 }, 751 #endif 752 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) 753 { 754 .flags = FLAG_SOF, 755 .acpi_hid = "INT3438" 756 }, 757 #endif 758 /* Haswell - not supported by SOF but added for consistency */ 759 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 760 { 761 .flags = FLAG_SST, 762 .acpi_hid = "INT33C8" 763 }, 764 #endif 765 }; 766 767 static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 768 const struct config_entry *table, 769 u32 len) 770 { 771 for (; len > 0; len--, table++) { 772 if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 773 continue; 774 if (table->dmi_table && !dmi_check_system(table->dmi_table)) 775 continue; 776 return table; 777 } 778 return NULL; 779 } 780 781 int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 782 { 783 const struct config_entry *cfg; 784 785 if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 786 return dsp_driver; 787 788 if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 789 dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 790 SND_INTEL_DSP_DRIVER_LEGACY); 791 } 792 793 /* find the configuration for the specific device */ 794 cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 795 ARRAY_SIZE(acpi_config_table)); 796 if (!cfg) 797 return SND_INTEL_DSP_DRIVER_ANY; 798 799 if (cfg->flags & FLAG_SST) 800 return SND_INTEL_DSP_DRIVER_SST; 801 802 if (cfg->flags & FLAG_SOF) 803 return SND_INTEL_DSP_DRIVER_SOF; 804 805 return SND_INTEL_DSP_DRIVER_SST; 806 } 807 EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 808 809 MODULE_LICENSE("GPL v2"); 810 MODULE_DESCRIPTION("Intel DSP config driver"); 811 MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); 812
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.