182d9d54aSJaroslav Kysela // SPDX-License-Identifier: GPL-2.0 282d9d54aSJaroslav Kysela // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz> 382d9d54aSJaroslav Kysela 406508575SPierre-Louis Bossart #include <linux/acpi.h> 582d9d54aSJaroslav Kysela #include <linux/bits.h> 682d9d54aSJaroslav Kysela #include <linux/dmi.h> 782d9d54aSJaroslav Kysela #include <linux/module.h> 882d9d54aSJaroslav Kysela #include <linux/pci.h> 906508575SPierre-Louis Bossart #include <linux/soundwire/sdw.h> 1006508575SPierre-Louis Bossart #include <linux/soundwire/sdw_intel.h> 1182d9d54aSJaroslav Kysela #include <sound/core.h> 1282d9d54aSJaroslav Kysela #include <sound/intel-dsp-config.h> 1382d9d54aSJaroslav Kysela #include <sound/intel-nhlt.h> 1482d9d54aSJaroslav Kysela 1582d9d54aSJaroslav Kysela static int dsp_driver; 1682d9d54aSJaroslav Kysela 1782d9d54aSJaroslav Kysela module_param(dsp_driver, int, 0444); 1882d9d54aSJaroslav Kysela MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)"); 1982d9d54aSJaroslav Kysela 2082d9d54aSJaroslav Kysela #define FLAG_SST BIT(0) 2182d9d54aSJaroslav Kysela #define FLAG_SOF BIT(1) 2282d9d54aSJaroslav Kysela #define FLAG_SOF_ONLY_IF_DMIC BIT(16) 2306508575SPierre-Louis Bossart #define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) 2406508575SPierre-Louis Bossart 2506508575SPierre-Louis Bossart #define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ 2606508575SPierre-Louis Bossart FLAG_SOF_ONLY_IF_SOUNDWIRE) 2782d9d54aSJaroslav Kysela 2882d9d54aSJaroslav Kysela struct config_entry { 2982d9d54aSJaroslav Kysela u32 flags; 3082d9d54aSJaroslav Kysela u16 device; 3182d9d54aSJaroslav Kysela const struct dmi_system_id *dmi_table; 3282d9d54aSJaroslav Kysela }; 3382d9d54aSJaroslav Kysela 3482d9d54aSJaroslav Kysela /* 3582d9d54aSJaroslav Kysela * configuration table 3682d9d54aSJaroslav Kysela * - the order of similar PCI ID entries is important! 3782d9d54aSJaroslav Kysela * - the first successful match will win 3882d9d54aSJaroslav Kysela */ 3982d9d54aSJaroslav Kysela static const struct config_entry config_table[] = { 4082d9d54aSJaroslav Kysela /* Merrifield */ 4182d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 4282d9d54aSJaroslav Kysela { 4382d9d54aSJaroslav Kysela .flags = FLAG_SOF, 4482d9d54aSJaroslav Kysela .device = 0x119a, 4582d9d54aSJaroslav Kysela }, 4682d9d54aSJaroslav Kysela #endif 4782d9d54aSJaroslav Kysela /* Broxton-T */ 4882d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 4982d9d54aSJaroslav Kysela { 50cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 5182d9d54aSJaroslav Kysela .device = 0x1a98, 5282d9d54aSJaroslav Kysela }, 5382d9d54aSJaroslav Kysela #endif 54cc8f81c7SPierre-Louis Bossart /* 55cc8f81c7SPierre-Louis Bossart * Apollolake (Broxton-P) 56cc8f81c7SPierre-Louis Bossart * the legacy HDaudio driver is used except on Up Squared (SOF) and 57cc8f81c7SPierre-Louis Bossart * Chromebooks (SST) 58cc8f81c7SPierre-Louis Bossart */ 5982d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 6082d9d54aSJaroslav Kysela { 6182d9d54aSJaroslav Kysela .flags = FLAG_SOF, 6282d9d54aSJaroslav Kysela .device = 0x5a98, 6382d9d54aSJaroslav Kysela .dmi_table = (const struct dmi_system_id []) { 6482d9d54aSJaroslav Kysela { 6582d9d54aSJaroslav Kysela .ident = "Up Squared", 6682d9d54aSJaroslav Kysela .matches = { 6782d9d54aSJaroslav Kysela DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 6882d9d54aSJaroslav Kysela DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), 6982d9d54aSJaroslav Kysela } 7082d9d54aSJaroslav Kysela }, 7182d9d54aSJaroslav Kysela {} 7282d9d54aSJaroslav Kysela } 7382d9d54aSJaroslav Kysela }, 7482d9d54aSJaroslav Kysela #endif 7582d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) 7682d9d54aSJaroslav Kysela { 7782d9d54aSJaroslav Kysela .flags = FLAG_SST, 7882d9d54aSJaroslav Kysela .device = 0x5a98, 79cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 80cc8f81c7SPierre-Louis Bossart { 81cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 82cc8f81c7SPierre-Louis Bossart .matches = { 83cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 84cc8f81c7SPierre-Louis Bossart } 85cc8f81c7SPierre-Louis Bossart }, 86cc8f81c7SPierre-Louis Bossart {} 87cc8f81c7SPierre-Louis Bossart } 8882d9d54aSJaroslav Kysela }, 8982d9d54aSJaroslav Kysela #endif 90cc8f81c7SPierre-Louis Bossart /* 91cc8f81c7SPierre-Louis Bossart * Skylake and Kabylake use legacy HDaudio driver except for Google 92cc8f81c7SPierre-Louis Bossart * Chromebooks (SST) 93cc8f81c7SPierre-Louis Bossart */ 94cc8f81c7SPierre-Louis Bossart 95cc8f81c7SPierre-Louis Bossart /* Sunrise Point-LP */ 96cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) 97cc8f81c7SPierre-Louis Bossart { 98cc8f81c7SPierre-Louis Bossart .flags = FLAG_SST, 99cc8f81c7SPierre-Louis Bossart .device = 0x9d70, 100cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 101cc8f81c7SPierre-Louis Bossart { 102cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 103cc8f81c7SPierre-Louis Bossart .matches = { 104cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 105cc8f81c7SPierre-Louis Bossart } 106cc8f81c7SPierre-Louis Bossart }, 107cc8f81c7SPierre-Louis Bossart {} 108cc8f81c7SPierre-Louis Bossart } 109cc8f81c7SPierre-Louis Bossart }, 110cc8f81c7SPierre-Louis Bossart #endif 111cc8f81c7SPierre-Louis Bossart /* Kabylake-LP */ 112cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) 113cc8f81c7SPierre-Louis Bossart { 114cc8f81c7SPierre-Louis Bossart .flags = FLAG_SST, 115cc8f81c7SPierre-Louis Bossart .device = 0x9d71, 116cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 117cc8f81c7SPierre-Louis Bossart { 118cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 119cc8f81c7SPierre-Louis Bossart .matches = { 120cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 121cc8f81c7SPierre-Louis Bossart } 122cc8f81c7SPierre-Louis Bossart }, 123cc8f81c7SPierre-Louis Bossart {} 124cc8f81c7SPierre-Louis Bossart } 125cc8f81c7SPierre-Louis Bossart }, 126cc8f81c7SPierre-Louis Bossart #endif 127cc8f81c7SPierre-Louis Bossart 128cc8f81c7SPierre-Louis Bossart /* 129cc8f81c7SPierre-Louis Bossart * Geminilake uses legacy HDaudio driver except for Google 130cc8f81c7SPierre-Louis Bossart * Chromebooks 131cc8f81c7SPierre-Louis Bossart */ 132cc8f81c7SPierre-Louis Bossart /* Geminilake */ 133cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 134cc8f81c7SPierre-Louis Bossart { 135cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 136cc8f81c7SPierre-Louis Bossart .device = 0x3198, 137cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 138cc8f81c7SPierre-Louis Bossart { 139cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 140cc8f81c7SPierre-Louis Bossart .matches = { 141cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 142cc8f81c7SPierre-Louis Bossart } 143cc8f81c7SPierre-Louis Bossart }, 144cc8f81c7SPierre-Louis Bossart {} 145cc8f81c7SPierre-Louis Bossart } 146cc8f81c7SPierre-Louis Bossart }, 147cc8f81c7SPierre-Louis Bossart #endif 148cc8f81c7SPierre-Louis Bossart 149cc8f81c7SPierre-Louis Bossart /* 150cc8f81c7SPierre-Louis Bossart * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake use legacy 151cc8f81c7SPierre-Louis Bossart * HDaudio driver except for Google Chromebooks and when DMICs are 152cc8f81c7SPierre-Louis Bossart * present. Two cases are required since Coreboot does not expose NHLT 153cc8f81c7SPierre-Louis Bossart * tables. 154cc8f81c7SPierre-Louis Bossart * 155cc8f81c7SPierre-Louis Bossart * When the Chromebook quirk is not present, it's based on information 156cc8f81c7SPierre-Louis Bossart * that no such device exists. When the quirk is present, it could be 157cc8f81c7SPierre-Louis Bossart * either based on product information or a placeholder. 158cc8f81c7SPierre-Louis Bossart */ 159cc8f81c7SPierre-Louis Bossart 16082d9d54aSJaroslav Kysela /* Cannonlake */ 16182d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 16282d9d54aSJaroslav Kysela { 163cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 164cc8f81c7SPierre-Louis Bossart .device = 0x9dc8, 165cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 166cc8f81c7SPierre-Louis Bossart { 167cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 168cc8f81c7SPierre-Louis Bossart .matches = { 169cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 170cc8f81c7SPierre-Louis Bossart } 171cc8f81c7SPierre-Louis Bossart }, 172cc8f81c7SPierre-Louis Bossart {} 173cc8f81c7SPierre-Louis Bossart } 174cc8f81c7SPierre-Louis Bossart }, 175cc8f81c7SPierre-Louis Bossart { 17606508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 17782d9d54aSJaroslav Kysela .device = 0x9dc8, 17882d9d54aSJaroslav Kysela }, 17982d9d54aSJaroslav Kysela #endif 180cc8f81c7SPierre-Louis Bossart 18182d9d54aSJaroslav Kysela /* Coffelake */ 18282d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 18382d9d54aSJaroslav Kysela { 184cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 185cc8f81c7SPierre-Louis Bossart .device = 0xa348, 186cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 187cc8f81c7SPierre-Louis Bossart { 188cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 189cc8f81c7SPierre-Louis Bossart .matches = { 190cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 191cc8f81c7SPierre-Louis Bossart } 192cc8f81c7SPierre-Louis Bossart }, 193cc8f81c7SPierre-Louis Bossart {} 194cc8f81c7SPierre-Louis Bossart } 195cc8f81c7SPierre-Louis Bossart }, 196cc8f81c7SPierre-Louis Bossart { 19706508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 19882d9d54aSJaroslav Kysela .device = 0xa348, 19982d9d54aSJaroslav Kysela }, 20082d9d54aSJaroslav Kysela #endif 201cc8f81c7SPierre-Louis Bossart 202cc8f81c7SPierre-Louis Bossart /* Cometlake-LP */ 203cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) 204cc8f81c7SPierre-Louis Bossart { 205cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 206cc8f81c7SPierre-Louis Bossart .device = 0x02c8, 207cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 208cc8f81c7SPierre-Louis Bossart { 209cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 210cc8f81c7SPierre-Louis Bossart .matches = { 211cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 212cc8f81c7SPierre-Louis Bossart } 213cc8f81c7SPierre-Louis Bossart }, 21406508575SPierre-Louis Bossart { 21506508575SPierre-Louis Bossart .matches = { 21606508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 21706508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 21806508575SPierre-Louis Bossart }, 21906508575SPierre-Louis Bossart }, 22006508575SPierre-Louis Bossart { 22106508575SPierre-Louis Bossart /* early version of SKU 09C6 */ 22206508575SPierre-Louis Bossart .matches = { 22306508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 22406508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 22506508575SPierre-Louis Bossart }, 22606508575SPierre-Louis Bossart }, 227cc8f81c7SPierre-Louis Bossart {} 228cc8f81c7SPierre-Louis Bossart } 229cc8f81c7SPierre-Louis Bossart }, 230cc8f81c7SPierre-Louis Bossart { 23106508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 232cc8f81c7SPierre-Louis Bossart .device = 0x02c8, 233cc8f81c7SPierre-Louis Bossart }, 234cc8f81c7SPierre-Louis Bossart #endif 235cc8f81c7SPierre-Louis Bossart /* Cometlake-H */ 236cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) 237cc8f81c7SPierre-Louis Bossart { 23806508575SPierre-Louis Bossart .flags = FLAG_SOF, 23906508575SPierre-Louis Bossart .device = 0x06c8, 24006508575SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 24106508575SPierre-Louis Bossart { 24206508575SPierre-Louis Bossart .matches = { 24306508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 24406508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 24506508575SPierre-Louis Bossart }, 24606508575SPierre-Louis Bossart }, 24706508575SPierre-Louis Bossart { 24806508575SPierre-Louis Bossart .matches = { 24906508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 25006508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 25106508575SPierre-Louis Bossart }, 25206508575SPierre-Louis Bossart }, 25306508575SPierre-Louis Bossart {} 25406508575SPierre-Louis Bossart } 25506508575SPierre-Louis Bossart }, 25606508575SPierre-Louis Bossart { 25706508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 258cc8f81c7SPierre-Louis Bossart .device = 0x06c8, 259cc8f81c7SPierre-Louis Bossart }, 260cc8f81c7SPierre-Louis Bossart #endif 261cc8f81c7SPierre-Louis Bossart 262cc8f81c7SPierre-Louis Bossart /* Icelake */ 263cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 264cc8f81c7SPierre-Louis Bossart { 265cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 266cc8f81c7SPierre-Louis Bossart .device = 0x34c8, 267cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 268cc8f81c7SPierre-Louis Bossart { 269cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 270cc8f81c7SPierre-Louis Bossart .matches = { 271cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 272cc8f81c7SPierre-Louis Bossart } 273cc8f81c7SPierre-Louis Bossart }, 274cc8f81c7SPierre-Louis Bossart {} 275cc8f81c7SPierre-Louis Bossart } 276cc8f81c7SPierre-Louis Bossart }, 277cc8f81c7SPierre-Louis Bossart { 27806508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 279cc8f81c7SPierre-Louis Bossart .device = 0x34c8, 280cc8f81c7SPierre-Louis Bossart }, 281cc8f81c7SPierre-Louis Bossart #endif 282cc8f81c7SPierre-Louis Bossart 283cc8f81c7SPierre-Louis Bossart /* Tigerlake */ 284cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 285cc8f81c7SPierre-Louis Bossart { 286cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 287cc8f81c7SPierre-Louis Bossart .device = 0xa0c8, 288cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 289cc8f81c7SPierre-Louis Bossart { 290cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 291cc8f81c7SPierre-Louis Bossart .matches = { 292cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 293cc8f81c7SPierre-Louis Bossart } 294cc8f81c7SPierre-Louis Bossart }, 295cc8f81c7SPierre-Louis Bossart {} 296cc8f81c7SPierre-Louis Bossart } 297cc8f81c7SPierre-Louis Bossart }, 298cc8f81c7SPierre-Louis Bossart { 29906508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 300cc8f81c7SPierre-Louis Bossart .device = 0xa0c8, 301cc8f81c7SPierre-Louis Bossart }, 302cc8f81c7SPierre-Louis Bossart #endif 303cc8f81c7SPierre-Louis Bossart 304cc8f81c7SPierre-Louis Bossart /* Elkhart Lake */ 305cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 306cc8f81c7SPierre-Louis Bossart { 307cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 308cc8f81c7SPierre-Louis Bossart .device = 0x4b55, 309cc8f81c7SPierre-Louis Bossart }, 310cc8f81c7SPierre-Louis Bossart #endif 311cc8f81c7SPierre-Louis Bossart 31282d9d54aSJaroslav Kysela }; 31382d9d54aSJaroslav Kysela 31482d9d54aSJaroslav Kysela static const struct config_entry *snd_intel_dsp_find_config 31582d9d54aSJaroslav Kysela (struct pci_dev *pci, const struct config_entry *table, u32 len) 31682d9d54aSJaroslav Kysela { 31782d9d54aSJaroslav Kysela u16 device; 31882d9d54aSJaroslav Kysela 31982d9d54aSJaroslav Kysela device = pci->device; 32082d9d54aSJaroslav Kysela for (; len > 0; len--, table++) { 32182d9d54aSJaroslav Kysela if (table->device != device) 32282d9d54aSJaroslav Kysela continue; 32382d9d54aSJaroslav Kysela if (table->dmi_table && !dmi_check_system(table->dmi_table)) 32482d9d54aSJaroslav Kysela continue; 32582d9d54aSJaroslav Kysela return table; 32682d9d54aSJaroslav Kysela } 32782d9d54aSJaroslav Kysela return NULL; 32882d9d54aSJaroslav Kysela } 32982d9d54aSJaroslav Kysela 33082d9d54aSJaroslav Kysela static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 33182d9d54aSJaroslav Kysela { 33282d9d54aSJaroslav Kysela struct nhlt_acpi_table *nhlt; 33382d9d54aSJaroslav Kysela int ret = 0; 33482d9d54aSJaroslav Kysela 33582d9d54aSJaroslav Kysela nhlt = intel_nhlt_init(&pci->dev); 33682d9d54aSJaroslav Kysela if (nhlt) { 33782d9d54aSJaroslav Kysela if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) 33882d9d54aSJaroslav Kysela ret = 1; 33982d9d54aSJaroslav Kysela intel_nhlt_free(nhlt); 34082d9d54aSJaroslav Kysela } 34182d9d54aSJaroslav Kysela return ret; 34282d9d54aSJaroslav Kysela } 34382d9d54aSJaroslav Kysela 34406508575SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 34506508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 34606508575SPierre-Louis Bossart { 34706508575SPierre-Louis Bossart struct sdw_intel_acpi_info info; 34806508575SPierre-Louis Bossart acpi_handle handle; 34906508575SPierre-Louis Bossart int ret; 35006508575SPierre-Louis Bossart 35106508575SPierre-Louis Bossart handle = ACPI_HANDLE(&pci->dev); 35206508575SPierre-Louis Bossart 35306508575SPierre-Louis Bossart ret = sdw_intel_acpi_scan(handle, &info); 35406508575SPierre-Louis Bossart if (ret < 0) 35506508575SPierre-Louis Bossart return ret; 35606508575SPierre-Louis Bossart 35706508575SPierre-Louis Bossart return info.link_mask; 35806508575SPierre-Louis Bossart } 35906508575SPierre-Louis Bossart #else 36006508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 36106508575SPierre-Louis Bossart { 36206508575SPierre-Louis Bossart return 0; 36306508575SPierre-Louis Bossart } 36406508575SPierre-Louis Bossart #endif 36506508575SPierre-Louis Bossart 36682d9d54aSJaroslav Kysela int snd_intel_dsp_driver_probe(struct pci_dev *pci) 36782d9d54aSJaroslav Kysela { 36882d9d54aSJaroslav Kysela const struct config_entry *cfg; 36982d9d54aSJaroslav Kysela 37091636a82STakashi Iwai /* Intel vendor only */ 37191636a82STakashi Iwai if (pci->vendor != 0x8086) 37291636a82STakashi Iwai return SND_INTEL_DSP_DRIVER_ANY; 37391636a82STakashi Iwai 37482d9d54aSJaroslav Kysela if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 37582d9d54aSJaroslav Kysela return dsp_driver; 37682d9d54aSJaroslav Kysela 37782d9d54aSJaroslav Kysela /* 37882d9d54aSJaroslav Kysela * detect DSP by checking class/subclass/prog-id information 37982d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 38082d9d54aSJaroslav Kysela * class=04 subclass 01 prog-if 00: DSP is present 38182d9d54aSJaroslav Kysela * (and may be required e.g. for DMIC or SSP support) 38282d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 80: use DSP or legacy mode 38382d9d54aSJaroslav Kysela */ 38482d9d54aSJaroslav Kysela if (pci->class == 0x040300) 38582d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 38682d9d54aSJaroslav Kysela if (pci->class != 0x040100 && pci->class != 0x040380) { 38782d9d54aSJaroslav Kysela dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDA legacy driver\n", pci->class); 38882d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 38982d9d54aSJaroslav Kysela } 39082d9d54aSJaroslav Kysela 39182d9d54aSJaroslav Kysela dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 39282d9d54aSJaroslav Kysela 39382d9d54aSJaroslav Kysela /* find the configuration for the specific device */ 39482d9d54aSJaroslav Kysela cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 39582d9d54aSJaroslav Kysela if (!cfg) 39682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_ANY; 39782d9d54aSJaroslav Kysela 39882d9d54aSJaroslav Kysela if (cfg->flags & FLAG_SOF) { 39906508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 40006508575SPierre-Louis Bossart snd_intel_dsp_check_soundwire(pci) > 0) { 40106508575SPierre-Louis Bossart dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 40206508575SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 40306508575SPierre-Louis Bossart } 40406508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 40506508575SPierre-Louis Bossart snd_intel_dsp_check_dmic(pci)) { 40682d9d54aSJaroslav Kysela dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 40782d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 40882d9d54aSJaroslav Kysela } 40906508575SPierre-Louis Bossart if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 41082d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 41182d9d54aSJaroslav Kysela } 41282d9d54aSJaroslav Kysela 41382d9d54aSJaroslav Kysela if (cfg->flags & FLAG_SST) 41482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SST; 41582d9d54aSJaroslav Kysela 41682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 41782d9d54aSJaroslav Kysela } 41882d9d54aSJaroslav Kysela EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 41982d9d54aSJaroslav Kysela 42082d9d54aSJaroslav Kysela MODULE_LICENSE("GPL v2"); 42182d9d54aSJaroslav Kysela MODULE_DESCRIPTION("Intel DSP config driver"); 42206508575SPierre-Louis Bossart MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); 423