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