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