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