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