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 }, 322*114613f6SPierre-Louis Bossart { 323*114613f6SPierre-Louis Bossart .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, 324*114613f6SPierre-Louis Bossart .device = 0x4b58, 325*114613f6SPierre-Louis Bossart }, 326cc8f81c7SPierre-Louis Bossart #endif 327cc8f81c7SPierre-Louis Bossart 328c4294d7fSKai Vehmanen /* Alder Lake */ 329c4294d7fSKai Vehmanen #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) 330c4294d7fSKai Vehmanen { 331c4294d7fSKai Vehmanen .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 332c4294d7fSKai Vehmanen .device = 0x7ad0, 333c4294d7fSKai Vehmanen }, 334c4294d7fSKai Vehmanen { 335c4294d7fSKai Vehmanen .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 336c4294d7fSKai Vehmanen .device = 0x51c8, 337c4294d7fSKai Vehmanen }, 3384ad7935dSKai Vehmanen { 3394ad7935dSKai Vehmanen .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 3404ad7935dSKai Vehmanen .device = 0x51cc, 3414ad7935dSKai Vehmanen }, 342c4294d7fSKai Vehmanen #endif 343c4294d7fSKai Vehmanen 34482d9d54aSJaroslav Kysela }; 34582d9d54aSJaroslav Kysela 34682d9d54aSJaroslav Kysela static const struct config_entry *snd_intel_dsp_find_config 34782d9d54aSJaroslav Kysela (struct pci_dev *pci, const struct config_entry *table, u32 len) 34882d9d54aSJaroslav Kysela { 34982d9d54aSJaroslav Kysela u16 device; 35082d9d54aSJaroslav Kysela 35182d9d54aSJaroslav Kysela device = pci->device; 35282d9d54aSJaroslav Kysela for (; len > 0; len--, table++) { 35382d9d54aSJaroslav Kysela if (table->device != device) 35482d9d54aSJaroslav Kysela continue; 35582d9d54aSJaroslav Kysela if (table->dmi_table && !dmi_check_system(table->dmi_table)) 35682d9d54aSJaroslav Kysela continue; 35782d9d54aSJaroslav Kysela return table; 35882d9d54aSJaroslav Kysela } 35982d9d54aSJaroslav Kysela return NULL; 36082d9d54aSJaroslav Kysela } 36182d9d54aSJaroslav Kysela 36282d9d54aSJaroslav Kysela static int snd_intel_dsp_check_dmic(struct pci_dev *pci) 36382d9d54aSJaroslav Kysela { 36482d9d54aSJaroslav Kysela struct nhlt_acpi_table *nhlt; 36582d9d54aSJaroslav Kysela int ret = 0; 36682d9d54aSJaroslav Kysela 36782d9d54aSJaroslav Kysela nhlt = intel_nhlt_init(&pci->dev); 36882d9d54aSJaroslav Kysela if (nhlt) { 36982d9d54aSJaroslav Kysela if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) 37082d9d54aSJaroslav Kysela ret = 1; 37182d9d54aSJaroslav Kysela intel_nhlt_free(nhlt); 37282d9d54aSJaroslav Kysela } 37382d9d54aSJaroslav Kysela return ret; 37482d9d54aSJaroslav Kysela } 37582d9d54aSJaroslav Kysela 37606508575SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 37706508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 37806508575SPierre-Louis Bossart { 37906508575SPierre-Louis Bossart struct sdw_intel_acpi_info info; 38006508575SPierre-Louis Bossart acpi_handle handle; 38106508575SPierre-Louis Bossart int ret; 38206508575SPierre-Louis Bossart 38306508575SPierre-Louis Bossart handle = ACPI_HANDLE(&pci->dev); 38406508575SPierre-Louis Bossart 38506508575SPierre-Louis Bossart ret = sdw_intel_acpi_scan(handle, &info); 38606508575SPierre-Louis Bossart if (ret < 0) 38706508575SPierre-Louis Bossart return ret; 38806508575SPierre-Louis Bossart 38906508575SPierre-Louis Bossart return info.link_mask; 39006508575SPierre-Louis Bossart } 39106508575SPierre-Louis Bossart #else 39206508575SPierre-Louis Bossart static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) 39306508575SPierre-Louis Bossart { 39406508575SPierre-Louis Bossart return 0; 39506508575SPierre-Louis Bossart } 39606508575SPierre-Louis Bossart #endif 39706508575SPierre-Louis Bossart 39882d9d54aSJaroslav Kysela int snd_intel_dsp_driver_probe(struct pci_dev *pci) 39982d9d54aSJaroslav Kysela { 40082d9d54aSJaroslav Kysela const struct config_entry *cfg; 40182d9d54aSJaroslav Kysela 40291636a82STakashi Iwai /* Intel vendor only */ 40391636a82STakashi Iwai if (pci->vendor != 0x8086) 40491636a82STakashi Iwai return SND_INTEL_DSP_DRIVER_ANY; 40591636a82STakashi Iwai 4060e5cc221SPierre-Louis Bossart /* 4070e5cc221SPierre-Louis Bossart * Legacy devices don't have a PCI-based DSP and use HDaudio 4080e5cc221SPierre-Louis Bossart * for HDMI/DP support, ignore kernel parameter 4090e5cc221SPierre-Louis Bossart */ 4100e5cc221SPierre-Louis Bossart switch (pci->device) { 4110e5cc221SPierre-Louis Bossart case 0x160c: /* Broadwell */ 4120e5cc221SPierre-Louis Bossart case 0x0a0c: /* Haswell */ 4130e5cc221SPierre-Louis Bossart case 0x0c0c: 4140e5cc221SPierre-Louis Bossart case 0x0d0c: 4150e5cc221SPierre-Louis Bossart case 0x0f04: /* Baytrail */ 4160e5cc221SPierre-Louis Bossart case 0x2284: /* Braswell */ 4170e5cc221SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_ANY; 4180e5cc221SPierre-Louis Bossart } 4190e5cc221SPierre-Louis Bossart 42082d9d54aSJaroslav Kysela if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 42182d9d54aSJaroslav Kysela return dsp_driver; 42282d9d54aSJaroslav Kysela 42382d9d54aSJaroslav Kysela /* 42482d9d54aSJaroslav Kysela * detect DSP by checking class/subclass/prog-id information 42582d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 00: no DSP, use legacy driver 42682d9d54aSJaroslav Kysela * class=04 subclass 01 prog-if 00: DSP is present 42782d9d54aSJaroslav Kysela * (and may be required e.g. for DMIC or SSP support) 42882d9d54aSJaroslav Kysela * class=04 subclass 03 prog-if 80: use DSP or legacy mode 42982d9d54aSJaroslav Kysela */ 43082d9d54aSJaroslav Kysela if (pci->class == 0x040300) 43182d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 43282d9d54aSJaroslav Kysela if (pci->class != 0x040100 && pci->class != 0x040380) { 433b79de57bSPierre-Louis Bossart dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); 43482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 43582d9d54aSJaroslav Kysela } 43682d9d54aSJaroslav Kysela 43782d9d54aSJaroslav Kysela dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); 43882d9d54aSJaroslav Kysela 43982d9d54aSJaroslav Kysela /* find the configuration for the specific device */ 44082d9d54aSJaroslav Kysela cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); 44182d9d54aSJaroslav Kysela if (!cfg) 44282d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_ANY; 44382d9d54aSJaroslav Kysela 44482d9d54aSJaroslav Kysela if (cfg->flags & FLAG_SOF) { 44506508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && 44606508575SPierre-Louis Bossart snd_intel_dsp_check_soundwire(pci) > 0) { 44706508575SPierre-Louis Bossart dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); 44806508575SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 44906508575SPierre-Louis Bossart } 45006508575SPierre-Louis Bossart if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && 45106508575SPierre-Louis Bossart snd_intel_dsp_check_dmic(pci)) { 45282d9d54aSJaroslav Kysela dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); 45382d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 45482d9d54aSJaroslav Kysela } 45506508575SPierre-Louis Bossart if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) 45682d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SOF; 45782d9d54aSJaroslav Kysela } 45882d9d54aSJaroslav Kysela 459df1fceacSCezary Rojewski 460df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST) { 461df1fceacSCezary Rojewski if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { 462df1fceacSCezary Rojewski if (snd_intel_dsp_check_dmic(pci)) { 463df1fceacSCezary Rojewski dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); 46482d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_SST; 465df1fceacSCezary Rojewski } 466df1fceacSCezary Rojewski } else { 467df1fceacSCezary Rojewski return SND_INTEL_DSP_DRIVER_SST; 468df1fceacSCezary Rojewski } 469df1fceacSCezary Rojewski } 47082d9d54aSJaroslav Kysela 47182d9d54aSJaroslav Kysela return SND_INTEL_DSP_DRIVER_LEGACY; 47282d9d54aSJaroslav Kysela } 47382d9d54aSJaroslav Kysela EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); 47482d9d54aSJaroslav Kysela 4755427c7d6SHans de Goede /* Should we default to SOF or SST for BYT/CHT ? */ 4765427c7d6SHans de Goede #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ 4775427c7d6SHans de Goede !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) 4785427c7d6SHans de Goede #define FLAG_SST_OR_SOF_BYT FLAG_SOF 4795427c7d6SHans de Goede #else 4805427c7d6SHans de Goede #define FLAG_SST_OR_SOF_BYT FLAG_SST 4815427c7d6SHans de Goede #endif 4825427c7d6SHans de Goede 483b5682305SPierre-Louis Bossart /* 484b5682305SPierre-Louis Bossart * configuration table 485b5682305SPierre-Louis Bossart * - the order of similar ACPI ID entries is important! 486b5682305SPierre-Louis Bossart * - the first successful match will win 487b5682305SPierre-Louis Bossart */ 488b5682305SPierre-Louis Bossart static const struct config_entry acpi_config_table[] = { 4895427c7d6SHans de Goede #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ 4905427c7d6SHans de Goede IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 491b5682305SPierre-Louis Bossart /* BayTrail */ 492b5682305SPierre-Louis Bossart { 4935427c7d6SHans de Goede .flags = FLAG_SST_OR_SOF_BYT, 494b5682305SPierre-Louis Bossart .acpi_hid = "80860F28", 495b5682305SPierre-Louis Bossart }, 496b5682305SPierre-Louis Bossart /* CherryTrail */ 497b5682305SPierre-Louis Bossart { 4985427c7d6SHans de Goede .flags = FLAG_SST_OR_SOF_BYT, 499b5682305SPierre-Louis Bossart .acpi_hid = "808622A8", 500b5682305SPierre-Louis Bossart }, 501b5682305SPierre-Louis Bossart #endif 502803e5913SPierre-Louis Bossart /* Broadwell */ 503803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 504803e5913SPierre-Louis Bossart { 505803e5913SPierre-Louis Bossart .flags = FLAG_SST, 506803e5913SPierre-Louis Bossart .acpi_hid = "INT3438" 507803e5913SPierre-Louis Bossart }, 508803e5913SPierre-Louis Bossart #endif 509803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) 510803e5913SPierre-Louis Bossart { 511803e5913SPierre-Louis Bossart .flags = FLAG_SOF, 512803e5913SPierre-Louis Bossart .acpi_hid = "INT3438" 513803e5913SPierre-Louis Bossart }, 514803e5913SPierre-Louis Bossart #endif 515803e5913SPierre-Louis Bossart /* Haswell - not supported by SOF but added for consistency */ 516803e5913SPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) 517803e5913SPierre-Louis Bossart { 518803e5913SPierre-Louis Bossart .flags = FLAG_SST, 519803e5913SPierre-Louis Bossart .acpi_hid = "INT33C8" 520803e5913SPierre-Louis Bossart }, 521803e5913SPierre-Louis Bossart #endif 522b5682305SPierre-Louis Bossart }; 523b5682305SPierre-Louis Bossart 524b5682305SPierre-Louis Bossart static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], 525b5682305SPierre-Louis Bossart const struct config_entry *table, 526b5682305SPierre-Louis Bossart u32 len) 527b5682305SPierre-Louis Bossart { 528b5682305SPierre-Louis Bossart for (; len > 0; len--, table++) { 529b5682305SPierre-Louis Bossart if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) 530b5682305SPierre-Louis Bossart continue; 531b5682305SPierre-Louis Bossart if (table->dmi_table && !dmi_check_system(table->dmi_table)) 532b5682305SPierre-Louis Bossart continue; 533b5682305SPierre-Louis Bossart return table; 534b5682305SPierre-Louis Bossart } 535b5682305SPierre-Louis Bossart return NULL; 536b5682305SPierre-Louis Bossart } 537b5682305SPierre-Louis Bossart 538b5682305SPierre-Louis Bossart int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) 539b5682305SPierre-Louis Bossart { 540b5682305SPierre-Louis Bossart const struct config_entry *cfg; 541b5682305SPierre-Louis Bossart 542b5682305SPierre-Louis Bossart if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) 543b5682305SPierre-Louis Bossart return dsp_driver; 544b5682305SPierre-Louis Bossart 545b5682305SPierre-Louis Bossart if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { 546b5682305SPierre-Louis Bossart dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", 547b5682305SPierre-Louis Bossart SND_INTEL_DSP_DRIVER_LEGACY); 548b5682305SPierre-Louis Bossart } 549b5682305SPierre-Louis Bossart 550b5682305SPierre-Louis Bossart /* find the configuration for the specific device */ 551b5682305SPierre-Louis Bossart cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, 552b5682305SPierre-Louis Bossart ARRAY_SIZE(acpi_config_table)); 553b5682305SPierre-Louis Bossart if (!cfg) 554b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_ANY; 555b5682305SPierre-Louis Bossart 556b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SST) 557b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 558b5682305SPierre-Louis Bossart 559b5682305SPierre-Louis Bossart if (cfg->flags & FLAG_SOF) 560b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SOF; 561b5682305SPierre-Louis Bossart 562b5682305SPierre-Louis Bossart return SND_INTEL_DSP_DRIVER_SST; 563b5682305SPierre-Louis Bossart } 564b5682305SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); 565b5682305SPierre-Louis Bossart 56682d9d54aSJaroslav Kysela MODULE_LICENSE("GPL v2"); 56782d9d54aSJaroslav Kysela MODULE_DESCRIPTION("Intel DSP config driver"); 56808c2a4bcSPierre-Louis Bossart MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); 569