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) 22df1fceacSCezary Rojewski #define FLAG_SST_ONLY_IF_DMIC BIT(15) 2382d9d54aSJaroslav Kysela #define FLAG_SOF_ONLY_IF_DMIC BIT(16) 2406508575SPierre-Louis Bossart #define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) 2506508575SPierre-Louis Bossart 2606508575SPierre-Louis Bossart #define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ 2706508575SPierre-Louis Bossart FLAG_SOF_ONLY_IF_SOUNDWIRE) 2882d9d54aSJaroslav Kysela 2982d9d54aSJaroslav Kysela struct config_entry { 3082d9d54aSJaroslav Kysela u32 flags; 3182d9d54aSJaroslav Kysela u16 device; 32*b5682305SPierre-Louis Bossart u8 acpi_hid[ACPI_ID_LEN]; 3382d9d54aSJaroslav Kysela const struct dmi_system_id *dmi_table; 3482d9d54aSJaroslav Kysela }; 3582d9d54aSJaroslav Kysela 3682d9d54aSJaroslav Kysela /* 3782d9d54aSJaroslav Kysela * configuration table 3882d9d54aSJaroslav Kysela * - the order of similar PCI ID entries is important! 3982d9d54aSJaroslav Kysela * - the first successful match will win 4082d9d54aSJaroslav Kysela */ 4182d9d54aSJaroslav Kysela static const struct config_entry config_table[] = { 4282d9d54aSJaroslav Kysela /* Merrifield */ 4382d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) 4482d9d54aSJaroslav Kysela { 4582d9d54aSJaroslav Kysela .flags = FLAG_SOF, 4682d9d54aSJaroslav Kysela .device = 0x119a, 4782d9d54aSJaroslav Kysela }, 4882d9d54aSJaroslav Kysela #endif 4982d9d54aSJaroslav Kysela /* Broxton-T */ 5082d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 5182d9d54aSJaroslav Kysela { 52cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 5382d9d54aSJaroslav Kysela .device = 0x1a98, 5482d9d54aSJaroslav Kysela }, 5582d9d54aSJaroslav Kysela #endif 56cc8f81c7SPierre-Louis Bossart /* 57cc8f81c7SPierre-Louis Bossart * Apollolake (Broxton-P) 58b79de57bSPierre-Louis Bossart * the legacy HDAudio driver is used except on Up Squared (SOF) and 59cc8f81c7SPierre-Louis Bossart * Chromebooks (SST) 60cc8f81c7SPierre-Louis Bossart */ 6182d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) 6282d9d54aSJaroslav Kysela { 6382d9d54aSJaroslav Kysela .flags = FLAG_SOF, 6482d9d54aSJaroslav Kysela .device = 0x5a98, 6582d9d54aSJaroslav Kysela .dmi_table = (const struct dmi_system_id []) { 6682d9d54aSJaroslav Kysela { 6782d9d54aSJaroslav Kysela .ident = "Up Squared", 6882d9d54aSJaroslav Kysela .matches = { 6982d9d54aSJaroslav Kysela DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 7082d9d54aSJaroslav Kysela DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), 7182d9d54aSJaroslav Kysela } 7282d9d54aSJaroslav Kysela }, 7382d9d54aSJaroslav Kysela {} 7482d9d54aSJaroslav Kysela } 7582d9d54aSJaroslav Kysela }, 7682d9d54aSJaroslav Kysela #endif 7782d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) 7882d9d54aSJaroslav Kysela { 7982d9d54aSJaroslav Kysela .flags = FLAG_SST, 8082d9d54aSJaroslav Kysela .device = 0x5a98, 81cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 82cc8f81c7SPierre-Louis Bossart { 83cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 84cc8f81c7SPierre-Louis Bossart .matches = { 85cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 86cc8f81c7SPierre-Louis Bossart } 87cc8f81c7SPierre-Louis Bossart }, 88cc8f81c7SPierre-Louis Bossart {} 89cc8f81c7SPierre-Louis Bossart } 9082d9d54aSJaroslav Kysela }, 9182d9d54aSJaroslav Kysela #endif 92cc8f81c7SPierre-Louis Bossart /* 93b79de57bSPierre-Louis Bossart * Skylake and Kabylake use legacy HDAudio driver except for Google 94cc8f81c7SPierre-Louis Bossart * Chromebooks (SST) 95cc8f81c7SPierre-Louis Bossart */ 96cc8f81c7SPierre-Louis Bossart 97cc8f81c7SPierre-Louis Bossart /* Sunrise Point-LP */ 98cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) 99cc8f81c7SPierre-Louis Bossart { 100cc8f81c7SPierre-Louis Bossart .flags = FLAG_SST, 101cc8f81c7SPierre-Louis Bossart .device = 0x9d70, 102cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 103cc8f81c7SPierre-Louis Bossart { 104cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 105cc8f81c7SPierre-Louis Bossart .matches = { 106cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 107cc8f81c7SPierre-Louis Bossart } 108cc8f81c7SPierre-Louis Bossart }, 109cc8f81c7SPierre-Louis Bossart {} 110cc8f81c7SPierre-Louis Bossart } 111cc8f81c7SPierre-Louis Bossart }, 112df1fceacSCezary Rojewski { 113df1fceacSCezary Rojewski .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 114df1fceacSCezary Rojewski .device = 0x9d70, 115df1fceacSCezary Rojewski }, 116cc8f81c7SPierre-Louis Bossart #endif 117cc8f81c7SPierre-Louis Bossart /* Kabylake-LP */ 118cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) 119cc8f81c7SPierre-Louis Bossart { 120cc8f81c7SPierre-Louis Bossart .flags = FLAG_SST, 121cc8f81c7SPierre-Louis Bossart .device = 0x9d71, 122cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 123cc8f81c7SPierre-Louis Bossart { 124cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 125cc8f81c7SPierre-Louis Bossart .matches = { 126cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 127cc8f81c7SPierre-Louis Bossart } 128cc8f81c7SPierre-Louis Bossart }, 129cc8f81c7SPierre-Louis Bossart {} 130cc8f81c7SPierre-Louis Bossart } 131cc8f81c7SPierre-Louis Bossart }, 132df1fceacSCezary Rojewski { 133df1fceacSCezary Rojewski .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, 134df1fceacSCezary Rojewski .device = 0x9d71, 135df1fceacSCezary Rojewski }, 136cc8f81c7SPierre-Louis Bossart #endif 137cc8f81c7SPierre-Louis Bossart 138cc8f81c7SPierre-Louis Bossart /* 139b79de57bSPierre-Louis Bossart * Geminilake uses legacy HDAudio driver except for Google 140cc8f81c7SPierre-Louis Bossart * Chromebooks 141cc8f81c7SPierre-Louis Bossart */ 142cc8f81c7SPierre-Louis Bossart /* Geminilake */ 143cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) 144cc8f81c7SPierre-Louis Bossart { 145cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 146cc8f81c7SPierre-Louis Bossart .device = 0x3198, 147cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 148cc8f81c7SPierre-Louis Bossart { 149cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 150cc8f81c7SPierre-Louis Bossart .matches = { 151cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 152cc8f81c7SPierre-Louis Bossart } 153cc8f81c7SPierre-Louis Bossart }, 154cc8f81c7SPierre-Louis Bossart {} 155cc8f81c7SPierre-Louis Bossart } 156cc8f81c7SPierre-Louis Bossart }, 157cc8f81c7SPierre-Louis Bossart #endif 158cc8f81c7SPierre-Louis Bossart 159cc8f81c7SPierre-Louis Bossart /* 160cc8f81c7SPierre-Louis Bossart * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake use legacy 161b79de57bSPierre-Louis Bossart * HDAudio driver except for Google Chromebooks and when DMICs are 162cc8f81c7SPierre-Louis Bossart * present. Two cases are required since Coreboot does not expose NHLT 163cc8f81c7SPierre-Louis Bossart * tables. 164cc8f81c7SPierre-Louis Bossart * 165cc8f81c7SPierre-Louis Bossart * When the Chromebook quirk is not present, it's based on information 166cc8f81c7SPierre-Louis Bossart * that no such device exists. When the quirk is present, it could be 167cc8f81c7SPierre-Louis Bossart * either based on product information or a placeholder. 168cc8f81c7SPierre-Louis Bossart */ 169cc8f81c7SPierre-Louis Bossart 17082d9d54aSJaroslav Kysela /* Cannonlake */ 17182d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) 17282d9d54aSJaroslav Kysela { 173cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 174cc8f81c7SPierre-Louis Bossart .device = 0x9dc8, 175cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 176cc8f81c7SPierre-Louis Bossart { 177cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 178cc8f81c7SPierre-Louis Bossart .matches = { 179cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 180cc8f81c7SPierre-Louis Bossart } 181cc8f81c7SPierre-Louis Bossart }, 182cc8f81c7SPierre-Louis Bossart {} 183cc8f81c7SPierre-Louis Bossart } 184cc8f81c7SPierre-Louis Bossart }, 185cc8f81c7SPierre-Louis Bossart { 18606508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 18782d9d54aSJaroslav Kysela .device = 0x9dc8, 18882d9d54aSJaroslav Kysela }, 18982d9d54aSJaroslav Kysela #endif 190cc8f81c7SPierre-Louis Bossart 19182d9d54aSJaroslav Kysela /* Coffelake */ 19282d9d54aSJaroslav Kysela #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) 19382d9d54aSJaroslav Kysela { 194cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 195cc8f81c7SPierre-Louis Bossart .device = 0xa348, 196cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 197cc8f81c7SPierre-Louis Bossart { 198cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 199cc8f81c7SPierre-Louis Bossart .matches = { 200cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 201cc8f81c7SPierre-Louis Bossart } 202cc8f81c7SPierre-Louis Bossart }, 203cc8f81c7SPierre-Louis Bossart {} 204cc8f81c7SPierre-Louis Bossart } 205cc8f81c7SPierre-Louis Bossart }, 206cc8f81c7SPierre-Louis Bossart { 20706508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 20882d9d54aSJaroslav Kysela .device = 0xa348, 20982d9d54aSJaroslav Kysela }, 21082d9d54aSJaroslav Kysela #endif 211cc8f81c7SPierre-Louis Bossart 2124228668eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) 213cc8f81c7SPierre-Louis Bossart /* Cometlake-LP */ 214cc8f81c7SPierre-Louis Bossart { 215cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 216cc8f81c7SPierre-Louis Bossart .device = 0x02c8, 217cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 218cc8f81c7SPierre-Louis Bossart { 219cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 220cc8f81c7SPierre-Louis Bossart .matches = { 221cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 222cc8f81c7SPierre-Louis Bossart } 223cc8f81c7SPierre-Louis Bossart }, 22406508575SPierre-Louis Bossart { 22506508575SPierre-Louis Bossart .matches = { 22606508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 22706508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") 22806508575SPierre-Louis Bossart }, 22906508575SPierre-Louis Bossart }, 23006508575SPierre-Louis Bossart { 23106508575SPierre-Louis Bossart /* early version of SKU 09C6 */ 23206508575SPierre-Louis Bossart .matches = { 23306508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 23406508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") 23506508575SPierre-Louis Bossart }, 23606508575SPierre-Louis Bossart }, 237cc8f81c7SPierre-Louis Bossart {} 238cc8f81c7SPierre-Louis Bossart } 239cc8f81c7SPierre-Louis Bossart }, 240cc8f81c7SPierre-Louis Bossart { 24106508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 242cc8f81c7SPierre-Louis Bossart .device = 0x02c8, 243cc8f81c7SPierre-Louis Bossart }, 244cc8f81c7SPierre-Louis Bossart /* Cometlake-H */ 245cc8f81c7SPierre-Louis Bossart { 24606508575SPierre-Louis Bossart .flags = FLAG_SOF, 24706508575SPierre-Louis Bossart .device = 0x06c8, 24806508575SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 24906508575SPierre-Louis Bossart { 25006508575SPierre-Louis Bossart .matches = { 25106508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 25206508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), 25306508575SPierre-Louis Bossart }, 25406508575SPierre-Louis Bossart }, 25506508575SPierre-Louis Bossart { 25606508575SPierre-Louis Bossart .matches = { 25706508575SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 25806508575SPierre-Louis Bossart DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), 25906508575SPierre-Louis Bossart }, 26006508575SPierre-Louis Bossart }, 26106508575SPierre-Louis Bossart {} 26206508575SPierre-Louis Bossart } 26306508575SPierre-Louis Bossart }, 26406508575SPierre-Louis Bossart { 26506508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 266cc8f81c7SPierre-Louis Bossart .device = 0x06c8, 267cc8f81c7SPierre-Louis Bossart }, 268cc8f81c7SPierre-Louis Bossart #endif 269cc8f81c7SPierre-Louis Bossart 270cc8f81c7SPierre-Louis Bossart /* Icelake */ 271cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) 272cc8f81c7SPierre-Louis Bossart { 273cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 274cc8f81c7SPierre-Louis Bossart .device = 0x34c8, 275cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 276cc8f81c7SPierre-Louis Bossart { 277cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 278cc8f81c7SPierre-Louis Bossart .matches = { 279cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 280cc8f81c7SPierre-Louis Bossart } 281cc8f81c7SPierre-Louis Bossart }, 282cc8f81c7SPierre-Louis Bossart {} 283cc8f81c7SPierre-Louis Bossart } 284cc8f81c7SPierre-Louis Bossart }, 285cc8f81c7SPierre-Louis Bossart { 28606508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 287cc8f81c7SPierre-Louis Bossart .device = 0x34c8, 288cc8f81c7SPierre-Louis Bossart }, 289cc8f81c7SPierre-Louis Bossart #endif 290cc8f81c7SPierre-Louis Bossart 291cc8f81c7SPierre-Louis Bossart /* Tigerlake */ 292cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) 293cc8f81c7SPierre-Louis Bossart { 294cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF, 295cc8f81c7SPierre-Louis Bossart .device = 0xa0c8, 296cc8f81c7SPierre-Louis Bossart .dmi_table = (const struct dmi_system_id []) { 297cc8f81c7SPierre-Louis Bossart { 298cc8f81c7SPierre-Louis Bossart .ident = "Google Chromebooks", 299cc8f81c7SPierre-Louis Bossart .matches = { 300cc8f81c7SPierre-Louis Bossart DMI_MATCH(DMI_SYS_VENDOR, "Google"), 301cc8f81c7SPierre-Louis Bossart } 302cc8f81c7SPierre-Louis Bossart }, 303cc8f81c7SPierre-Louis Bossart {} 304cc8f81c7SPierre-Louis Bossart } 305cc8f81c7SPierre-Louis Bossart }, 306cc8f81c7SPierre-Louis Bossart { 30706508575SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 308cc8f81c7SPierre-Louis Bossart .device = 0xa0c8, 309cc8f81c7SPierre-Louis Bossart }, 310cc8f81c7SPierre-Louis Bossart #endif 311cc8f81c7SPierre-Louis Bossart 312cc8f81c7SPierre-Louis Bossart /* Elkhart Lake */ 313cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 314cc8f81c7SPierre-Louis Bossart { 315cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 316cc8f81c7SPierre-Louis Bossart .device = 0x4b55, 317cc8f81c7SPierre-Louis Bossart }, 318cc8f81c7SPierre-Louis Bossart #endif 319cc8f81c7SPierre-Louis Bossart 32082d9d54aSJaroslav Kysela }; 32182d9d54aSJaroslav Kysela 32282d9d54aSJaroslav Kysela static const struct config_entry *snd_intel_dsp_find_config 32382d9d54aSJaroslav Kysela (struct pci_dev *pci, const struct config_entry *table, u32 len) 32482d9d54aSJaroslav Kysela { 32582d9d54aSJaroslav Kysela u16 device; 32682d9d54aSJaroslav Kysela 32782d9d54aSJaroslav Kysela device = pci->device; 32882d9d54aSJaroslav Kysela for (; len > 0; len--, table++) { 32982d9d54aSJaroslav Kysela if (table->device != device) 33082d9d54aSJaroslav Kysela continue; 33182d9d54aSJaroslav Kysela if (table->dmi_table && !dmi_check_system(table->dmi_table)) 33282d9d54aSJaroslav Kysela continue; 33382d9d54aSJaroslav Kysela return table; 33482d9d54aSJaroslav Kysela } 33582d9d54aSJaroslav Kysela return NULL; 33682d9d54aSJaroslav Kysela } 33782d9d54aSJaroslav Kysela 33882d9d54aSJaroslav Kysela static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 33982d9d54aSJaroslav Kysela { 34082d9d54aSJaroslav Kysela struct nhlt_acpi_table *nhlt; 34182d9d54aSJaroslav Kysela int ret = 0; 34282d9d54aSJaroslav Kysela 34382d9d54aSJaroslav Kysela nhlt = intel_nhlt_init(&pci->dev); 34482d9d54aSJaroslav Kysela if (nhlt) { 34582d9d54aSJaroslav Kysela if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) 34682d9d54aSJaroslav Kysela ret = 1; 34782d9d54aSJaroslav Kysela intel_nhlt_free(nhlt); 34882d9d54aSJaroslav Kysela } 34982d9d54aSJaroslav Kysela return ret; 35082d9d54aSJaroslav Kysela } 35182d9d54aSJaroslav Kysela 35206508575SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 35306508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 35406508575SPierre-Louis Bossart { 35506508575SPierre-Louis Bossart struct sdw_intel_acpi_info info; 35606508575SPierre-Louis Bossart acpi_handle handle; 35706508575SPierre-Louis Bossart int ret; 35806508575SPierre-Louis Bossart 35906508575SPierre-Louis Bossart handle = ACPI_HANDLE(&pci->dev); 36006508575SPierre-Louis Bossart 36106508575SPierre-Louis Bossart ret = sdw_intel_acpi_scan(handle, &info); 36206508575SPierre-Louis Bossart if (ret < 0) 36306508575SPierre-Louis Bossart return ret; 36406508575SPierre-Louis Bossart 36506508575SPierre-Louis Bossart return info.link_mask; 36606508575SPierre-Louis Bossart } 36706508575SPierre-Louis Bossart #else 36806508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 36906508575SPierre-Louis Bossart { 37006508575SPierre-Louis Bossart return 0; 37106508575SPierre-Louis Bossart } 37206508575SPierre-Louis Bossart #endif 37306508575SPierre-Louis Bossart 37482d9d54aSJaroslav Kysela int snd_intel_dsp_driver_probe(struct pci_dev *pci) 37582d9d54aSJaroslav Kysela { 37682d9d54aSJaroslav Kysela const struct config_entry *cfg; 37782d9d54aSJaroslav Kysela 37891636a82STakashi Iwai /* Intel vendor only */ 37991636a82STakashi Iwai if (pci->vendor != 0x8086) 38091636a82STakashi Iwai return SND_INTEL_DSP_DRIVER_ANY; 38191636a82STakashi Iwai 38282d9d54aSJaroslav Kysela if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 38382d9d54aSJaroslav Kysela return dsp_driver; 38482d9d54aSJaroslav Kysela 38582d9d54aSJaroslav Kysela /* 38682d9d54aSJaroslav Kysela * detect DSP by checking class/subclass/prog-id information 38782d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 38882d9d54aSJaroslav Kysela * class=04 subclass 01 prog-if 00: DSP is present 38982d9d54aSJaroslav Kysela * (and may be required e.g. for DMIC or SSP support) 39082d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 80: use DSP or legacy mode 39182d9d54aSJaroslav Kysela */ 39282d9d54aSJaroslav Kysela if (pci->class == 0x040300) 39382d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 39482d9d54aSJaroslav Kysela if (pci->class != 0x040100 && pci->class != 0x040380) { 395b79de57bSPierre-Louis Bossart dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 39682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 39782d9d54aSJaroslav Kysela } 39882d9d54aSJaroslav Kysela 39982d9d54aSJaroslav Kysela dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 40082d9d54aSJaroslav Kysela 40182d9d54aSJaroslav Kysela /* find the configuration for the specific device */ 40282d9d54aSJaroslav Kysela cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 40382d9d54aSJaroslav Kysela if (!cfg) 40482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_ANY; 40582d9d54aSJaroslav Kysela 40682d9d54aSJaroslav Kysela if (cfg->flags & FLAG_SOF) { 40706508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 40806508575SPierre-Louis Bossart snd_intel_dsp_check_soundwire(pci) > 0) { 40906508575SPierre-Louis Bossart dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 41006508575SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 41106508575SPierre-Louis Bossart } 41206508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 41306508575SPierre-Louis Bossart snd_intel_dsp_check_dmic(pci)) { 41482d9d54aSJaroslav Kysela dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 41582d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 41682d9d54aSJaroslav Kysela } 41706508575SPierre-Louis Bossart if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 41882d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 41982d9d54aSJaroslav Kysela } 42082d9d54aSJaroslav Kysela 421df1fceacSCezary Rojewski 422df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST) { 423df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 424df1fceacSCezary Rojewski if (snd_intel_dsp_check_dmic(pci)) { 425df1fceacSCezary Rojewski dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 42682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SST; 427df1fceacSCezary Rojewski } 428df1fceacSCezary Rojewski } else { 429df1fceacSCezary Rojewski return SND_INTEL_DSP_DRIVER_SST; 430df1fceacSCezary Rojewski } 431df1fceacSCezary Rojewski } 43282d9d54aSJaroslav Kysela 43382d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 43482d9d54aSJaroslav Kysela } 43582d9d54aSJaroslav Kysela EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 43682d9d54aSJaroslav Kysela 437*b5682305SPierre-Louis Bossart /* 438*b5682305SPierre-Louis Bossart * configuration table 439*b5682305SPierre-Louis Bossart * - the order of similar ACPI ID entries is important! 440*b5682305SPierre-Louis Bossart * - the first successful match will win 441*b5682305SPierre-Louis Bossart */ 442*b5682305SPierre-Louis Bossart static const struct config_entry acpi_config_table[] = { 443*b5682305SPierre-Louis Bossart /* BayTrail */ 444*b5682305SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 445*b5682305SPierre-Louis Bossart { 446*b5682305SPierre-Louis Bossart .flags = FLAG_SST, 447*b5682305SPierre-Louis Bossart .acpi_hid = "80860F28", 448*b5682305SPierre-Louis Bossart }, 449*b5682305SPierre-Louis Bossart #endif 450*b5682305SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 451*b5682305SPierre-Louis Bossart { 452*b5682305SPierre-Louis Bossart .flags = FLAG_SOF, 453*b5682305SPierre-Louis Bossart .acpi_hid = "80860F28", 454*b5682305SPierre-Louis Bossart }, 455*b5682305SPierre-Louis Bossart #endif 456*b5682305SPierre-Louis Bossart /* CherryTrail */ 457*b5682305SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 458*b5682305SPierre-Louis Bossart { 459*b5682305SPierre-Louis Bossart .flags = FLAG_SST, 460*b5682305SPierre-Louis Bossart .acpi_hid = "808622A8", 461*b5682305SPierre-Louis Bossart }, 462*b5682305SPierre-Louis Bossart #endif 463*b5682305SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 464*b5682305SPierre-Louis Bossart { 465*b5682305SPierre-Louis Bossart .flags = FLAG_SOF, 466*b5682305SPierre-Louis Bossart .acpi_hid = "808622A8", 467*b5682305SPierre-Louis Bossart }, 468*b5682305SPierre-Louis Bossart #endif 469*b5682305SPierre-Louis Bossart }; 470*b5682305SPierre-Louis Bossart 471*b5682305SPierre-Louis Bossart static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 472*b5682305SPierre-Louis Bossart const struct config_entry *table, 473*b5682305SPierre-Louis Bossart u32 len) 474*b5682305SPierre-Louis Bossart { 475*b5682305SPierre-Louis Bossart for (; len > 0; len--, table++) { 476*b5682305SPierre-Louis Bossart if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 477*b5682305SPierre-Louis Bossart continue; 478*b5682305SPierre-Louis Bossart if (table->dmi_table && !dmi_check_system(table->dmi_table)) 479*b5682305SPierre-Louis Bossart continue; 480*b5682305SPierre-Louis Bossart return table; 481*b5682305SPierre-Louis Bossart } 482*b5682305SPierre-Louis Bossart return NULL; 483*b5682305SPierre-Louis Bossart } 484*b5682305SPierre-Louis Bossart 485*b5682305SPierre-Louis Bossart int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 486*b5682305SPierre-Louis Bossart { 487*b5682305SPierre-Louis Bossart const struct config_entry *cfg; 488*b5682305SPierre-Louis Bossart 489*b5682305SPierre-Louis Bossart if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 490*b5682305SPierre-Louis Bossart return dsp_driver; 491*b5682305SPierre-Louis Bossart 492*b5682305SPierre-Louis Bossart if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 493*b5682305SPierre-Louis Bossart dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 494*b5682305SPierre-Louis Bossart SND_INTEL_DSP_DRIVER_LEGACY); 495*b5682305SPierre-Louis Bossart } 496*b5682305SPierre-Louis Bossart 497*b5682305SPierre-Louis Bossart /* find the configuration for the specific device */ 498*b5682305SPierre-Louis Bossart cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 499*b5682305SPierre-Louis Bossart ARRAY_SIZE(acpi_config_table)); 500*b5682305SPierre-Louis Bossart if (!cfg) 501*b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_ANY; 502*b5682305SPierre-Louis Bossart 503*b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SST) 504*b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 505*b5682305SPierre-Louis Bossart 506*b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SOF) 507*b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 508*b5682305SPierre-Louis Bossart 509*b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 510*b5682305SPierre-Louis Bossart } 511*b5682305SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 512*b5682305SPierre-Louis Bossart 51382d9d54aSJaroslav Kysela MODULE_LICENSE("GPL v2"); 51482d9d54aSJaroslav Kysela MODULE_DESCRIPTION("Intel DSP config driver"); 51506508575SPierre-Louis Bossart MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); 516