1139804Simp// SPDX-License-Identifier: GPL-2.0 21541Srgrimes// Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz> 31541Srgrimes 41541Srgrimes#include <linux/acpi.h> 51541Srgrimes#include <linux/bits.h> 61541Srgrimes#include <linux/dmi.h> 71541Srgrimes#include <linux/module.h> 81541Srgrimes#include <linux/pci.h> 91541Srgrimes#include <linux/soundwire/sdw.h> 101541Srgrimes#include <linux/soundwire/sdw_intel.h> 111541Srgrimes#include <sound/core.h> 121541Srgrimes#include <sound/intel-dsp-config.h> 131541Srgrimes#include <sound/intel-nhlt.h> 141541Srgrimes#include <sound/soc-acpi.h> 151541Srgrimes 161541Srgrimesstatic int dsp_driver; 171541Srgrimes 181541Srgrimesmodule_param(dsp_driver, int, 0444); 191541SrgrimesMODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)"); 201541Srgrimes 211541Srgrimes#define FLAG_SST BIT(0) 221541Srgrimes#define FLAG_SOF BIT(1) 231541Srgrimes#define FLAG_SST_ONLY_IF_DMIC BIT(15) 241541Srgrimes#define FLAG_SOF_ONLY_IF_DMIC BIT(16) 251541Srgrimes#define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) 261541Srgrimes 271541Srgrimes#define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ 281541Srgrimes FLAG_SOF_ONLY_IF_SOUNDWIRE) 291541Srgrimes 301541Srgrimesstruct config_entry { 311541Srgrimes u32 flags; 321541Srgrimes u16 device; 331541Srgrimes u8 acpi_hid[ACPI_ID_LEN]; 3414526Shsu const struct dmi_system_id *dmi_table; 351541Srgrimes const struct snd_soc_acpi_codecs *codec_hid; 361541Srgrimes}; 37116182Sobrien 38116182Sobrienstatic const struct snd_soc_acpi_codecs __maybe_unused essx_83x6 = { 39116182Sobrien .num_codecs = 3, 4014328Speter .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, 4180418Speter}; 4213226Swollman 431541Srgrimes/* 4480418Speter * configuration table 4580418Speter * - the order of similar PCI ID entries is important! 46172696Salfred * - the first successful match will win 471541Srgrimes */ 48137393Sdesstatic const struct config_entry config_table[] = { 4984783Sps/* Merrifield */ 501541Srgrimes#if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 511541Srgrimes { 521541Srgrimes .flags = FLAG_SOF, 531541Srgrimes .device = PCI_DEVICE_ID_INTEL_SST_TNG, 541541Srgrimes }, 55145154Smarius#endif 56137307Sphk/* 57137307Sphk * Apollolake (Broxton-P) 58137307Sphk * the legacy HDAudio driver is used except on Up Squared (SOF) and 59138214Sbms * Chromebooks (SST), as well as devices based on the ES8336 codec 60184323Ssobomax */ 61184323Ssobomax#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 62184323Ssobomax { 63184323Ssobomax .flags = FLAG_SOF, 64184323Ssobomax .device = PCI_DEVICE_ID_INTEL_HDA_APL, 65184323Ssobomax .dmi_table = (const struct dmi_system_id []) { 66184323Ssobomax { 671541Srgrimes .ident = "Up Squared", 6880418Speter .matches = { 6980418Speter DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 7080418Speter DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), 7180418Speter } 7245515Sdes }, 7380418Speter {} 7445515Sdes } 758747Sdg }, 76186619Sivoras { 77186619Sivoras .flags = FLAG_SOF, 78186619Sivoras .device = PCI_DEVICE_ID_INTEL_HDA_APL, 79186252Sivoras .codec_hid = &essx_83x6, 80186286Sivoras }, 81186286Sivoras#endif 8280418Speter#if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) 8380418Speter { 8480418Speter .flags = FLAG_SST, 8580418Speter .device = PCI_DEVICE_ID_INTEL_HDA_APL, 8680418Speter .dmi_table = (const struct dmi_system_id []) { 8780418Speter { 8880418Speter .ident = "Google Chromebooks", 8980418Speter .matches = { 9080418Speter DMI_MATCH(DMI_SYS_VENDOR, "Google"), 9180418Speter } 92189595Sjhb }, 93189595Sjhb {} 94189649Sjhb } 95186286Sivoras }, 96137393Sdes#endif 97137393Sdes/* 98137393Sdes * Skylake and Kabylake use legacy HDAudio driver except for Google 99137393Sdes * Chromebooks (SST) 100137393Sdes */ 101137393Sdes 1021541Srgrimes/* Sunrise Point-LP */ 103178872Spjd#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) 104189744Sjhb { 105189744Sjhb .flags = FLAG_SST, 106189744Sjhb .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, 107189744Sjhb .dmi_table = (const struct dmi_system_id []) { 108189744Sjhb { 109189744Sjhb .ident = "Google Chromebooks", 110178872Spjd .matches = { 111178872Spjd DMI_MATCH(DMI_SYS_VENDOR, "Google"), 112178872Spjd } 113178872Spjd }, 114178872Spjd {} 115178872Spjd } 116178872Spjd }, 117178872Spjd { 118178872Spjd .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 119178872Spjd .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, 120178872Spjd }, 121178872Spjd#endif 122178872Spjd/* Kabylake-LP */ 123178872Spjd#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) 124178872Spjd { 125178872Spjd .flags = FLAG_SST, 126186286Sivoras .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, 127186286Sivoras .dmi_table = (const struct dmi_system_id []) { 128186286Sivoras { 129172696Salfred .ident = "Google Chromebooks", 1301541Srgrimes .matches = { 1311541Srgrimes DMI_MATCH(DMI_SYS_VENDOR, "Google"), 1321541Srgrimes } 1331541Srgrimes }, 1341541Srgrimes {} 1359759Sbde } 13667046Sjasone }, 137186522Sbz { 138186522Sbz .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 139186522Sbz .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, 140186522Sbz }, 141186522Sbz#endif 142186522Sbz 143186522Sbz/* 144186522Sbz * Geminilake uses legacy HDAudio driver except for Google 145185772Sjkim * Chromebooks and devices based on the ES8336 codec 146185772Sjkim */ 147185772Sjkim/* Geminilake */ 148185772Sjkim#if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 149185772Sjkim { 150185772Sjkim .flags = FLAG_SOF, 151185772Sjkim .device = PCI_DEVICE_ID_INTEL_HDA_GML, 152184326Ssobomax .dmi_table = (const struct dmi_system_id []) { 153184323Ssobomax { 154184323Ssobomax .ident = "Google Chromebooks", 155184323Ssobomax .matches = { 156184323Ssobomax DMI_MATCH(DMI_SYS_VENDOR, "Google"), 157184323Ssobomax } 158184323Ssobomax }, 159184323Ssobomax {} 160186286Sivoras } 161186286Sivoras }, 162186286Sivoras { 163186286Sivoras .flags = FLAG_SOF, 164186252Sivoras .device = PCI_DEVICE_ID_INTEL_HDA_GML, 165184323Ssobomax .codec_hid = &essx_83x6, 166184323Ssobomax }, 167184323Ssobomax#endif 168184323Ssobomax 169184323Ssobomax/* 170185772Sjkim * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake, AlderLake, 171185772Sjkim * RaptorLake use legacy HDAudio driver except for Google Chromebooks 172185772Sjkim * and when DMICs are present. Two cases are required since Coreboot 173185772Sjkim * does not expose NHLT tables. 174185772Sjkim * 175186252Sivoras * When the Chromebook quirk is not present, it's based on information 176185772Sjkim * that no such device exists. When the quirk is present, it could be 177185772Sjkim * either based on product information or a placeholder. 178185772Sjkim */ 179184323Ssobomax 180184323Ssobomax/* Cannonlake */ 181185772Sjkim#if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 182185772Sjkim { 183185772Sjkim .flags = FLAG_SOF, 184186252Sivoras .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 185185772Sjkim .dmi_table = (const struct dmi_system_id []) { 186185772Sjkim { 187184323Ssobomax .ident = "Google Chromebooks", 188186252Sivoras .matches = { 189184323Ssobomax DMI_MATCH(DMI_SYS_VENDOR, "Google"), 190186522Sbz } 191184323Ssobomax }, 19267046Sjasone { 19387546Sdillon .ident = "UP-WHL", 19480418Speter .matches = { 19580418Speter DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 19687546Sdillon } 19780418Speter }, 198186252Sivoras {} 199186252Sivoras } 200186252Sivoras }, 201186252Sivoras { 202186252Sivoras .flags = FLAG_SOF, 203184323Ssobomax .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 20480418Speter .codec_hid = &essx_83x6, 205185772Sjkim }, 206186252Sivoras { 20780418Speter .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 20880418Speter .device = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, 20981986Sdillon }, 21081933Sdillon#endif 21181986Sdillon 212189595Sjhb/* Coffelake */ 21381986Sdillon#if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 21481933Sdillon { 21581986Sdillon .flags = FLAG_SOF, 216189595Sjhb .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, 21784783Sps .dmi_table = (const struct dmi_system_id []) { 21884783Sps { 219137393Sdes .ident = "Google Chromebooks", 22084783Sps .matches = { 221137393Sdes DMI_MATCH(DMI_SYS_VENDOR, "Google"), 22284783Sps } 223137393Sdes }, 22484783Sps {} 225137393Sdes } 22684783Sps }, 227137393Sdes { 22884783Sps .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 229137393Sdes .device = PCI_DEVICE_ID_INTEL_HDA_CNL_H, 23080418Speter }, 23187546Sdillon#endif 23287546Sdillon 23387546Sdillon#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 23487546Sdillon/* Cometlake-LP */ 23587546Sdillon { 236102600Speter .flags = FLAG_SOF, 23787546Sdillon .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 23887546Sdillon .dmi_table = (const struct dmi_system_id []) { 23987546Sdillon { 24090274Sdillon .ident = "Google Chromebooks", 24190274Sdillon .matches = { 24290274Sdillon DMI_MATCH(DMI_SYS_VENDOR, "Google"), 24389769Sdillon } 24487546Sdillon }, 24587546Sdillon { 24689769Sdillon .matches = { 24789769Sdillon DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 24887546Sdillon DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 24987546Sdillon }, 25087546Sdillon }, 25187546Sdillon { 25287546Sdillon /* early version of SKU 09C6 */ 25387546Sdillon .matches = { 25487546Sdillon DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 25587546Sdillon DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 25691780Ssilby }, 25791780Ssilby }, 25891780Ssilby {} 25991780Ssilby } 26091780Ssilby }, 26191780Ssilby { 26287546Sdillon .flags = FLAG_SOF, 26387546Sdillon .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 26487817Ssilby .codec_hid = &essx_83x6, 26587817Ssilby }, 266117391Ssilby { 267117391Ssilby .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 268117391Ssilby .device = PCI_DEVICE_ID_INTEL_HDA_CML_LP, 269117391Ssilby }, 270117391Ssilby/* Cometlake-H */ 271117391Ssilby { 27287546Sdillon .flags = FLAG_SOF, 273117391Ssilby .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 274117391Ssilby .dmi_table = (const struct dmi_system_id []) { 275117391Ssilby { 276117391Ssilby .matches = { 277117391Ssilby DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 278180262Salc DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 279117391Ssilby }, 280117391Ssilby }, 281117391Ssilby { 282117391Ssilby .matches = { 283127612Salc DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 28487546Sdillon DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 285180262Salc }, 286127612Salc }, 287117325Ssilby {} 288118764Ssilby } 289117325Ssilby }, 290117325Ssilby { 291189649Sjhb .flags = FLAG_SOF, 29287546Sdillon .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 293186286Sivoras .codec_hid = &essx_83x6, 294186286Sivoras }, 295186286Sivoras { 296186286Sivoras .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 297186286Sivoras .device = PCI_DEVICE_ID_INTEL_HDA_CML_H, 298186286Sivoras }, 299186286Sivoras#endif 300186286Sivoras 301186286Sivoras/* Icelake */ 302186286Sivoras#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 546static 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 if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) 562 break; 563 if (i == table->codec_hid->num_codecs) 564 continue; 565 } 566 return table; 567 } 568 return NULL; 569} 570 571static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 572{ 573 struct nhlt_acpi_table *nhlt; 574 int ret = 0; 575 576 nhlt = intel_nhlt_init(&pci->dev); 577 if (nhlt) { 578 if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC)) 579 ret = 1; 580 intel_nhlt_free(nhlt); 581 } 582 return ret; 583} 584 585#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 586static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 587{ 588 struct sdw_intel_acpi_info info; 589 acpi_handle handle; 590 int ret; 591 592 handle = ACPI_HANDLE(&pci->dev); 593 594 ret = sdw_intel_acpi_scan(handle, &info); 595 if (ret < 0) 596 return ret; 597 598 return info.link_mask; 599} 600#else 601static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 602{ 603 return 0; 604} 605#endif 606 607int snd_intel_dsp_driver_probe(struct pci_dev *pci) 608{ 609 const struct config_entry *cfg; 610 611 /* Intel vendor only */ 612 if (pci->vendor != PCI_VENDOR_ID_INTEL) 613 return SND_INTEL_DSP_DRIVER_ANY; 614 615 /* 616 * Legacy devices don't have a PCI-based DSP and use HDaudio 617 * for HDMI/DP support, ignore kernel parameter 618 */ 619 switch (pci->device) { 620 case PCI_DEVICE_ID_INTEL_HDA_BDW: 621 case PCI_DEVICE_ID_INTEL_HDA_HSW_0: 622 case PCI_DEVICE_ID_INTEL_HDA_HSW_2: 623 case PCI_DEVICE_ID_INTEL_HDA_HSW_3: 624 case PCI_DEVICE_ID_INTEL_HDA_BYT: 625 case PCI_DEVICE_ID_INTEL_HDA_BSW: 626 return SND_INTEL_DSP_DRIVER_ANY; 627 } 628 629 if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 630 return dsp_driver; 631 632 /* 633 * detect DSP by checking class/subclass/prog-id information 634 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 635 * class=04 subclass 01 prog-if 00: DSP is present 636 * (and may be required e.g. for DMIC or SSP support) 637 * class=04 subclass 03 prog-if 80: use DSP or legacy mode 638 */ 639 if (pci->class == 0x040300) 640 return SND_INTEL_DSP_DRIVER_LEGACY; 641 if (pci->class != 0x040100 && pci->class != 0x040380) { 642 dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 643 return SND_INTEL_DSP_DRIVER_LEGACY; 644 } 645 646 dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 647 648 /* find the configuration for the specific device */ 649 cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 650 if (!cfg) 651 return SND_INTEL_DSP_DRIVER_ANY; 652 653 if (cfg->flags & FLAG_SOF) { 654 if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 655 snd_intel_dsp_check_soundwire(pci) > 0) { 656 dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 657 return SND_INTEL_DSP_DRIVER_SOF; 658 } 659 if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 660 snd_intel_dsp_check_dmic(pci)) { 661 dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 662 return SND_INTEL_DSP_DRIVER_SOF; 663 } 664 if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 665 return SND_INTEL_DSP_DRIVER_SOF; 666 } 667 668 669 if (cfg->flags & FLAG_SST) { 670 if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 671 if (snd_intel_dsp_check_dmic(pci)) { 672 dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 673 return SND_INTEL_DSP_DRIVER_SST; 674 } 675 } else { 676 return SND_INTEL_DSP_DRIVER_SST; 677 } 678 } 679 680 return SND_INTEL_DSP_DRIVER_LEGACY; 681} 682EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 683 684/* Should we default to SOF or SST for BYT/CHT ? */ 685#if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ 686 !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 687#define FLAG_SST_OR_SOF_BYT FLAG_SOF 688#else 689#define FLAG_SST_OR_SOF_BYT FLAG_SST 690#endif 691 692/* 693 * configuration table 694 * - the order of similar ACPI ID entries is important! 695 * - the first successful match will win 696 */ 697static const struct config_entry acpi_config_table[] = { 698#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ 699 IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 700/* BayTrail */ 701 { 702 .flags = FLAG_SST_OR_SOF_BYT, 703 .acpi_hid = "80860F28", 704 }, 705/* CherryTrail */ 706 { 707 .flags = FLAG_SST_OR_SOF_BYT, 708 .acpi_hid = "808622A8", 709 }, 710#endif 711/* Broadwell */ 712#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 713 { 714 .flags = FLAG_SST, 715 .acpi_hid = "INT3438" 716 }, 717#endif 718#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) 719 { 720 .flags = FLAG_SOF, 721 .acpi_hid = "INT3438" 722 }, 723#endif 724/* Haswell - not supported by SOF but added for consistency */ 725#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 726 { 727 .flags = FLAG_SST, 728 .acpi_hid = "INT33C8" 729 }, 730#endif 731}; 732 733static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 734 const struct config_entry *table, 735 u32 len) 736{ 737 for (; len > 0; len--, table++) { 738 if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 739 continue; 740 if (table->dmi_table && !dmi_check_system(table->dmi_table)) 741 continue; 742 return table; 743 } 744 return NULL; 745} 746 747int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 748{ 749 const struct config_entry *cfg; 750 751 if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 752 return dsp_driver; 753 754 if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 755 dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 756 SND_INTEL_DSP_DRIVER_LEGACY); 757 } 758 759 /* find the configuration for the specific device */ 760 cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 761 ARRAY_SIZE(acpi_config_table)); 762 if (!cfg) 763 return SND_INTEL_DSP_DRIVER_ANY; 764 765 if (cfg->flags & FLAG_SST) 766 return SND_INTEL_DSP_DRIVER_SST; 767 768 if (cfg->flags & FLAG_SOF) 769 return SND_INTEL_DSP_DRIVER_SOF; 770 771 return SND_INTEL_DSP_DRIVER_SST; 772} 773EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 774 775MODULE_LICENSE("GPL v2"); 776MODULE_DESCRIPTION("Intel DSP config driver"); 777MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); 778