Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/hda/core/intel-dsp-config.c
26424 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_GML,
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_GML,
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
};
582
583
static const struct config_entry *snd_intel_dsp_find_config
584
(struct pci_dev *pci, const struct config_entry *table, u32 len)
585
{
586
u16 device;
587
588
device = pci->device;
589
for (; len > 0; len--, table++) {
590
if (table->device != device)
591
continue;
592
if (table->dmi_table && !dmi_check_system(table->dmi_table))
593
continue;
594
if (table->codec_hid) {
595
int i;
596
597
for (i = 0; i < table->codec_hid->num_codecs; i++) {
598
struct nhlt_acpi_table *nhlt;
599
bool ssp_found = false;
600
601
if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
602
continue;
603
604
nhlt = intel_nhlt_init(&pci->dev);
605
if (!nhlt) {
606
dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
607
__func__, table->codec_hid->codecs[i]);
608
continue;
609
}
610
611
if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
612
intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
613
ssp_found = true;
614
615
intel_nhlt_free(nhlt);
616
617
if (ssp_found)
618
break;
619
620
dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
621
__func__, table->codec_hid->codecs[i]);
622
}
623
if (i == table->codec_hid->num_codecs)
624
continue;
625
}
626
return table;
627
}
628
return NULL;
629
}
630
631
static int snd_intel_dsp_check_dmic(struct pci_dev *pci)
632
{
633
int ret = 0;
634
635
acpi_nhlt_get_gbl_table();
636
637
if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1))
638
ret = 1;
639
640
acpi_nhlt_put_gbl_table();
641
642
return ret;
643
}
644
645
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
646
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
647
{
648
struct sdw_intel_acpi_info info;
649
acpi_handle handle;
650
int ret;
651
652
handle = ACPI_HANDLE(&pci->dev);
653
654
ret = sdw_intel_acpi_scan(handle, &info);
655
if (ret < 0)
656
return ret;
657
658
return info.link_mask;
659
}
660
#else
661
static int snd_intel_dsp_check_soundwire(struct pci_dev *pci)
662
{
663
return 0;
664
}
665
#endif
666
667
int snd_intel_dsp_driver_probe(struct pci_dev *pci)
668
{
669
const struct config_entry *cfg;
670
671
/* Intel vendor only */
672
if (pci->vendor != PCI_VENDOR_ID_INTEL)
673
return SND_INTEL_DSP_DRIVER_ANY;
674
675
/*
676
* Legacy devices don't have a PCI-based DSP and use HDaudio
677
* for HDMI/DP support, ignore kernel parameter
678
*/
679
switch (pci->device) {
680
case PCI_DEVICE_ID_INTEL_HDA_BDW:
681
case PCI_DEVICE_ID_INTEL_HDA_HSW_0:
682
case PCI_DEVICE_ID_INTEL_HDA_HSW_2:
683
case PCI_DEVICE_ID_INTEL_HDA_HSW_3:
684
case PCI_DEVICE_ID_INTEL_HDA_BYT:
685
case PCI_DEVICE_ID_INTEL_HDA_BSW:
686
return SND_INTEL_DSP_DRIVER_ANY;
687
}
688
689
if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
690
return dsp_driver;
691
692
/*
693
* detect DSP by checking class/subclass/prog-id information
694
* class=04 subclass 03 prog-if 00: no DSP, use legacy driver
695
* class=04 subclass 01 prog-if 00: DSP is present
696
* (and may be required e.g. for DMIC or SSP support)
697
* class=04 subclass 03 prog-if 80: use DSP or legacy mode
698
*/
699
if (pci->class == 0x040300)
700
return SND_INTEL_DSP_DRIVER_LEGACY;
701
if (pci->class != 0x040100 && pci->class != 0x040380) {
702
dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class);
703
return SND_INTEL_DSP_DRIVER_LEGACY;
704
}
705
706
dev_dbg(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
707
708
/* find the configuration for the specific device */
709
cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table));
710
if (!cfg)
711
return SND_INTEL_DSP_DRIVER_ANY;
712
713
if (cfg->flags & FLAG_SOF) {
714
if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE &&
715
snd_intel_dsp_check_soundwire(pci) > 0) {
716
dev_info_once(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n");
717
return SND_INTEL_DSP_DRIVER_SOF;
718
}
719
if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC &&
720
snd_intel_dsp_check_dmic(pci)) {
721
dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n");
722
return SND_INTEL_DSP_DRIVER_SOF;
723
}
724
if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE))
725
return SND_INTEL_DSP_DRIVER_SOF;
726
}
727
728
729
if (cfg->flags & FLAG_SST) {
730
if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) {
731
if (snd_intel_dsp_check_dmic(pci)) {
732
dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n");
733
return SND_INTEL_DSP_DRIVER_SST;
734
}
735
} else {
736
return SND_INTEL_DSP_DRIVER_SST;
737
}
738
}
739
740
return SND_INTEL_DSP_DRIVER_LEGACY;
741
}
742
EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
743
744
/* Should we default to SOF or SST for BYT/CHT ? */
745
#if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
746
!IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
747
#define FLAG_SST_OR_SOF_BYT FLAG_SOF
748
#else
749
#define FLAG_SST_OR_SOF_BYT FLAG_SST
750
#endif
751
752
/*
753
* configuration table
754
* - the order of similar ACPI ID entries is important!
755
* - the first successful match will win
756
*/
757
static const struct config_entry acpi_config_table[] = {
758
#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
759
IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
760
/* BayTrail */
761
{
762
.flags = FLAG_SST_OR_SOF_BYT,
763
.acpi_hid = "LPE0F28",
764
},
765
{
766
.flags = FLAG_SST_OR_SOF_BYT,
767
.acpi_hid = "80860F28",
768
},
769
/* CherryTrail */
770
{
771
.flags = FLAG_SST_OR_SOF_BYT,
772
.acpi_hid = "808622A8",
773
},
774
#endif
775
/* Broadwell */
776
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
777
{
778
.flags = FLAG_SST,
779
.acpi_hid = "INT3438"
780
},
781
#endif
782
#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
783
{
784
.flags = FLAG_SOF,
785
.acpi_hid = "INT3438"
786
},
787
#endif
788
/* Haswell - not supported by SOF but added for consistency */
789
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT)
790
{
791
.flags = FLAG_SST,
792
.acpi_hid = "INT33C8"
793
},
794
#endif
795
};
796
797
static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN],
798
const struct config_entry *table,
799
u32 len)
800
{
801
for (; len > 0; len--, table++) {
802
if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN))
803
continue;
804
if (table->dmi_table && !dmi_check_system(table->dmi_table))
805
continue;
806
return table;
807
}
808
return NULL;
809
}
810
811
int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN])
812
{
813
const struct config_entry *cfg;
814
815
if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST)
816
return dsp_driver;
817
818
if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) {
819
dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n",
820
SND_INTEL_DSP_DRIVER_LEGACY);
821
}
822
823
/* find the configuration for the specific device */
824
cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table,
825
ARRAY_SIZE(acpi_config_table));
826
if (!cfg)
827
return SND_INTEL_DSP_DRIVER_ANY;
828
829
if (cfg->flags & FLAG_SST)
830
return SND_INTEL_DSP_DRIVER_SST;
831
832
if (cfg->flags & FLAG_SOF)
833
return SND_INTEL_DSP_DRIVER_SOF;
834
835
return SND_INTEL_DSP_DRIVER_SST;
836
}
837
EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe);
838
839
MODULE_LICENSE("GPL v2");
840
MODULE_DESCRIPTION("Intel DSP config driver");
841
MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
842
843