xref: /openbmc/linux/sound/hda/intel-dsp-config.c (revision 06508575)
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