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; 32b5682305SPierre-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 }, 310c5b5ff60SBard Liao { 311c5b5ff60SBard Liao .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 312c5b5ff60SBard Liao .device = 0x43c8, 313c5b5ff60SBard Liao }, 314cc8f81c7SPierre-Louis Bossart #endif 315cc8f81c7SPierre-Louis Bossart 316cc8f81c7SPierre-Louis Bossart /* Elkhart Lake */ 317cc8f81c7SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) 318cc8f81c7SPierre-Louis Bossart { 319cc8f81c7SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 320cc8f81c7SPierre-Louis Bossart .device = 0x4b55, 321cc8f81c7SPierre-Louis Bossart }, 322cc8f81c7SPierre-Louis Bossart #endif 323cc8f81c7SPierre-Louis Bossart 32482d9d54aSJaroslav Kysela }; 32582d9d54aSJaroslav Kysela 32682d9d54aSJaroslav Kysela static const struct config_entry *snd_intel_dsp_find_config 32782d9d54aSJaroslav Kysela (struct pci_dev *pci, const struct config_entry *table, u32 len) 32882d9d54aSJaroslav Kysela { 32982d9d54aSJaroslav Kysela u16 device; 33082d9d54aSJaroslav Kysela 33182d9d54aSJaroslav Kysela device = pci->device; 33282d9d54aSJaroslav Kysela for (; len > 0; len--, table++) { 33382d9d54aSJaroslav Kysela if (table->device != device) 33482d9d54aSJaroslav Kysela continue; 33582d9d54aSJaroslav Kysela if (table->dmi_table && !dmi_check_system(table->dmi_table)) 33682d9d54aSJaroslav Kysela continue; 33782d9d54aSJaroslav Kysela return table; 33882d9d54aSJaroslav Kysela } 33982d9d54aSJaroslav Kysela return NULL; 34082d9d54aSJaroslav Kysela } 34182d9d54aSJaroslav Kysela 34282d9d54aSJaroslav Kysela static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 34382d9d54aSJaroslav Kysela { 34482d9d54aSJaroslav Kysela struct nhlt_acpi_table *nhlt; 34582d9d54aSJaroslav Kysela int ret = 0; 34682d9d54aSJaroslav Kysela 34782d9d54aSJaroslav Kysela nhlt = intel_nhlt_init(&pci->dev); 34882d9d54aSJaroslav Kysela if (nhlt) { 34982d9d54aSJaroslav Kysela if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) 35082d9d54aSJaroslav Kysela ret = 1; 35182d9d54aSJaroslav Kysela intel_nhlt_free(nhlt); 35282d9d54aSJaroslav Kysela } 35382d9d54aSJaroslav Kysela return ret; 35482d9d54aSJaroslav Kysela } 35582d9d54aSJaroslav Kysela 35606508575SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 35706508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 35806508575SPierre-Louis Bossart { 35906508575SPierre-Louis Bossart struct sdw_intel_acpi_info info; 36006508575SPierre-Louis Bossart acpi_handle handle; 36106508575SPierre-Louis Bossart int ret; 36206508575SPierre-Louis Bossart 36306508575SPierre-Louis Bossart handle = ACPI_HANDLE(&pci->dev); 36406508575SPierre-Louis Bossart 36506508575SPierre-Louis Bossart ret = sdw_intel_acpi_scan(handle, &info); 36606508575SPierre-Louis Bossart if (ret < 0) 36706508575SPierre-Louis Bossart return ret; 36806508575SPierre-Louis Bossart 36906508575SPierre-Louis Bossart return info.link_mask; 37006508575SPierre-Louis Bossart } 37106508575SPierre-Louis Bossart #else 37206508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 37306508575SPierre-Louis Bossart { 37406508575SPierre-Louis Bossart return 0; 37506508575SPierre-Louis Bossart } 37606508575SPierre-Louis Bossart #endif 37706508575SPierre-Louis Bossart 37882d9d54aSJaroslav Kysela int snd_intel_dsp_driver_probe(struct pci_dev *pci) 37982d9d54aSJaroslav Kysela { 38082d9d54aSJaroslav Kysela const struct config_entry *cfg; 38182d9d54aSJaroslav Kysela 38291636a82STakashi Iwai /* Intel vendor only */ 38391636a82STakashi Iwai if (pci->vendor != 0x8086) 38491636a82STakashi Iwai return SND_INTEL_DSP_DRIVER_ANY; 38591636a82STakashi Iwai 3860e5cc221SPierre-Louis Bossart /* 3870e5cc221SPierre-Louis Bossart * Legacy devices don't have a PCI-based DSP and use HDaudio 3880e5cc221SPierre-Louis Bossart * for HDMI/DP support, ignore kernel parameter 3890e5cc221SPierre-Louis Bossart */ 3900e5cc221SPierre-Louis Bossart switch (pci->device) { 3910e5cc221SPierre-Louis Bossart case 0x160c: /* Broadwell */ 3920e5cc221SPierre-Louis Bossart case 0x0a0c: /* Haswell */ 3930e5cc221SPierre-Louis Bossart case 0x0c0c: 3940e5cc221SPierre-Louis Bossart case 0x0d0c: 3950e5cc221SPierre-Louis Bossart case 0x0f04: /* Baytrail */ 3960e5cc221SPierre-Louis Bossart case 0x2284: /* Braswell */ 3970e5cc221SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_ANY; 3980e5cc221SPierre-Louis Bossart } 3990e5cc221SPierre-Louis Bossart 40082d9d54aSJaroslav Kysela if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 40182d9d54aSJaroslav Kysela return dsp_driver; 40282d9d54aSJaroslav Kysela 40382d9d54aSJaroslav Kysela /* 40482d9d54aSJaroslav Kysela * detect DSP by checking class/subclass/prog-id information 40582d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 40682d9d54aSJaroslav Kysela * class=04 subclass 01 prog-if 00: DSP is present 40782d9d54aSJaroslav Kysela * (and may be required e.g. for DMIC or SSP support) 40882d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 80: use DSP or legacy mode 40982d9d54aSJaroslav Kysela */ 41082d9d54aSJaroslav Kysela if (pci->class == 0x040300) 41182d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 41282d9d54aSJaroslav Kysela if (pci->class != 0x040100 && pci->class != 0x040380) { 413b79de57bSPierre-Louis Bossart dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 41482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 41582d9d54aSJaroslav Kysela } 41682d9d54aSJaroslav Kysela 41782d9d54aSJaroslav Kysela dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 41882d9d54aSJaroslav Kysela 41982d9d54aSJaroslav Kysela /* find the configuration for the specific device */ 42082d9d54aSJaroslav Kysela cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 42182d9d54aSJaroslav Kysela if (!cfg) 42282d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_ANY; 42382d9d54aSJaroslav Kysela 42482d9d54aSJaroslav Kysela if (cfg->flags & FLAG_SOF) { 42506508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 42606508575SPierre-Louis Bossart snd_intel_dsp_check_soundwire(pci) > 0) { 42706508575SPierre-Louis Bossart dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 42806508575SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 42906508575SPierre-Louis Bossart } 43006508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 43106508575SPierre-Louis Bossart snd_intel_dsp_check_dmic(pci)) { 43282d9d54aSJaroslav Kysela dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 43382d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 43482d9d54aSJaroslav Kysela } 43506508575SPierre-Louis Bossart if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 43682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 43782d9d54aSJaroslav Kysela } 43882d9d54aSJaroslav Kysela 439df1fceacSCezary Rojewski 440df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST) { 441df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 442df1fceacSCezary Rojewski if (snd_intel_dsp_check_dmic(pci)) { 443df1fceacSCezary Rojewski dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 44482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SST; 445df1fceacSCezary Rojewski } 446df1fceacSCezary Rojewski } else { 447df1fceacSCezary Rojewski return SND_INTEL_DSP_DRIVER_SST; 448df1fceacSCezary Rojewski } 449df1fceacSCezary Rojewski } 45082d9d54aSJaroslav Kysela 45182d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 45282d9d54aSJaroslav Kysela } 45382d9d54aSJaroslav Kysela EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 45482d9d54aSJaroslav Kysela 455*5427c7d6SHans de Goede /* Should we default to SOF or SST for BYT/CHT ? */ 456*5427c7d6SHans de Goede #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ 457*5427c7d6SHans de Goede !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 458*5427c7d6SHans de Goede #define FLAG_SST_OR_SOF_BYT FLAG_SOF 459*5427c7d6SHans de Goede #else 460*5427c7d6SHans de Goede #define FLAG_SST_OR_SOF_BYT FLAG_SST 461*5427c7d6SHans de Goede #endif 462*5427c7d6SHans de Goede 463b5682305SPierre-Louis Bossart /* 464b5682305SPierre-Louis Bossart * configuration table 465b5682305SPierre-Louis Bossart * - the order of similar ACPI ID entries is important! 466b5682305SPierre-Louis Bossart * - the first successful match will win 467b5682305SPierre-Louis Bossart */ 468b5682305SPierre-Louis Bossart static const struct config_entry acpi_config_table[] = { 469*5427c7d6SHans de Goede #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ 470*5427c7d6SHans de Goede IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 471b5682305SPierre-Louis Bossart /* BayTrail */ 472b5682305SPierre-Louis Bossart { 473*5427c7d6SHans de Goede .flags = FLAG_SST_OR_SOF_BYT, 474b5682305SPierre-Louis Bossart .acpi_hid = "80860F28", 475b5682305SPierre-Louis Bossart }, 476b5682305SPierre-Louis Bossart /* CherryTrail */ 477b5682305SPierre-Louis Bossart { 478*5427c7d6SHans de Goede .flags = FLAG_SST_OR_SOF_BYT, 479b5682305SPierre-Louis Bossart .acpi_hid = "808622A8", 480b5682305SPierre-Louis Bossart }, 481b5682305SPierre-Louis Bossart #endif 482803e5913SPierre-Louis Bossart /* Broadwell */ 483803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 484803e5913SPierre-Louis Bossart { 485803e5913SPierre-Louis Bossart .flags = FLAG_SST, 486803e5913SPierre-Louis Bossart .acpi_hid = "INT3438" 487803e5913SPierre-Louis Bossart }, 488803e5913SPierre-Louis Bossart #endif 489803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) 490803e5913SPierre-Louis Bossart { 491803e5913SPierre-Louis Bossart .flags = FLAG_SOF, 492803e5913SPierre-Louis Bossart .acpi_hid = "INT3438" 493803e5913SPierre-Louis Bossart }, 494803e5913SPierre-Louis Bossart #endif 495803e5913SPierre-Louis Bossart /* Haswell - not supported by SOF but added for consistency */ 496803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 497803e5913SPierre-Louis Bossart { 498803e5913SPierre-Louis Bossart .flags = FLAG_SST, 499803e5913SPierre-Louis Bossart .acpi_hid = "INT33C8" 500803e5913SPierre-Louis Bossart }, 501803e5913SPierre-Louis Bossart #endif 502b5682305SPierre-Louis Bossart }; 503b5682305SPierre-Louis Bossart 504b5682305SPierre-Louis Bossart static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 505b5682305SPierre-Louis Bossart const struct config_entry *table, 506b5682305SPierre-Louis Bossart u32 len) 507b5682305SPierre-Louis Bossart { 508b5682305SPierre-Louis Bossart for (; len > 0; len--, table++) { 509b5682305SPierre-Louis Bossart if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 510b5682305SPierre-Louis Bossart continue; 511b5682305SPierre-Louis Bossart if (table->dmi_table && !dmi_check_system(table->dmi_table)) 512b5682305SPierre-Louis Bossart continue; 513b5682305SPierre-Louis Bossart return table; 514b5682305SPierre-Louis Bossart } 515b5682305SPierre-Louis Bossart return NULL; 516b5682305SPierre-Louis Bossart } 517b5682305SPierre-Louis Bossart 518b5682305SPierre-Louis Bossart int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 519b5682305SPierre-Louis Bossart { 520b5682305SPierre-Louis Bossart const struct config_entry *cfg; 521b5682305SPierre-Louis Bossart 522b5682305SPierre-Louis Bossart if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 523b5682305SPierre-Louis Bossart return dsp_driver; 524b5682305SPierre-Louis Bossart 525b5682305SPierre-Louis Bossart if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 526b5682305SPierre-Louis Bossart dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 527b5682305SPierre-Louis Bossart SND_INTEL_DSP_DRIVER_LEGACY); 528b5682305SPierre-Louis Bossart } 529b5682305SPierre-Louis Bossart 530b5682305SPierre-Louis Bossart /* find the configuration for the specific device */ 531b5682305SPierre-Louis Bossart cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 532b5682305SPierre-Louis Bossart ARRAY_SIZE(acpi_config_table)); 533b5682305SPierre-Louis Bossart if (!cfg) 534b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_ANY; 535b5682305SPierre-Louis Bossart 536b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SST) 537b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 538b5682305SPierre-Louis Bossart 539b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SOF) 540b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 541b5682305SPierre-Louis Bossart 542b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 543b5682305SPierre-Louis Bossart } 544b5682305SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 545b5682305SPierre-Louis Bossart 54682d9d54aSJaroslav Kysela MODULE_LICENSE("GPL v2"); 54782d9d54aSJaroslav Kysela MODULE_DESCRIPTION("Intel DSP config driver"); 54806508575SPierre-Louis Bossart MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); 549