Linux 6.9-rc1
[linux-2.6-microblaze.git] / sound / hda / intel-dsp-config.c
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                                 .ident = "Google firmware",
341                                 .matches = {
342                                         DMI_MATCH(DMI_BIOS_VERSION, "Google"),
343                                 }
344                         },
345                         {}
346                 }
347         },
348         {
349                 .flags = FLAG_SOF,
350                 .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N,
351                 .codec_hid =  &essx_83x6,
352         },
353         {
354                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
355                 .device = PCI_DEVICE_ID_INTEL_HDA_JSL_N,
356         },
357 #endif
358
359 /* Tigerlake */
360 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
361         {
362                 .flags = FLAG_SOF,
363                 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP,
364                 .dmi_table = (const struct dmi_system_id []) {
365                         {
366                                 .ident = "Google Chromebooks",
367                                 .matches = {
368                                         DMI_MATCH(DMI_SYS_VENDOR, "Google"),
369                                 }
370                         },
371                         {
372                                 .ident = "UPX-TGL",
373                                 .matches = {
374                                         DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
375                                 }
376                         },
377                         {}
378                 }
379         },
380         {
381                 .flags = FLAG_SOF,
382                 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP,
383                 .codec_hid =  &essx_83x6,
384         },
385         {
386                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
387                 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_LP,
388         },
389         {
390                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
391                 .device = PCI_DEVICE_ID_INTEL_HDA_TGL_H,
392         },
393 #endif
394
395 /* Elkhart Lake */
396 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
397         {
398                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
399                 .device = PCI_DEVICE_ID_INTEL_HDA_EHL_0,
400         },
401         {
402                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
403                 .device = PCI_DEVICE_ID_INTEL_HDA_EHL_3,
404         },
405 #endif
406
407 /* Alder Lake / Raptor Lake */
408 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE)
409         {
410                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
411                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_S,
412         },
413         {
414                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
415                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_S,
416         },
417         {
418                 .flags = FLAG_SOF,
419                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P,
420                 .dmi_table = (const struct dmi_system_id []) {
421                         {
422                                 .ident = "Google Chromebooks",
423                                 .matches = {
424                                         DMI_MATCH(DMI_SYS_VENDOR, "Google"),
425                                 }
426                         },
427                         {}
428                 }
429         },
430         {
431                 .flags = FLAG_SOF,
432                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P,
433                 .codec_hid =  &essx_83x6,
434         },
435         {
436                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
437                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_P,
438         },
439         {
440                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
441                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PX,
442         },
443         {
444                 .flags = FLAG_SOF,
445                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS,
446                 .codec_hid =  &essx_83x6,
447         },
448         {
449                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
450                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_PS,
451         },
452         {
453                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
454                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_M,
455         },
456         {
457                 .flags = FLAG_SOF,
458                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N,
459                 .dmi_table = (const struct dmi_system_id []) {
460                         {
461                                 .ident = "Google Chromebooks",
462                                 .matches = {
463                                         DMI_MATCH(DMI_SYS_VENDOR, "Google"),
464                                 }
465                         },
466                         {}
467                 }
468         },
469         {
470                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
471                 .device = PCI_DEVICE_ID_INTEL_HDA_ADL_N,
472         },
473         {
474                 .flags = FLAG_SOF,
475                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0,
476                 .dmi_table = (const struct dmi_system_id []) {
477                         {
478                                 .ident = "Google Chromebooks",
479                                 .matches = {
480                                         DMI_MATCH(DMI_SYS_VENDOR, "Google"),
481                                 }
482                         },
483                         {}
484                 }
485         },
486         {
487                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
488                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_0,
489         },
490         {
491                 .flags = FLAG_SOF,
492                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1,
493                 .dmi_table = (const struct dmi_system_id []) {
494                         {
495                                 .ident = "Google Chromebooks",
496                                 .matches = {
497                                         DMI_MATCH(DMI_SYS_VENDOR, "Google"),
498                                 }
499                         },
500                         {}
501                 }
502         },
503         {
504                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
505                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_P_1,
506         },
507         {
508                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
509                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_M,
510         },
511         {
512                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
513                 .device = PCI_DEVICE_ID_INTEL_HDA_RPL_PX,
514         },
515 #endif
516
517 /* Meteor Lake */
518 #if IS_ENABLED(CONFIG_SND_SOC_SOF_METEORLAKE)
519         /* Meteorlake-P */
520         {
521                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
522                 .device = PCI_DEVICE_ID_INTEL_HDA_MTL,
523         },
524         /* ArrowLake-S */
525         {
526                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
527                 .device = PCI_DEVICE_ID_INTEL_HDA_ARL_S,
528         },
529         /* ArrowLake */
530         {
531                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
532                 .device = PCI_DEVICE_ID_INTEL_HDA_ARL,
533         },
534 #endif
535
536 /* Lunar Lake */
537 #if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE)
538         /* Lunarlake-P */
539         {
540                 .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
541                 .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P,
542         },
543 #endif
544 };
545
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                                 if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
562                                         break;
563                         if (i == table->codec_hid->num_codecs)
564                                 continue;
565                 }
566                 return table;
567         }
568         return NULL;
569 }
570
571 static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
572 {
573         struct nhlt_acpi_table *nhlt;
574         int ret = 0;
575
576         nhlt = intel_nhlt_init(&pci->dev);
577         if (nhlt) {
578                 if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC))
579                         ret = 1;
580                 intel_nhlt_free(nhlt);
581         }
582         return ret;
583 }
584
585 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
586 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
587 {
588         struct sdw_intel_acpi_info info;
589         acpi_handle handle;
590         int ret;
591
592         handle = ACPI_HANDLE(&pci->dev);
593
594         ret = sdw_intel_acpi_scan(handle, &info);
595         if (ret < 0)
596                 return ret;
597
598         return info.link_mask;
599 }
600 #else
601 static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
602 {
603         return 0;
604 }
605 #endif
606
607 int snd_intel_dsp_driver_probe(struct pci_dev *pci)
608 {
609         const struct config_entry *cfg;
610
611         /* Intel vendor only */
612         if (pci->vendor != PCI_VENDOR_ID_INTEL)
613                 return SND_INTEL_DSP_DRIVER_ANY;
614
615         /*
616          * Legacy devices don't have a PCI-based DSP and use HDaudio
617          * for HDMI/DP support, ignore kernel parameter
618          */
619         switch (pci->device) {
620         case PCI_DEVICE_ID_INTEL_HDA_BDW:
621         case PCI_DEVICE_ID_INTEL_HDA_HSW_0:
622         case PCI_DEVICE_ID_INTEL_HDA_HSW_2:
623         case PCI_DEVICE_ID_INTEL_HDA_HSW_3:
624         case PCI_DEVICE_ID_INTEL_HDA_BYT:
625         case PCI_DEVICE_ID_INTEL_HDA_BSW:
626                 return SND_INTEL_DSP_DRIVER_ANY;
627         }
628
629         if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
630                 return dsp_driver;
631
632         /*
633          * detect DSP by checking class/subclass/prog-id information
634          * class=04 subclass 03 prog-if 00: no DSP, use legacy driver
635          * class=04 subclass 01 prog-if 00: DSP is present
636          *  (and may be required e.g. for DMIC or SSP support)
637          * class=04 subclass 03 prog-if 80: use DSP or legacy mode
638          */
639         if (pci->class == 0x040300)
640                 return SND_INTEL_DSP_DRIVER_LEGACY;
641         if (pci->class != 0x040100 && pci->class != 0x040380) {
642                 dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class);
643                 return SND_INTEL_DSP_DRIVER_LEGACY;
644         }
645
646         dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
647
648         /* find the configuration for the specific device */
649         cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
650         if (!cfg)
651                 return SND_INTEL_DSP_DRIVER_ANY;
652
653         if (cfg->flags & FLAG_SOF) {
654                 if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
655                     snd_intel_dsp_check_soundwire(pci) > 0) {
656                         dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
657                         return SND_INTEL_DSP_DRIVER_SOF;
658                 }
659                 if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
660                     snd_intel_dsp_check_dmic(pci)) {
661                         dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
662                         return SND_INTEL_DSP_DRIVER_SOF;
663                 }
664                 if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
665                         return SND_INTEL_DSP_DRIVER_SOF;
666         }
667
668
669         if (cfg->flags & FLAG_SST) {
670                 if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) {
671                         if (snd_intel_dsp_check_dmic(pci)) {
672                                 dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n");
673                                 return SND_INTEL_DSP_DRIVER_SST;
674                         }
675                 } else {
676                         return SND_INTEL_DSP_DRIVER_SST;
677                 }
678         }
679
680         return SND_INTEL_DSP_DRIVER_LEGACY;
681 }
682 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
683
684 /* Should we default to SOF or SST for BYT/CHT ? */
685 #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
686     !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
687 #define FLAG_SST_OR_SOF_BYT     FLAG_SOF
688 #else
689 #define FLAG_SST_OR_SOF_BYT     FLAG_SST
690 #endif
691
692 /*
693  * configuration table
694  * - the order of similar ACPI ID entries is important!
695  * - the first successful match will win
696  */
697 static const struct config_entry acpi_config_table[] = {
698 #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
699     IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
700 /* BayTrail */
701         {
702                 .flags = FLAG_SST_OR_SOF_BYT,
703                 .acpi_hid = "80860F28",
704         },
705 /* CherryTrail */
706         {
707                 .flags = FLAG_SST_OR_SOF_BYT,
708                 .acpi_hid = "808622A8",
709         },
710 #endif
711 /* Broadwell */
712 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
713         {
714                 .flags = FLAG_SST,
715                 .acpi_hid = "INT3438"
716         },
717 #endif
718 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
719         {
720                 .flags = FLAG_SOF,
721                 .acpi_hid = "INT3438"
722         },
723 #endif
724 /* Haswell - not supported by SOF but added for consistency */
725 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
726         {
727                 .flags = FLAG_SST,
728                 .acpi_hid = "INT33C8"
729         },
730 #endif
731 };
732
733 static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],
734                                                                  const struct config_entry *table,
735                                                                  u32 len)
736 {
737         for (; len > 0; len--, table++) {
738                 if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN))
739                         continue;
740                 if (table->dmi_table && !dmi_check_system(table->dmi_table))
741                         continue;
742                 return table;
743         }
744         return NULL;
745 }
746
747 int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN])
748 {
749         const struct config_entry *cfg;
750
751         if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
752                 return dsp_driver;
753
754         if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) {
755                 dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n",
756                          SND_INTEL_DSP_DRIVER_LEGACY);
757         }
758
759         /* find the configuration for the specific device */
760         cfg = snd_intel_acpi_dsp_find_config(acpi_hid,  acpi_config_table,
761                                              ARRAY_SIZE(acpi_config_table));
762         if (!cfg)
763                 return SND_INTEL_DSP_DRIVER_ANY;
764
765         if (cfg->flags & FLAG_SST)
766                 return SND_INTEL_DSP_DRIVER_SST;
767
768         if (cfg->flags & FLAG_SOF)
769                 return SND_INTEL_DSP_DRIVER_SOF;
770
771         return SND_INTEL_DSP_DRIVER_SST;
772 }
773 EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe);
774
775 MODULE_LICENSE("GPL v2");
776 MODULE_DESCRIPTION("Intel DSP config driver");
777 MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);