• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz>
3 
4 #include <linux/acpi.h>
5 #include <linux/bits.h>
6 #include <linux/dmi.h>
7 #include <linux/module.h>
8 #include <linux/pci.h>
9 #include <linux/soundwire/sdw.h>
10 #include <linux/soundwire/sdw_intel.h>
11 #include <sound/core.h>
12 #include <sound/intel-dsp-config.h>
13 #include <sound/intel-nhlt.h>
14 #include <sound/soc-acpi.h>
15 
16 static int dsp_driver;
17 
18 module_param(dsp_driver, int, 0444);
19 MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)");
20 
21 #define FLAG_SST			BIT(0)
22 #define FLAG_SOF			BIT(1)
23 #define FLAG_SST_ONLY_IF_DMIC		BIT(15)
24 #define FLAG_SOF_ONLY_IF_DMIC		BIT(16)
25 #define FLAG_SOF_ONLY_IF_SOUNDWIRE	BIT(17)
26 
27 #define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \
28 					    FLAG_SOF_ONLY_IF_SOUNDWIRE)
29 
30 struct config_entry {
31 	u32 flags;
32 	u16 device;
33 	u8 acpi_hid[ACPI_ID_LEN];
34 	const struct dmi_system_id *dmi_table;
35 	const struct snd_soc_acpi_codecs *codec_hid;
36 };
37 
38 static const struct snd_soc_acpi_codecs __maybe_unused essx_83x6 = {
39 	.num_codecs = 3,
40 	.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
41 };
42 
43 /*
44  * configuration table
45  * - the order of similar PCI ID entries is important!
46  * - the first successful match will win
47  */
48 static const struct config_entry config_table[] = {
49 /* Merrifield */
50 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
51 	{
52 		.flags = FLAG_SOF,
53 		.device = 0x119a,
54 	},
55 #endif
56 /* Broxton-T */
57 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
58 	{
59 		.flags = FLAG_SOF,
60 		.device = 0x1a98,
61 	},
62 #endif
63 /*
64  * Apollolake (Broxton-P)
65  * the legacy HDAudio driver is used except on Up Squared (SOF) and
66  * Chromebooks (SST), as well as devices based on the ES8336 codec
67  */
68 #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
69 	{
70 		.flags = FLAG_SOF,
71 		.device = 0x5a98,
72 		.dmi_table = (const struct dmi_system_id []) {
73 			{
74 				.ident = "Up Squared",
75 				.matches = {
76 					DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
77 					DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"),
78 				}
79 			},
80 			{}
81 		}
82 	},
83 	{
84 		.flags = FLAG_SOF,
85 		.device = 0x5a98,
86 		.codec_hid =  &essx_83x6,
87 	},
88 #endif
89 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL)
90 	{
91 		.flags = FLAG_SST,
92 		.device = 0x5a98,
93 		.dmi_table = (const struct dmi_system_id []) {
94 			{
95 				.ident = "Google Chromebooks",
96 				.matches = {
97 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
98 				}
99 			},
100 			{}
101 		}
102 	},
103 #endif
104 /*
105  * Skylake and Kabylake use legacy HDAudio driver except for Google
106  * Chromebooks (SST)
107  */
108 
109 /* Sunrise Point-LP */
110 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL)
111 	{
112 		.flags = FLAG_SST,
113 		.device = 0x9d70,
114 		.dmi_table = (const struct dmi_system_id []) {
115 			{
116 				.ident = "Google Chromebooks",
117 				.matches = {
118 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
119 				}
120 			},
121 			{}
122 		}
123 	},
124 	{
125 		.flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC,
126 		.device = 0x9d70,
127 	},
128 #endif
129 /* Kabylake-LP */
130 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL)
131 	{
132 		.flags = FLAG_SST,
133 		.device = 0x9d71,
134 		.dmi_table = (const struct dmi_system_id []) {
135 			{
136 				.ident = "Google Chromebooks",
137 				.matches = {
138 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
139 				}
140 			},
141 			{}
142 		}
143 	},
144 	{
145 		.flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC,
146 		.device = 0x9d71,
147 	},
148 #endif
149 
150 /*
151  * Geminilake uses legacy HDAudio driver except for Google
152  * Chromebooks and devices based on the ES8336 codec
153  */
154 /* Geminilake */
155 #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE)
156 	{
157 		.flags = FLAG_SOF,
158 		.device = 0x3198,
159 		.dmi_table = (const struct dmi_system_id []) {
160 			{
161 				.ident = "Google Chromebooks",
162 				.matches = {
163 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
164 				}
165 			},
166 			{}
167 		}
168 	},
169 	{
170 		.flags = FLAG_SOF,
171 		.device = 0x3198,
172 		.codec_hid =  &essx_83x6,
173 	},
174 #endif
175 
176 /*
177  * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake use legacy
178  * HDAudio driver except for Google Chromebooks and when DMICs are
179  * present. Two cases are required since Coreboot does not expose NHLT
180  * tables.
181  *
182  * When the Chromebook quirk is not present, it's based on information
183  * that no such device exists. When the quirk is present, it could be
184  * either based on product information or a placeholder.
185  */
186 
187 /* Cannonlake */
188 #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE)
189 	{
190 		.flags = FLAG_SOF,
191 		.device = 0x9dc8,
192 		.dmi_table = (const struct dmi_system_id []) {
193 			{
194 				.ident = "Google Chromebooks",
195 				.matches = {
196 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
197 				}
198 			},
199 			{
200 				.ident = "UP-WHL",
201 				.matches = {
202 					DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
203 				}
204 			},
205 			{}
206 		}
207 	},
208 	{
209 		.flags = FLAG_SOF,
210 		.device = 0x09dc8,
211 		.codec_hid =  &essx_83x6,
212 	},
213 	{
214 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
215 		.device = 0x9dc8,
216 	},
217 #endif
218 
219 /* Coffelake */
220 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
221 	{
222 		.flags = FLAG_SOF,
223 		.device = 0xa348,
224 		.dmi_table = (const struct dmi_system_id []) {
225 			{
226 				.ident = "Google Chromebooks",
227 				.matches = {
228 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
229 				}
230 			},
231 			{}
232 		}
233 	},
234 	{
235 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
236 		.device = 0xa348,
237 	},
238 #endif
239 
240 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
241 /* Cometlake-LP */
242 	{
243 		.flags = FLAG_SOF,
244 		.device = 0x02c8,
245 		.dmi_table = (const struct dmi_system_id []) {
246 			{
247 				.ident = "Google Chromebooks",
248 				.matches = {
249 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
250 				}
251 			},
252 			{
253 				.matches = {
254 					DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
255 					DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
256 				},
257 			},
258 			{
259 				/* early version of SKU 09C6 */
260 				.matches = {
261 					DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
262 					DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
263 				},
264 			},
265 			{}
266 		}
267 	},
268 	{
269 		.flags = FLAG_SOF,
270 		.device = 0x02c8,
271 		.codec_hid =  &essx_83x6,
272 	},
273 	{
274 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
275 		.device = 0x02c8,
276 	},
277 /* Cometlake-H */
278 	{
279 		.flags = FLAG_SOF,
280 		.device = 0x06c8,
281 		.dmi_table = (const struct dmi_system_id []) {
282 			{
283 				.matches = {
284 					DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
285 					DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
286 				},
287 			},
288 			{
289 				.matches = {
290 					DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
291 					DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
292 				},
293 			},
294 			{}
295 		}
296 	},
297 	{
298 		.flags = FLAG_SOF,
299 		.device = 0x06c8,
300 		.codec_hid =  &essx_83x6,
301 	},
302 	{
303 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
304 		.device = 0x06c8,
305 	},
306 #endif
307 
308 /* Icelake */
309 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
310 	{
311 		.flags = FLAG_SOF,
312 		.device = 0x34c8,
313 		.dmi_table = (const struct dmi_system_id []) {
314 			{
315 				.ident = "Google Chromebooks",
316 				.matches = {
317 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
318 				}
319 			},
320 			{}
321 		}
322 	},
323 	{
324 		.flags = FLAG_SOF,
325 		.device = 0x34c8,
326 		.codec_hid =  &essx_83x6,
327 	},
328 	{
329 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
330 		.device = 0x34c8,
331 	},
332 #endif
333 
334 /* Jasper Lake */
335 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
336 	{
337 		.flags = FLAG_SOF,
338 		.device = 0x4dc8,
339 		.dmi_table = (const struct dmi_system_id []) {
340 			{
341 				.ident = "Google Chromebooks",
342 				.matches = {
343 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
344 				}
345 			},
346 			{
347 				.ident = "Google firmware",
348 				.matches = {
349 					DMI_MATCH(DMI_BIOS_VERSION, "Google"),
350 				}
351 			},
352 			{}
353 		}
354 	},
355 	{
356 		.flags = FLAG_SOF,
357 		.device = 0x4dc8,
358 		.codec_hid =  &essx_83x6,
359 	},
360 	{
361 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
362 		.device = 0x4dc8,
363 	},
364 #endif
365 
366 /* Tigerlake */
367 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
368 	{
369 		.flags = FLAG_SOF,
370 		.device = 0xa0c8,
371 		.dmi_table = (const struct dmi_system_id []) {
372 			{
373 				.ident = "Google Chromebooks",
374 				.matches = {
375 					DMI_MATCH(DMI_SYS_VENDOR, "Google"),
376 				}
377 			},
378 			{
379 				.ident = "UPX-TGL",
380 				.matches = {
381 					DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
382 				}
383 			},
384 			{}
385 		}
386 	},
387 	{
388 		.flags = FLAG_SOF,
389 		.device = 0xa0c8,
390 		.codec_hid =  &essx_83x6,
391 	},
392 	{
393 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
394 		.device = 0xa0c8,
395 	},
396 	{
397 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
398 		.device = 0x43c8,
399 	},
400 #endif
401 
402 /* Elkhart Lake */
403 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
404 	{
405 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
406 		.device = 0x4b55,
407 	},
408 	{
409 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
410 		.device = 0x4b58,
411 	},
412 #endif
413 
414 /* Alder Lake */
415 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
416 	/* Alderlake-S */
417 	{
418 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
419 		.device = 0x7ad0,
420 	},
421 	/* RaptorLake-S */
422 	{
423 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
424 		.device = 0x7a50,
425 	},
426 	/* Alderlake-P */
427 	{
428 		.flags = FLAG_SOF,
429 		.device = 0x51c8,
430 		.codec_hid =  &essx_83x6,
431 	},
432 	{
433 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
434 		.device = 0x51c8,
435 	},
436 	{
437 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
438 		.device = 0x51cd,
439 	},
440 	/* Alderlake-PS */
441 	{
442 		.flags = FLAG_SOF,
443 		.device = 0x51c9,
444 		.codec_hid =  &essx_83x6,
445 	},
446 	{
447 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
448 		.device = 0x51c9,
449 	},
450 	/* Alderlake-M */
451 	{
452 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
453 		.device = 0x51cc,
454 	},
455 	/* Alderlake-N */
456 	{
457 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
458 		.device = 0x54c8,
459 	},
460 	/* RaptorLake-P */
461 	{
462 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
463 		.device = 0x51ca,
464 	},
465 	{
466 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
467 		.device = 0x51cb,
468 	},
469 	/* RaptorLake-M */
470 	{
471 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
472 		.device = 0x51ce,
473 	},
474 	/* RaptorLake-PX */
475 	{
476 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
477 		.device = 0x51cf,
478 	},
479 #endif
480 
481 /* Meteor Lake */
482 #if IS_ENABLED(CONFIG_SND_SOC_SOF_METEORLAKE)
483 	/* Meteorlake-P */
484 	{
485 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
486 		.device = 0x7e28,
487 	},
488 #endif
489 
490 /* Lunar Lake */
491 #if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE)
492 	/* Lunarlake-P */
493 	{
494 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
495 		.device = PCI_DEVICE_ID_INTEL_HDA_LNL_P,
496 	},
497 #endif
498 };
499 
snd_intel_dsp_find_config(struct pci_dev * pci,const struct config_entry * table,u32 len)500 static const struct config_entry *snd_intel_dsp_find_config
501 		(struct pci_dev *pci, const struct config_entry *table, u32 len)
502 {
503 	u16 device;
504 
505 	device = pci->device;
506 	for (; len > 0; len--, table++) {
507 		if (table->device != device)
508 			continue;
509 		if (table->dmi_table && !dmi_check_system(table->dmi_table))
510 			continue;
511 		if (table->codec_hid) {
512 			int i;
513 
514 			for (i = 0; i < table->codec_hid->num_codecs; i++)
515 				if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
516 					break;
517 			if (i == table->codec_hid->num_codecs)
518 				continue;
519 		}
520 		return table;
521 	}
522 	return NULL;
523 }
524 
snd_intel_dsp_check_dmic(struct pci_dev * pci)525 static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
526 {
527 	struct nhlt_acpi_table *nhlt;
528 	int ret = 0;
529 
530 	nhlt = intel_nhlt_init(&pci->dev);
531 	if (nhlt) {
532 		if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC))
533 			ret = 1;
534 		intel_nhlt_free(nhlt);
535 	}
536 	return ret;
537 }
538 
539 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
snd_intel_dsp_check_soundwire(struct pci_dev * pci)540 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
541 {
542 	struct sdw_intel_acpi_info info;
543 	acpi_handle handle;
544 	int ret;
545 
546 	handle = ACPI_HANDLE(&pci->dev);
547 
548 	ret = sdw_intel_acpi_scan(handle, &info);
549 	if (ret < 0)
550 		return ret;
551 
552 	return info.link_mask;
553 }
554 #else
snd_intel_dsp_check_soundwire(struct pci_dev * pci)555 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
556 {
557 	return 0;
558 }
559 #endif
560 
snd_intel_dsp_driver_probe(struct pci_dev * pci)561 int snd_intel_dsp_driver_probe(struct pci_dev *pci)
562 {
563 	const struct config_entry *cfg;
564 
565 	/* Intel vendor only */
566 	if (pci->vendor != 0x8086)
567 		return SND_INTEL_DSP_DRIVER_ANY;
568 
569 	/*
570 	 * Legacy devices don't have a PCI-based DSP and use HDaudio
571 	 * for HDMI/DP support, ignore kernel parameter
572 	 */
573 	switch (pci->device) {
574 	case 0x160c: /* Broadwell */
575 	case 0x0a0c: /* Haswell */
576 	case 0x0c0c:
577 	case 0x0d0c:
578 	case 0x0f04: /* Baytrail */
579 	case 0x2284: /* Braswell */
580 		return SND_INTEL_DSP_DRIVER_ANY;
581 	}
582 
583 	if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
584 		return dsp_driver;
585 
586 	/*
587 	 * detect DSP by checking class/subclass/prog-id information
588 	 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
589 	 * class=04 subclass 01 prog-if 00: DSP is present
590 	 *  (and may be required e.g. for DMIC or SSP support)
591 	 * class=04 subclass 03 prog-if 80: use DSP or legacy mode
592 	 */
593 	if (pci->class == 0x040300)
594 		return SND_INTEL_DSP_DRIVER_LEGACY;
595 	if (pci->class != 0x040100 && pci->class != 0x040380) {
596 		dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class);
597 		return SND_INTEL_DSP_DRIVER_LEGACY;
598 	}
599 
600 	dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
601 
602 	/* find the configuration for the specific device */
603 	cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
604 	if (!cfg)
605 		return SND_INTEL_DSP_DRIVER_ANY;
606 
607 	if (cfg->flags & FLAG_SOF) {
608 		if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
609 		    snd_intel_dsp_check_soundwire(pci) > 0) {
610 			dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
611 			return SND_INTEL_DSP_DRIVER_SOF;
612 		}
613 		if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
614 		    snd_intel_dsp_check_dmic(pci)) {
615 			dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
616 			return SND_INTEL_DSP_DRIVER_SOF;
617 		}
618 		if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
619 			return SND_INTEL_DSP_DRIVER_SOF;
620 	}
621 
622 
623 	if (cfg->flags & FLAG_SST) {
624 		if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) {
625 			if (snd_intel_dsp_check_dmic(pci)) {
626 				dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n");
627 				return SND_INTEL_DSP_DRIVER_SST;
628 			}
629 		} else {
630 			return SND_INTEL_DSP_DRIVER_SST;
631 		}
632 	}
633 
634 	return SND_INTEL_DSP_DRIVER_LEGACY;
635 }
636 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
637 
638 /* Should we default to SOF or SST for BYT/CHT ? */
639 #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
640     !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
641 #define FLAG_SST_OR_SOF_BYT	FLAG_SOF
642 #else
643 #define FLAG_SST_OR_SOF_BYT	FLAG_SST
644 #endif
645 
646 /*
647  * configuration table
648  * - the order of similar ACPI ID entries is important!
649  * - the first successful match will win
650  */
651 static const struct config_entry acpi_config_table[] = {
652 #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
653     IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
654 /* BayTrail */
655 	{
656 		.flags = FLAG_SST_OR_SOF_BYT,
657 		.acpi_hid = "80860F28",
658 	},
659 /* CherryTrail */
660 	{
661 		.flags = FLAG_SST_OR_SOF_BYT,
662 		.acpi_hid = "808622A8",
663 	},
664 #endif
665 /* Broadwell */
666 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
667 	{
668 		.flags = FLAG_SST,
669 		.acpi_hid = "INT3438"
670 	},
671 #endif
672 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
673 	{
674 		.flags = FLAG_SOF,
675 		.acpi_hid = "INT3438"
676 	},
677 #endif
678 /* Haswell - not supported by SOF but added for consistency */
679 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
680 	{
681 		.flags = FLAG_SST,
682 		.acpi_hid = "INT33C8"
683 	},
684 #endif
685 };
686 
snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],const struct config_entry * table,u32 len)687 static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],
688 								 const struct config_entry *table,
689 								 u32 len)
690 {
691 	for (; len > 0; len--, table++) {
692 		if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN))
693 			continue;
694 		if (table->dmi_table && !dmi_check_system(table->dmi_table))
695 			continue;
696 		return table;
697 	}
698 	return NULL;
699 }
700 
snd_intel_acpi_dsp_driver_probe(struct device * dev,const u8 acpi_hid[ACPI_ID_LEN])701 int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN])
702 {
703 	const struct config_entry *cfg;
704 
705 	if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
706 		return dsp_driver;
707 
708 	if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) {
709 		dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n",
710 			 SND_INTEL_DSP_DRIVER_LEGACY);
711 	}
712 
713 	/* find the configuration for the specific device */
714 	cfg = snd_intel_acpi_dsp_find_config(acpi_hid,  acpi_config_table,
715 					     ARRAY_SIZE(acpi_config_table));
716 	if (!cfg)
717 		return SND_INTEL_DSP_DRIVER_ANY;
718 
719 	if (cfg->flags & FLAG_SST)
720 		return SND_INTEL_DSP_DRIVER_SST;
721 
722 	if (cfg->flags & FLAG_SOF)
723 		return SND_INTEL_DSP_DRIVER_SOF;
724 
725 	return SND_INTEL_DSP_DRIVER_SST;
726 }
727 EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe);
728 
729 MODULE_LICENSE("GPL v2");
730 MODULE_DESCRIPTION("Intel DSP config driver");
731 MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);
732