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