]>
Commit | Line | Data |
---|---|---|
82d9d54a JK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2019 Jaroslav Kysela <perex@perex.cz> | |
3 | ||
06508575 | 4 | #include <linux/acpi.h> |
82d9d54a JK |
5 | #include <linux/bits.h> |
6 | #include <linux/dmi.h> | |
7 | #include <linux/module.h> | |
8 | #include <linux/pci.h> | |
06508575 PLB |
9 | #include <linux/soundwire/sdw.h> |
10 | #include <linux/soundwire/sdw_intel.h> | |
82d9d54a JK |
11 | #include <sound/core.h> |
12 | #include <sound/intel-dsp-config.h> | |
13 | #include <sound/intel-nhlt.h> | |
de24d97f | 14 | #include <sound/soc-acpi.h> |
82d9d54a JK |
15 | |
16 | static int dsp_driver; | |
17 | ||
18 | module_param(dsp_driver, int, 0444); | |
19 | MODULE_PARM_DESC(dsp_driver, "Force the DSP driver for Intel DSP (0=auto, 1=legacy, 2=SST, 3=SOF)"); | |
20 | ||
06508575 PLB |
21 | #define FLAG_SST BIT(0) |
22 | #define FLAG_SOF BIT(1) | |
df1fceac | 23 | #define FLAG_SST_ONLY_IF_DMIC BIT(15) |
06508575 PLB |
24 | #define FLAG_SOF_ONLY_IF_DMIC BIT(16) |
25 | #define FLAG_SOF_ONLY_IF_SOUNDWIRE BIT(17) | |
26 | ||
27 | #define FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE (FLAG_SOF_ONLY_IF_DMIC | \ | |
28 | FLAG_SOF_ONLY_IF_SOUNDWIRE) | |
82d9d54a JK |
29 | |
30 | struct config_entry { | |
31 | u32 flags; | |
32 | u16 device; | |
b5682305 | 33 | u8 acpi_hid[ACPI_ID_LEN]; |
82d9d54a | 34 | const struct dmi_system_id *dmi_table; |
de24d97f PLB |
35 | const struct snd_soc_acpi_codecs *codec_hid; |
36 | }; | |
37 | ||
38 | static const struct snd_soc_acpi_codecs __maybe_unused essx_83x6 = { | |
39 | .num_codecs = 3, | |
40 | .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, | |
82d9d54a JK |
41 | }; |
42 | ||
43 | /* | |
44 | * configuration table | |
45 | * - the order of similar PCI ID entries is important! | |
46 | * - the first successful match will win | |
47 | */ | |
48 | static const struct config_entry config_table[] = { | |
cc8f81c7 PLB |
49 | /* Merrifield */ |
50 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) | |
82d9d54a | 51 | { |
cc8f81c7 PLB |
52 | .flags = FLAG_SOF, |
53 | .device = 0x119a, | |
82d9d54a | 54 | }, |
cc8f81c7 PLB |
55 | #endif |
56 | /* Broxton-T */ | |
57 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) | |
82d9d54a JK |
58 | { |
59 | .flags = FLAG_SOF, | |
cc8f81c7 | 60 | .device = 0x1a98, |
82d9d54a JK |
61 | }, |
62 | #endif | |
cc8f81c7 PLB |
63 | /* |
64 | * Apollolake (Broxton-P) | |
b79de57b | 65 | * the legacy HDAudio driver is used except on Up Squared (SOF) and |
9d36ceab | 66 | * Chromebooks (SST), as well as devices based on the ES8336 codec |
cc8f81c7 PLB |
67 | */ |
68 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) | |
82d9d54a | 69 | { |
cc8f81c7 PLB |
70 | .flags = FLAG_SOF, |
71 | .device = 0x5a98, | |
72 | .dmi_table = (const struct dmi_system_id []) { | |
73 | { | |
74 | .ident = "Up Squared", | |
75 | .matches = { | |
76 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), | |
77 | DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), | |
78 | } | |
79 | }, | |
80 | {} | |
81 | } | |
82d9d54a | 82 | }, |
9d36ceab PLB |
83 | { |
84 | .flags = FLAG_SOF, | |
85 | .device = 0x5a98, | |
de24d97f | 86 | .codec_hid = &essx_83x6, |
9d36ceab | 87 | }, |
cc8f81c7 PLB |
88 | #endif |
89 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) | |
82d9d54a | 90 | { |
cc8f81c7 PLB |
91 | .flags = FLAG_SST, |
92 | .device = 0x5a98, | |
93 | .dmi_table = (const struct dmi_system_id []) { | |
94 | { | |
95 | .ident = "Google Chromebooks", | |
96 | .matches = { | |
97 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
98 | } | |
99 | }, | |
100 | {} | |
101 | } | |
82d9d54a JK |
102 | }, |
103 | #endif | |
cc8f81c7 | 104 | /* |
b79de57b | 105 | * Skylake and Kabylake use legacy HDAudio driver except for Google |
cc8f81c7 PLB |
106 | * Chromebooks (SST) |
107 | */ | |
108 | ||
109 | /* Sunrise Point-LP */ | |
110 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) | |
82d9d54a | 111 | { |
cc8f81c7 PLB |
112 | .flags = FLAG_SST, |
113 | .device = 0x9d70, | |
114 | .dmi_table = (const struct dmi_system_id []) { | |
115 | { | |
116 | .ident = "Google Chromebooks", | |
117 | .matches = { | |
118 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
119 | } | |
120 | }, | |
121 | {} | |
122 | } | |
82d9d54a | 123 | }, |
df1fceac CR |
124 | { |
125 | .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, | |
126 | .device = 0x9d70, | |
127 | }, | |
82d9d54a | 128 | #endif |
cc8f81c7 PLB |
129 | /* Kabylake-LP */ |
130 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) | |
82d9d54a | 131 | { |
cc8f81c7 PLB |
132 | .flags = FLAG_SST, |
133 | .device = 0x9d71, | |
134 | .dmi_table = (const struct dmi_system_id []) { | |
135 | { | |
136 | .ident = "Google Chromebooks", | |
137 | .matches = { | |
138 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
139 | } | |
140 | }, | |
141 | {} | |
142 | } | |
82d9d54a | 143 | }, |
df1fceac CR |
144 | { |
145 | .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, | |
146 | .device = 0x9d71, | |
147 | }, | |
82d9d54a | 148 | #endif |
cc8f81c7 PLB |
149 | |
150 | /* | |
b79de57b | 151 | * Geminilake uses legacy HDAudio driver except for Google |
9d36ceab | 152 | * Chromebooks and devices based on the ES8336 codec |
cc8f81c7 | 153 | */ |
82d9d54a JK |
154 | /* Geminilake */ |
155 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) | |
156 | { | |
157 | .flags = FLAG_SOF, | |
158 | .device = 0x3198, | |
159 | .dmi_table = (const struct dmi_system_id []) { | |
160 | { | |
161 | .ident = "Google Chromebooks", | |
162 | .matches = { | |
163 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
164 | } | |
165 | }, | |
166 | {} | |
167 | } | |
168 | }, | |
9d36ceab PLB |
169 | { |
170 | .flags = FLAG_SOF, | |
171 | .device = 0x3198, | |
de24d97f | 172 | .codec_hid = &essx_83x6, |
9d36ceab | 173 | }, |
82d9d54a | 174 | #endif |
cc8f81c7 PLB |
175 | |
176 | /* | |
177 | * CoffeeLake, CannonLake, CometLake, IceLake, TigerLake use legacy | |
b79de57b | 178 | * HDAudio driver except for Google Chromebooks and when DMICs are |
cc8f81c7 PLB |
179 | * present. Two cases are required since Coreboot does not expose NHLT |
180 | * tables. | |
181 | * | |
182 | * When the Chromebook quirk is not present, it's based on information | |
183 | * that no such device exists. When the quirk is present, it could be | |
184 | * either based on product information or a placeholder. | |
185 | */ | |
186 | ||
187 | /* Cannonlake */ | |
188 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_CANNONLAKE) | |
82d9d54a | 189 | { |
cc8f81c7 PLB |
190 | .flags = FLAG_SOF, |
191 | .device = 0x9dc8, | |
192 | .dmi_table = (const struct dmi_system_id []) { | |
193 | { | |
194 | .ident = "Google Chromebooks", | |
195 | .matches = { | |
196 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
197 | } | |
198 | }, | |
33fa35db PLB |
199 | { |
200 | .ident = "UP-WHL", | |
201 | .matches = { | |
202 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), | |
203 | } | |
204 | }, | |
cc8f81c7 PLB |
205 | {} |
206 | } | |
82d9d54a | 207 | }, |
cded07a2 PLB |
208 | { |
209 | .flags = FLAG_SOF, | |
210 | .device = 0x09dc8, | |
211 | .codec_hid = &essx_83x6, | |
212 | }, | |
82d9d54a | 213 | { |
06508575 | 214 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
cc8f81c7 | 215 | .device = 0x9dc8, |
82d9d54a JK |
216 | }, |
217 | #endif | |
cc8f81c7 PLB |
218 | |
219 | /* Coffelake */ | |
220 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE) | |
221 | { | |
222 | .flags = FLAG_SOF, | |
223 | .device = 0xa348, | |
224 | .dmi_table = (const struct dmi_system_id []) { | |
225 | { | |
226 | .ident = "Google Chromebooks", | |
227 | .matches = { | |
228 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
229 | } | |
230 | }, | |
231 | {} | |
232 | } | |
233 | }, | |
82d9d54a | 234 | { |
06508575 | 235 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
cc8f81c7 | 236 | .device = 0xa348, |
82d9d54a JK |
237 | }, |
238 | #endif | |
cc8f81c7 | 239 | |
4228668e | 240 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) |
cc8f81c7 | 241 | /* Cometlake-LP */ |
82d9d54a JK |
242 | { |
243 | .flags = FLAG_SOF, | |
cc8f81c7 | 244 | .device = 0x02c8, |
82d9d54a JK |
245 | .dmi_table = (const struct dmi_system_id []) { |
246 | { | |
cc8f81c7 | 247 | .ident = "Google Chromebooks", |
82d9d54a | 248 | .matches = { |
cc8f81c7 | 249 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), |
82d9d54a JK |
250 | } |
251 | }, | |
06508575 PLB |
252 | { |
253 | .matches = { | |
254 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | |
255 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") | |
256 | }, | |
257 | }, | |
258 | { | |
259 | /* early version of SKU 09C6 */ | |
260 | .matches = { | |
261 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | |
262 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") | |
263 | }, | |
264 | }, | |
82d9d54a JK |
265 | {} |
266 | } | |
267 | }, | |
82d9d54a | 268 | { |
081c7370 | 269 | .flags = FLAG_SOF, |
cc8f81c7 | 270 | .device = 0x02c8, |
de24d97f | 271 | .codec_hid = &essx_83x6, |
82d9d54a | 272 | }, |
ae26c08e | 273 | { |
081c7370 | 274 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
ae26c08e | 275 | .device = 0x02c8, |
ae26c08e | 276 | }, |
cc8f81c7 | 277 | /* Cometlake-H */ |
82d9d54a | 278 | { |
06508575 PLB |
279 | .flags = FLAG_SOF, |
280 | .device = 0x06c8, | |
281 | .dmi_table = (const struct dmi_system_id []) { | |
282 | { | |
283 | .matches = { | |
284 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | |
285 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), | |
286 | }, | |
287 | }, | |
288 | { | |
289 | .matches = { | |
290 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | |
291 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), | |
292 | }, | |
293 | }, | |
294 | {} | |
295 | } | |
296 | }, | |
297 | { | |
ae26c08e PLB |
298 | .flags = FLAG_SOF, |
299 | .device = 0x06c8, | |
de24d97f | 300 | .codec_hid = &essx_83x6, |
ae26c08e | 301 | }, |
081c7370 BL |
302 | { |
303 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
304 | .device = 0x06c8, | |
305 | }, | |
82d9d54a | 306 | #endif |
cc8f81c7 PLB |
307 | |
308 | /* Icelake */ | |
309 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) | |
82d9d54a | 310 | { |
cc8f81c7 PLB |
311 | .flags = FLAG_SOF, |
312 | .device = 0x34c8, | |
313 | .dmi_table = (const struct dmi_system_id []) { | |
314 | { | |
315 | .ident = "Google Chromebooks", | |
316 | .matches = { | |
317 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
318 | } | |
319 | }, | |
320 | {} | |
321 | } | |
82d9d54a | 322 | }, |
82d9d54a | 323 | { |
06508575 | 324 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
cc8f81c7 | 325 | .device = 0x34c8, |
82d9d54a JK |
326 | }, |
327 | #endif | |
cc8f81c7 | 328 | |
19980aa1 | 329 | /* Jasper Lake */ |
fa9730b4 | 330 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) |
19980aa1 BL |
331 | { |
332 | .flags = FLAG_SOF, | |
333 | .device = 0x4dc8, | |
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 | } | |
343 | }, | |
fa9730b4 PLB |
344 | { |
345 | .flags = FLAG_SOF, | |
346 | .device = 0x4dc8, | |
de24d97f | 347 | .codec_hid = &essx_83x6, |
fa9730b4 | 348 | }, |
19980aa1 BL |
349 | { |
350 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
351 | .device = 0x4dc8, | |
352 | }, | |
fa9730b4 PLB |
353 | #endif |
354 | ||
82d9d54a JK |
355 | /* Tigerlake */ |
356 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) | |
cc8f81c7 PLB |
357 | { |
358 | .flags = FLAG_SOF, | |
359 | .device = 0xa0c8, | |
360 | .dmi_table = (const struct dmi_system_id []) { | |
361 | { | |
362 | .ident = "Google Chromebooks", | |
363 | .matches = { | |
364 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
365 | } | |
366 | }, | |
33fa35db PLB |
367 | { |
368 | .ident = "UPX-TGL", | |
369 | .matches = { | |
370 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), | |
371 | } | |
372 | }, | |
cc8f81c7 PLB |
373 | {} |
374 | } | |
375 | }, | |
82d9d54a | 376 | { |
081c7370 | 377 | .flags = FLAG_SOF, |
82d9d54a | 378 | .device = 0xa0c8, |
de24d97f | 379 | .codec_hid = &essx_83x6, |
82d9d54a | 380 | }, |
c5b5ff60 BL |
381 | { |
382 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
081c7370 | 383 | .device = 0xa0c8, |
c5b5ff60 | 384 | }, |
9d36ceab | 385 | { |
081c7370 BL |
386 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
387 | .device = 0x43c8, | |
9d36ceab | 388 | }, |
82d9d54a | 389 | #endif |
cc8f81c7 PLB |
390 | |
391 | /* Elkhart Lake */ | |
392 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) | |
82d9d54a JK |
393 | { |
394 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
cc8f81c7 | 395 | .device = 0x4b55, |
82d9d54a | 396 | }, |
114613f6 PLB |
397 | { |
398 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
399 | .device = 0x4b58, | |
400 | }, | |
82d9d54a | 401 | #endif |
cc8f81c7 | 402 | |
c4294d7f KV |
403 | /* Alder Lake */ |
404 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) | |
d52eee98 | 405 | /* Alderlake-S */ |
c4294d7f KV |
406 | { |
407 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
408 | .device = 0x7ad0, | |
409 | }, | |
d52eee98 | 410 | /* RaptorLake-S */ |
c4294d7f KV |
411 | { |
412 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
d52eee98 | 413 | .device = 0x7a50, |
c4294d7f | 414 | }, |
d52eee98 | 415 | /* Alderlake-P */ |
2ec8b081 MR |
416 | { |
417 | .flags = FLAG_SOF, | |
418 | .device = 0x51c8, | |
419 | .codec_hid = &essx_83x6, | |
420 | }, | |
4ad7935d KV |
421 | { |
422 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
d52eee98 | 423 | .device = 0x51c8, |
4ad7935d | 424 | }, |
ca1ece24 KV |
425 | { |
426 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
427 | .device = 0x51cd, | |
428 | }, | |
d52eee98 PLB |
429 | /* Alderlake-PS */ |
430 | { | |
431 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
432 | .device = 0x51c9, | |
433 | }, | |
434 | /* Alderlake-M */ | |
435 | { | |
436 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
437 | .device = 0x51cc, | |
438 | }, | |
439 | /* Alderlake-N */ | |
4d5a628d KV |
440 | { |
441 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
442 | .device = 0x54c8, | |
443 | }, | |
b07908ab GS |
444 | /* RaptorLake-P */ |
445 | { | |
446 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
447 | .device = 0x51ca, | |
448 | }, | |
449 | { | |
450 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
451 | .device = 0x51cb, | |
452 | }, | |
c35fbea4 PLB |
453 | /* RaptorLake-M */ |
454 | { | |
455 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
456 | .device = 0x51ce, | |
457 | }, | |
458 | /* RaptorLake-PX */ | |
459 | { | |
460 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
461 | .device = 0x51cf, | |
462 | }, | |
c4294d7f KV |
463 | #endif |
464 | ||
82d9d54a JK |
465 | }; |
466 | ||
467 | static const struct config_entry *snd_intel_dsp_find_config | |
468 | (struct pci_dev *pci, const struct config_entry *table, u32 len) | |
469 | { | |
470 | u16 device; | |
471 | ||
472 | device = pci->device; | |
473 | for (; len > 0; len--, table++) { | |
474 | if (table->device != device) | |
475 | continue; | |
476 | if (table->dmi_table && !dmi_check_system(table->dmi_table)) | |
477 | continue; | |
de24d97f PLB |
478 | if (table->codec_hid) { |
479 | int i; | |
480 | ||
481 | for (i = 0; i < table->codec_hid->num_codecs; i++) | |
482 | if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) | |
483 | break; | |
484 | if (i == table->codec_hid->num_codecs) | |
485 | continue; | |
486 | } | |
82d9d54a JK |
487 | return table; |
488 | } | |
489 | return NULL; | |
490 | } | |
491 | ||
492 | static int snd_intel_dsp_check_dmic(struct pci_dev *pci) | |
493 | { | |
494 | struct nhlt_acpi_table *nhlt; | |
495 | int ret = 0; | |
496 | ||
497 | nhlt = intel_nhlt_init(&pci->dev); | |
498 | if (nhlt) { | |
8235a08b | 499 | if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC)) |
82d9d54a JK |
500 | ret = 1; |
501 | intel_nhlt_free(nhlt); | |
502 | } | |
503 | return ret; | |
504 | } | |
505 | ||
06508575 PLB |
506 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) |
507 | static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) | |
508 | { | |
509 | struct sdw_intel_acpi_info info; | |
510 | acpi_handle handle; | |
511 | int ret; | |
512 | ||
513 | handle = ACPI_HANDLE(&pci->dev); | |
514 | ||
515 | ret = sdw_intel_acpi_scan(handle, &info); | |
516 | if (ret < 0) | |
517 | return ret; | |
518 | ||
519 | return info.link_mask; | |
520 | } | |
521 | #else | |
522 | static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) | |
523 | { | |
524 | return 0; | |
525 | } | |
526 | #endif | |
527 | ||
82d9d54a JK |
528 | int snd_intel_dsp_driver_probe(struct pci_dev *pci) |
529 | { | |
530 | const struct config_entry *cfg; | |
531 | ||
82d9d54a | 532 | /* Intel vendor only */ |
91636a82 | 533 | if (pci->vendor != 0x8086) |
82d9d54a JK |
534 | return SND_INTEL_DSP_DRIVER_ANY; |
535 | ||
0e5cc221 PLB |
536 | /* |
537 | * Legacy devices don't have a PCI-based DSP and use HDaudio | |
538 | * for HDMI/DP support, ignore kernel parameter | |
539 | */ | |
540 | switch (pci->device) { | |
541 | case 0x160c: /* Broadwell */ | |
542 | case 0x0a0c: /* Haswell */ | |
543 | case 0x0c0c: | |
544 | case 0x0d0c: | |
545 | case 0x0f04: /* Baytrail */ | |
546 | case 0x2284: /* Braswell */ | |
547 | return SND_INTEL_DSP_DRIVER_ANY; | |
548 | } | |
549 | ||
91636a82 TI |
550 | if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) |
551 | return dsp_driver; | |
552 | ||
82d9d54a JK |
553 | /* |
554 | * detect DSP by checking class/subclass/prog-id information | |
555 | * class=04 subclass 03 prog-if 00: no DSP, use legacy driver | |
556 | * class=04 subclass 01 prog-if 00: DSP is present | |
557 | * (and may be required e.g. for DMIC or SSP support) | |
558 | * class=04 subclass 03 prog-if 80: use DSP or legacy mode | |
559 | */ | |
560 | if (pci->class == 0x040300) | |
561 | return SND_INTEL_DSP_DRIVER_LEGACY; | |
562 | if (pci->class != 0x040100 && pci->class != 0x040380) { | |
b79de57b | 563 | dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); |
82d9d54a JK |
564 | return SND_INTEL_DSP_DRIVER_LEGACY; |
565 | } | |
566 | ||
567 | dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); | |
568 | ||
569 | /* find the configuration for the specific device */ | |
570 | cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); | |
571 | if (!cfg) | |
572 | return SND_INTEL_DSP_DRIVER_ANY; | |
573 | ||
574 | if (cfg->flags & FLAG_SOF) { | |
06508575 PLB |
575 | if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && |
576 | snd_intel_dsp_check_soundwire(pci) > 0) { | |
577 | dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); | |
578 | return SND_INTEL_DSP_DRIVER_SOF; | |
579 | } | |
580 | if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && | |
581 | snd_intel_dsp_check_dmic(pci)) { | |
582 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); | |
82d9d54a JK |
583 | return SND_INTEL_DSP_DRIVER_SOF; |
584 | } | |
06508575 PLB |
585 | if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) |
586 | return SND_INTEL_DSP_DRIVER_SOF; | |
82d9d54a JK |
587 | } |
588 | ||
df1fceac CR |
589 | |
590 | if (cfg->flags & FLAG_SST) { | |
591 | if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { | |
592 | if (snd_intel_dsp_check_dmic(pci)) { | |
593 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); | |
594 | return SND_INTEL_DSP_DRIVER_SST; | |
595 | } | |
596 | } else { | |
597 | return SND_INTEL_DSP_DRIVER_SST; | |
598 | } | |
599 | } | |
82d9d54a JK |
600 | |
601 | return SND_INTEL_DSP_DRIVER_LEGACY; | |
602 | } | |
603 | EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); | |
604 | ||
5427c7d6 HG |
605 | /* Should we default to SOF or SST for BYT/CHT ? */ |
606 | #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ | |
607 | !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) | |
608 | #define FLAG_SST_OR_SOF_BYT FLAG_SOF | |
609 | #else | |
610 | #define FLAG_SST_OR_SOF_BYT FLAG_SST | |
611 | #endif | |
612 | ||
b5682305 PLB |
613 | /* |
614 | * configuration table | |
615 | * - the order of similar ACPI ID entries is important! | |
616 | * - the first successful match will win | |
617 | */ | |
618 | static const struct config_entry acpi_config_table[] = { | |
5427c7d6 HG |
619 | #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ |
620 | IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) | |
b5682305 | 621 | /* BayTrail */ |
b5682305 | 622 | { |
5427c7d6 | 623 | .flags = FLAG_SST_OR_SOF_BYT, |
b5682305 PLB |
624 | .acpi_hid = "80860F28", |
625 | }, | |
b5682305 | 626 | /* CherryTrail */ |
b5682305 | 627 | { |
5427c7d6 | 628 | .flags = FLAG_SST_OR_SOF_BYT, |
b5682305 PLB |
629 | .acpi_hid = "808622A8", |
630 | }, | |
631 | #endif | |
803e5913 PLB |
632 | /* Broadwell */ |
633 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) | |
634 | { | |
635 | .flags = FLAG_SST, | |
636 | .acpi_hid = "INT3438" | |
637 | }, | |
638 | #endif | |
639 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) | |
640 | { | |
641 | .flags = FLAG_SOF, | |
642 | .acpi_hid = "INT3438" | |
643 | }, | |
644 | #endif | |
645 | /* Haswell - not supported by SOF but added for consistency */ | |
646 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) | |
647 | { | |
648 | .flags = FLAG_SST, | |
649 | .acpi_hid = "INT33C8" | |
650 | }, | |
651 | #endif | |
b5682305 PLB |
652 | }; |
653 | ||
654 | static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], | |
655 | const struct config_entry *table, | |
656 | u32 len) | |
657 | { | |
658 | for (; len > 0; len--, table++) { | |
659 | if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) | |
660 | continue; | |
661 | if (table->dmi_table && !dmi_check_system(table->dmi_table)) | |
662 | continue; | |
663 | return table; | |
664 | } | |
665 | return NULL; | |
666 | } | |
667 | ||
668 | int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) | |
669 | { | |
670 | const struct config_entry *cfg; | |
671 | ||
672 | if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) | |
673 | return dsp_driver; | |
674 | ||
675 | if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { | |
676 | dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", | |
677 | SND_INTEL_DSP_DRIVER_LEGACY); | |
678 | } | |
679 | ||
680 | /* find the configuration for the specific device */ | |
681 | cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, | |
682 | ARRAY_SIZE(acpi_config_table)); | |
683 | if (!cfg) | |
684 | return SND_INTEL_DSP_DRIVER_ANY; | |
685 | ||
686 | if (cfg->flags & FLAG_SST) | |
687 | return SND_INTEL_DSP_DRIVER_SST; | |
688 | ||
689 | if (cfg->flags & FLAG_SOF) | |
690 | return SND_INTEL_DSP_DRIVER_SOF; | |
691 | ||
692 | return SND_INTEL_DSP_DRIVER_SST; | |
693 | } | |
694 | EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); | |
695 | ||
82d9d54a JK |
696 | MODULE_LICENSE("GPL v2"); |
697 | MODULE_DESCRIPTION("Intel DSP config driver"); | |
08c2a4bc | 698 | MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); |