xref: /linux/sound/hda/intel-dsp-config.c (revision 6537cfb395f352782918d8ee7b7f10ba2cc3cbf2)
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 	{
543 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
544 		.device = PCI_DEVICE_ID_INTEL_HDA_PTL_H,
545 	},
546 
547 #endif
548 
549 };
550 
snd_intel_dsp_find_config(struct pci_dev * pci,const struct config_entry * table,u32 len)551 static const struct config_entry *snd_intel_dsp_find_config
552 		(struct pci_dev *pci, const struct config_entry *table, u32 len)
553 {
554 	u16 device;
555 
556 	device = pci->device;
557 	for (; len > 0; len--, table++) {
558 		if (table->device != device)
559 			continue;
560 		if (table->dmi_table && !dmi_check_system(table->dmi_table))
561 			continue;
562 		if (table->codec_hid) {
563 			int i;
564 
565 			for (i = 0; i < table->codec_hid->num_codecs; i++) {
566 				struct nhlt_acpi_table *nhlt;
567 				bool ssp_found = false;
568 
569 				if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
570 					continue;
571 
572 				nhlt = intel_nhlt_init(&pci->dev);
573 				if (!nhlt) {
574 					dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
575 						 __func__, table->codec_hid->codecs[i]);
576 					continue;
577 				}
578 
579 				if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
580 				    intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
581 					ssp_found = true;
582 
583 				intel_nhlt_free(nhlt);
584 
585 				if (ssp_found)
586 					break;
587 
588 				dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
589 					 __func__, table->codec_hid->codecs[i]);
590 			}
591 			if (i == table->codec_hid->num_codecs)
592 				continue;
593 		}
594 		return table;
595 	}
596 	return NULL;
597 }
598 
snd_intel_dsp_check_dmic(struct pci_dev * pci)599 static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
600 {
601 	int ret = 0;
602 
603 	acpi_nhlt_get_gbl_table();
604 
605 	if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1))
606 		ret = 1;
607 
608 	acpi_nhlt_put_gbl_table();
609 
610 	return ret;
611 }
612 
613 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
snd_intel_dsp_check_soundwire(struct pci_dev * pci)614 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
615 {
616 	struct sdw_intel_acpi_info info;
617 	acpi_handle handle;
618 	int ret;
619 
620 	handle = ACPI_HANDLE(&pci->dev);
621 
622 	ret = sdw_intel_acpi_scan(handle, &info);
623 	if (ret < 0)
624 		return ret;
625 
626 	return info.link_mask;
627 }
628 #else
snd_intel_dsp_check_soundwire(struct pci_dev * pci)629 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
630 {
631 	return 0;
632 }
633 #endif
634 
snd_intel_dsp_driver_probe(struct pci_dev * pci)635 int snd_intel_dsp_driver_probe(struct pci_dev *pci)
636 {
637 	const struct config_entry *cfg;
638 
639 	/* Intel vendor only */
640 	if (pci->vendor != PCI_VENDOR_ID_INTEL)
641 		return SND_INTEL_DSP_DRIVER_ANY;
642 
643 	/*
644 	 * Legacy devices don't have a PCI-based DSP and use HDaudio
645 	 * for HDMI/DP support, ignore kernel parameter
646 	 */
647 	switch (pci->device) {
648 	case PCI_DEVICE_ID_INTEL_HDA_BDW:
649 	case PCI_DEVICE_ID_INTEL_HDA_HSW_0:
650 	case PCI_DEVICE_ID_INTEL_HDA_HSW_2:
651 	case PCI_DEVICE_ID_INTEL_HDA_HSW_3:
652 	case PCI_DEVICE_ID_INTEL_HDA_BYT:
653 	case PCI_DEVICE_ID_INTEL_HDA_BSW:
654 		return SND_INTEL_DSP_DRIVER_ANY;
655 	}
656 
657 	if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
658 		return dsp_driver;
659 
660 	/*
661 	 * detect DSP by checking class/subclass/prog-id information
662 	 * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
663 	 * class=04 subclass 01 prog-if 00: DSP is present
664 	 *  (and may be required e.g. for DMIC or SSP support)
665 	 * class=04 subclass 03 prog-if 80: use DSP or legacy mode
666 	 */
667 	if (pci->class == 0x040300)
668 		return SND_INTEL_DSP_DRIVER_LEGACY;
669 	if (pci->class != 0x040100 && pci->class != 0x040380) {
670 		dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class);
671 		return SND_INTEL_DSP_DRIVER_LEGACY;
672 	}
673 
674 	dev_dbg(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
675 
676 	/* find the configuration for the specific device */
677 	cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
678 	if (!cfg)
679 		return SND_INTEL_DSP_DRIVER_ANY;
680 
681 	if (cfg->flags & FLAG_SOF) {
682 		if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
683 		    snd_intel_dsp_check_soundwire(pci) > 0) {
684 			dev_info_once(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
685 			return SND_INTEL_DSP_DRIVER_SOF;
686 		}
687 		if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
688 		    snd_intel_dsp_check_dmic(pci)) {
689 			dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
690 			return SND_INTEL_DSP_DRIVER_SOF;
691 		}
692 		if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
693 			return SND_INTEL_DSP_DRIVER_SOF;
694 	}
695 
696 
697 	if (cfg->flags & FLAG_SST) {
698 		if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) {
699 			if (snd_intel_dsp_check_dmic(pci)) {
700 				dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n");
701 				return SND_INTEL_DSP_DRIVER_SST;
702 			}
703 		} else {
704 			return SND_INTEL_DSP_DRIVER_SST;
705 		}
706 	}
707 
708 	return SND_INTEL_DSP_DRIVER_LEGACY;
709 }
710 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
711 
712 /* Should we default to SOF or SST for BYT/CHT ? */
713 #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
714     !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
715 #define FLAG_SST_OR_SOF_BYT	FLAG_SOF
716 #else
717 #define FLAG_SST_OR_SOF_BYT	FLAG_SST
718 #endif
719 
720 /*
721  * configuration table
722  * - the order of similar ACPI ID entries is important!
723  * - the first successful match will win
724  */
725 static const struct config_entry acpi_config_table[] = {
726 #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
727     IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
728 /* BayTrail */
729 	{
730 		.flags = FLAG_SST_OR_SOF_BYT,
731 		.acpi_hid = "LPE0F28",
732 	},
733 	{
734 		.flags = FLAG_SST_OR_SOF_BYT,
735 		.acpi_hid = "80860F28",
736 	},
737 /* CherryTrail */
738 	{
739 		.flags = FLAG_SST_OR_SOF_BYT,
740 		.acpi_hid = "808622A8",
741 	},
742 #endif
743 /* Broadwell */
744 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
745 	{
746 		.flags = FLAG_SST,
747 		.acpi_hid = "INT3438"
748 	},
749 #endif
750 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
751 	{
752 		.flags = FLAG_SOF,
753 		.acpi_hid = "INT3438"
754 	},
755 #endif
756 /* Haswell - not supported by SOF but added for consistency */
757 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
758 	{
759 		.flags = FLAG_SST,
760 		.acpi_hid = "INT33C8"
761 	},
762 #endif
763 };
764 
snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],const struct config_entry * table,u32 len)765 static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],
766 								 const struct config_entry *table,
767 								 u32 len)
768 {
769 	for (; len > 0; len--, table++) {
770 		if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN))
771 			continue;
772 		if (table->dmi_table && !dmi_check_system(table->dmi_table))
773 			continue;
774 		return table;
775 	}
776 	return NULL;
777 }
778 
snd_intel_acpi_dsp_driver_probe(struct device * dev,const u8 acpi_hid[ACPI_ID_LEN])779 int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN])
780 {
781 	const struct config_entry *cfg;
782 
783 	if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
784 		return dsp_driver;
785 
786 	if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) {
787 		dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n",
788 			 SND_INTEL_DSP_DRIVER_LEGACY);
789 	}
790 
791 	/* find the configuration for the specific device */
792 	cfg = snd_intel_acpi_dsp_find_config(acpi_hid,  acpi_config_table,
793 					     ARRAY_SIZE(acpi_config_table));
794 	if (!cfg)
795 		return SND_INTEL_DSP_DRIVER_ANY;
796 
797 	if (cfg->flags & FLAG_SST)
798 		return SND_INTEL_DSP_DRIVER_SST;
799 
800 	if (cfg->flags & FLAG_SOF)
801 		return SND_INTEL_DSP_DRIVER_SOF;
802 
803 	return SND_INTEL_DSP_DRIVER_SST;
804 }
805 EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe);
806 
807 MODULE_LICENSE("GPL v2");
808 MODULE_DESCRIPTION("Intel DSP config driver");
809 MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
810