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