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