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