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 | }, |
5d73263f PLB |
323 | { |
324 | .flags = FLAG_SOF, | |
325 | .device = 0x34c8, | |
326 | .codec_hid = &essx_83x6, | |
327 | }, | |
82d9d54a | 328 | { |
06508575 | 329 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
cc8f81c7 | 330 | .device = 0x34c8, |
82d9d54a JK |
331 | }, |
332 | #endif | |
cc8f81c7 | 333 | |
19980aa1 | 334 | /* Jasper Lake */ |
fa9730b4 | 335 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) |
19980aa1 BL |
336 | { |
337 | .flags = FLAG_SOF, | |
338 | .device = 0x4dc8, | |
339 | .dmi_table = (const struct dmi_system_id []) { | |
340 | { | |
341 | .ident = "Google Chromebooks", | |
342 | .matches = { | |
343 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
344 | } | |
345 | }, | |
346 | {} | |
347 | } | |
348 | }, | |
fa9730b4 PLB |
349 | { |
350 | .flags = FLAG_SOF, | |
351 | .device = 0x4dc8, | |
de24d97f | 352 | .codec_hid = &essx_83x6, |
fa9730b4 | 353 | }, |
19980aa1 BL |
354 | { |
355 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
356 | .device = 0x4dc8, | |
357 | }, | |
fa9730b4 PLB |
358 | #endif |
359 | ||
82d9d54a JK |
360 | /* Tigerlake */ |
361 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) | |
cc8f81c7 PLB |
362 | { |
363 | .flags = FLAG_SOF, | |
364 | .device = 0xa0c8, | |
365 | .dmi_table = (const struct dmi_system_id []) { | |
366 | { | |
367 | .ident = "Google Chromebooks", | |
368 | .matches = { | |
369 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | |
370 | } | |
371 | }, | |
33fa35db PLB |
372 | { |
373 | .ident = "UPX-TGL", | |
374 | .matches = { | |
375 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), | |
376 | } | |
377 | }, | |
cc8f81c7 PLB |
378 | {} |
379 | } | |
380 | }, | |
82d9d54a | 381 | { |
081c7370 | 382 | .flags = FLAG_SOF, |
82d9d54a | 383 | .device = 0xa0c8, |
de24d97f | 384 | .codec_hid = &essx_83x6, |
82d9d54a | 385 | }, |
c5b5ff60 BL |
386 | { |
387 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
081c7370 | 388 | .device = 0xa0c8, |
c5b5ff60 | 389 | }, |
9d36ceab | 390 | { |
081c7370 BL |
391 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
392 | .device = 0x43c8, | |
9d36ceab | 393 | }, |
82d9d54a | 394 | #endif |
cc8f81c7 PLB |
395 | |
396 | /* Elkhart Lake */ | |
397 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) | |
82d9d54a JK |
398 | { |
399 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
cc8f81c7 | 400 | .device = 0x4b55, |
82d9d54a | 401 | }, |
114613f6 PLB |
402 | { |
403 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, | |
404 | .device = 0x4b58, | |
405 | }, | |
82d9d54a | 406 | #endif |
cc8f81c7 | 407 | |
c4294d7f KV |
408 | /* Alder Lake */ |
409 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) | |
d52eee98 | 410 | /* Alderlake-S */ |
c4294d7f KV |
411 | { |
412 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
413 | .device = 0x7ad0, | |
414 | }, | |
d52eee98 | 415 | /* RaptorLake-S */ |
c4294d7f KV |
416 | { |
417 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
d52eee98 | 418 | .device = 0x7a50, |
c4294d7f | 419 | }, |
d52eee98 | 420 | /* Alderlake-P */ |
2ec8b081 MR |
421 | { |
422 | .flags = FLAG_SOF, | |
423 | .device = 0x51c8, | |
424 | .codec_hid = &essx_83x6, | |
425 | }, | |
4ad7935d KV |
426 | { |
427 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
d52eee98 | 428 | .device = 0x51c8, |
4ad7935d | 429 | }, |
ca1ece24 KV |
430 | { |
431 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
432 | .device = 0x51cd, | |
433 | }, | |
d52eee98 | 434 | /* Alderlake-PS */ |
9db1c9fa MR |
435 | { |
436 | .flags = FLAG_SOF, | |
437 | .device = 0x51c9, | |
438 | .codec_hid = &essx_83x6, | |
439 | }, | |
d52eee98 PLB |
440 | { |
441 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
442 | .device = 0x51c9, | |
443 | }, | |
444 | /* Alderlake-M */ | |
445 | { | |
446 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
447 | .device = 0x51cc, | |
448 | }, | |
449 | /* Alderlake-N */ | |
4d5a628d KV |
450 | { |
451 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
452 | .device = 0x54c8, | |
453 | }, | |
b07908ab GS |
454 | /* RaptorLake-P */ |
455 | { | |
456 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
457 | .device = 0x51ca, | |
458 | }, | |
459 | { | |
460 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
461 | .device = 0x51cb, | |
462 | }, | |
c35fbea4 PLB |
463 | /* RaptorLake-M */ |
464 | { | |
465 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
466 | .device = 0x51ce, | |
467 | }, | |
468 | /* RaptorLake-PX */ | |
469 | { | |
470 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, | |
471 | .device = 0x51cf, | |
472 | }, | |
c4294d7f KV |
473 | #endif |
474 | ||
82d9d54a JK |
475 | }; |
476 | ||
477 | static const struct config_entry *snd_intel_dsp_find_config | |
478 | (struct pci_dev *pci, const struct config_entry *table, u32 len) | |
479 | { | |
480 | u16 device; | |
481 | ||
482 | device = pci->device; | |
483 | for (; len > 0; len--, table++) { | |
484 | if (table->device != device) | |
485 | continue; | |
486 | if (table->dmi_table && !dmi_check_system(table->dmi_table)) | |
487 | continue; | |
de24d97f PLB |
488 | if (table->codec_hid) { |
489 | int i; | |
490 | ||
491 | for (i = 0; i < table->codec_hid->num_codecs; i++) | |
492 | if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) | |
493 | break; | |
494 | if (i == table->codec_hid->num_codecs) | |
495 | continue; | |
496 | } | |
82d9d54a JK |
497 | return table; |
498 | } | |
499 | return NULL; | |
500 | } | |
501 | ||
502 | static int snd_intel_dsp_check_dmic(struct pci_dev *pci) | |
503 | { | |
504 | struct nhlt_acpi_table *nhlt; | |
505 | int ret = 0; | |
506 | ||
507 | nhlt = intel_nhlt_init(&pci->dev); | |
508 | if (nhlt) { | |
8235a08b | 509 | if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC)) |
82d9d54a JK |
510 | ret = 1; |
511 | intel_nhlt_free(nhlt); | |
512 | } | |
513 | return ret; | |
514 | } | |
515 | ||
06508575 PLB |
516 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) |
517 | static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) | |
518 | { | |
519 | struct sdw_intel_acpi_info info; | |
520 | acpi_handle handle; | |
521 | int ret; | |
522 | ||
523 | handle = ACPI_HANDLE(&pci->dev); | |
524 | ||
525 | ret = sdw_intel_acpi_scan(handle, &info); | |
526 | if (ret < 0) | |
527 | return ret; | |
528 | ||
529 | return info.link_mask; | |
530 | } | |
531 | #else | |
532 | static int snd_intel_dsp_check_soundwire(struct pci_dev *pci) | |
533 | { | |
534 | return 0; | |
535 | } | |
536 | #endif | |
537 | ||
82d9d54a JK |
538 | int snd_intel_dsp_driver_probe(struct pci_dev *pci) |
539 | { | |
540 | const struct config_entry *cfg; | |
541 | ||
82d9d54a | 542 | /* Intel vendor only */ |
91636a82 | 543 | if (pci->vendor != 0x8086) |
82d9d54a JK |
544 | return SND_INTEL_DSP_DRIVER_ANY; |
545 | ||
0e5cc221 PLB |
546 | /* |
547 | * Legacy devices don't have a PCI-based DSP and use HDaudio | |
548 | * for HDMI/DP support, ignore kernel parameter | |
549 | */ | |
550 | switch (pci->device) { | |
551 | case 0x160c: /* Broadwell */ | |
552 | case 0x0a0c: /* Haswell */ | |
553 | case 0x0c0c: | |
554 | case 0x0d0c: | |
555 | case 0x0f04: /* Baytrail */ | |
556 | case 0x2284: /* Braswell */ | |
557 | return SND_INTEL_DSP_DRIVER_ANY; | |
558 | } | |
559 | ||
91636a82 TI |
560 | if (dsp_driver > 0 && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) |
561 | return dsp_driver; | |
562 | ||
82d9d54a JK |
563 | /* |
564 | * detect DSP by checking class/subclass/prog-id information | |
565 | * class=04 subclass 03 prog-if 00: no DSP, use legacy driver | |
566 | * class=04 subclass 01 prog-if 00: DSP is present | |
567 | * (and may be required e.g. for DMIC or SSP support) | |
568 | * class=04 subclass 03 prog-if 80: use DSP or legacy mode | |
569 | */ | |
570 | if (pci->class == 0x040300) | |
571 | return SND_INTEL_DSP_DRIVER_LEGACY; | |
572 | if (pci->class != 0x040100 && pci->class != 0x040380) { | |
b79de57b | 573 | dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, selecting HDAudio legacy driver\n", pci->class); |
82d9d54a JK |
574 | return SND_INTEL_DSP_DRIVER_LEGACY; |
575 | } | |
576 | ||
577 | dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); | |
578 | ||
579 | /* find the configuration for the specific device */ | |
580 | cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); | |
581 | if (!cfg) | |
582 | return SND_INTEL_DSP_DRIVER_ANY; | |
583 | ||
584 | if (cfg->flags & FLAG_SOF) { | |
06508575 PLB |
585 | if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && |
586 | snd_intel_dsp_check_soundwire(pci) > 0) { | |
587 | dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); | |
588 | return SND_INTEL_DSP_DRIVER_SOF; | |
589 | } | |
590 | if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && | |
591 | snd_intel_dsp_check_dmic(pci)) { | |
592 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); | |
82d9d54a JK |
593 | return SND_INTEL_DSP_DRIVER_SOF; |
594 | } | |
06508575 PLB |
595 | if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) |
596 | return SND_INTEL_DSP_DRIVER_SOF; | |
82d9d54a JK |
597 | } |
598 | ||
df1fceac CR |
599 | |
600 | if (cfg->flags & FLAG_SST) { | |
601 | if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { | |
602 | if (snd_intel_dsp_check_dmic(pci)) { | |
603 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); | |
604 | return SND_INTEL_DSP_DRIVER_SST; | |
605 | } | |
606 | } else { | |
607 | return SND_INTEL_DSP_DRIVER_SST; | |
608 | } | |
609 | } | |
82d9d54a JK |
610 | |
611 | return SND_INTEL_DSP_DRIVER_LEGACY; | |
612 | } | |
613 | EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); | |
614 | ||
5427c7d6 HG |
615 | /* Should we default to SOF or SST for BYT/CHT ? */ |
616 | #if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ | |
617 | !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) | |
618 | #define FLAG_SST_OR_SOF_BYT FLAG_SOF | |
619 | #else | |
620 | #define FLAG_SST_OR_SOF_BYT FLAG_SST | |
621 | #endif | |
622 | ||
b5682305 PLB |
623 | /* |
624 | * configuration table | |
625 | * - the order of similar ACPI ID entries is important! | |
626 | * - the first successful match will win | |
627 | */ | |
628 | static const struct config_entry acpi_config_table[] = { | |
5427c7d6 HG |
629 | #if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ |
630 | IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) | |
b5682305 | 631 | /* BayTrail */ |
b5682305 | 632 | { |
5427c7d6 | 633 | .flags = FLAG_SST_OR_SOF_BYT, |
b5682305 PLB |
634 | .acpi_hid = "80860F28", |
635 | }, | |
b5682305 | 636 | /* CherryTrail */ |
b5682305 | 637 | { |
5427c7d6 | 638 | .flags = FLAG_SST_OR_SOF_BYT, |
b5682305 PLB |
639 | .acpi_hid = "808622A8", |
640 | }, | |
641 | #endif | |
803e5913 PLB |
642 | /* Broadwell */ |
643 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) | |
644 | { | |
645 | .flags = FLAG_SST, | |
646 | .acpi_hid = "INT3438" | |
647 | }, | |
648 | #endif | |
649 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) | |
650 | { | |
651 | .flags = FLAG_SOF, | |
652 | .acpi_hid = "INT3438" | |
653 | }, | |
654 | #endif | |
655 | /* Haswell - not supported by SOF but added for consistency */ | |
656 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CATPT) | |
657 | { | |
658 | .flags = FLAG_SST, | |
659 | .acpi_hid = "INT33C8" | |
660 | }, | |
661 | #endif | |
b5682305 PLB |
662 | }; |
663 | ||
664 | static const struct config_entry *snd_intel_acpi_dsp_find_config(const u8 acpi_hid[ACPI_ID_LEN], | |
665 | const struct config_entry *table, | |
666 | u32 len) | |
667 | { | |
668 | for (; len > 0; len--, table++) { | |
669 | if (memcmp(table->acpi_hid, acpi_hid, ACPI_ID_LEN)) | |
670 | continue; | |
671 | if (table->dmi_table && !dmi_check_system(table->dmi_table)) | |
672 | continue; | |
673 | return table; | |
674 | } | |
675 | return NULL; | |
676 | } | |
677 | ||
678 | int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) | |
679 | { | |
680 | const struct config_entry *cfg; | |
681 | ||
682 | if (dsp_driver > SND_INTEL_DSP_DRIVER_LEGACY && dsp_driver <= SND_INTEL_DSP_DRIVER_LAST) | |
683 | return dsp_driver; | |
684 | ||
685 | if (dsp_driver == SND_INTEL_DSP_DRIVER_LEGACY) { | |
686 | dev_warn(dev, "dsp_driver parameter %d not supported, using automatic detection\n", | |
687 | SND_INTEL_DSP_DRIVER_LEGACY); | |
688 | } | |
689 | ||
690 | /* find the configuration for the specific device */ | |
691 | cfg = snd_intel_acpi_dsp_find_config(acpi_hid, acpi_config_table, | |
692 | ARRAY_SIZE(acpi_config_table)); | |
693 | if (!cfg) | |
694 | return SND_INTEL_DSP_DRIVER_ANY; | |
695 | ||
696 | if (cfg->flags & FLAG_SST) | |
697 | return SND_INTEL_DSP_DRIVER_SST; | |
698 | ||
699 | if (cfg->flags & FLAG_SOF) | |
700 | return SND_INTEL_DSP_DRIVER_SOF; | |
701 | ||
702 | return SND_INTEL_DSP_DRIVER_SST; | |
703 | } | |
704 | EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe); | |
705 | ||
82d9d54a JK |
706 | MODULE_LICENSE("GPL v2"); |
707 | MODULE_DESCRIPTION("Intel DSP config driver"); | |
08c2a4bc | 708 | MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); |