1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2020 Intel Corporation
5 * sof_sdw - ASOC Machine driver for Intel SoundWire platforms
8 #include <linux/acpi.h>
9 #include <linux/bitmap.h>
10 #include <linux/device.h>
11 #include <linux/dmi.h>
12 #include <linux/module.h>
13 #include <linux/soundwire/sdw.h>
14 #include <linux/soundwire/sdw_type.h>
15 #include <linux/soundwire/sdw_intel.h>
16 #include <sound/soc-acpi.h>
17 #include "sof_sdw_common.h"
18 #include "../../codecs/rt711.h"
20 static unsigned long sof_sdw_quirk
= RT711_JD1
;
21 static int quirk_override
= -1;
22 module_param_named(quirk
, quirk_override
, int, 0444);
23 MODULE_PARM_DESC(quirk
, "Board-specific quirk override");
25 static void log_quirks(struct device
*dev
)
27 if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk
))
28 dev_dbg(dev
, "quirk realtek,jack-detect-source %ld\n",
29 SOC_SDW_JACK_JDSRC(sof_sdw_quirk
));
30 if (sof_sdw_quirk
& SOC_SDW_FOUR_SPK
)
31 dev_err(dev
, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\n");
32 if (sof_sdw_quirk
& SOF_SDW_TGL_HDMI
)
33 dev_dbg(dev
, "quirk SOF_SDW_TGL_HDMI enabled\n");
34 if (sof_sdw_quirk
& SOC_SDW_PCH_DMIC
)
35 dev_dbg(dev
, "quirk SOC_SDW_PCH_DMIC enabled\n");
36 if (SOF_SSP_GET_PORT(sof_sdw_quirk
))
37 dev_dbg(dev
, "SSP port %ld\n",
38 SOF_SSP_GET_PORT(sof_sdw_quirk
));
39 if (sof_sdw_quirk
& SOC_SDW_NO_AGGREGATION
)
40 dev_err(dev
, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n");
41 if (sof_sdw_quirk
& SOC_SDW_CODEC_SPKR
)
42 dev_dbg(dev
, "quirk SOC_SDW_CODEC_SPKR enabled\n");
43 if (sof_sdw_quirk
& SOC_SDW_SIDECAR_AMPS
)
44 dev_dbg(dev
, "quirk SOC_SDW_SIDECAR_AMPS enabled\n");
47 static int sof_sdw_quirk_cb(const struct dmi_system_id
*id
)
49 sof_sdw_quirk
= (unsigned long)id
->driver_data
;
53 static const struct dmi_system_id sof_sdw_quirk_table
[] = {
54 /* CometLake devices */
56 .callback
= sof_sdw_quirk_cb
,
58 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
59 DMI_MATCH(DMI_PRODUCT_NAME
, "CometLake Client"),
61 .driver_data
= (void *)SOC_SDW_PCH_DMIC
,
64 .callback
= sof_sdw_quirk_cb
,
66 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
67 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "09C6")
69 .driver_data
= (void *)RT711_JD2
,
72 /* early version of SKU 09C6 */
73 .callback
= sof_sdw_quirk_cb
,
75 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
76 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0983")
78 .driver_data
= (void *)RT711_JD2
,
81 .callback
= sof_sdw_quirk_cb
,
83 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
84 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "098F"),
86 .driver_data
= (void *)(RT711_JD2
),
89 .callback
= sof_sdw_quirk_cb
,
91 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
92 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0990"),
94 .driver_data
= (void *)(RT711_JD2
),
98 .callback
= sof_sdw_quirk_cb
,
100 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
101 DMI_MATCH(DMI_PRODUCT_NAME
, "Ice Lake Client"),
103 .driver_data
= (void *)SOC_SDW_PCH_DMIC
,
105 /* TigerLake devices */
107 .callback
= sof_sdw_quirk_cb
,
109 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
110 DMI_MATCH(DMI_PRODUCT_NAME
,
111 "Tiger Lake Client Platform"),
113 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
116 SOF_SSP_PORT(SOF_I2S_SSP2
)),
119 .callback
= sof_sdw_quirk_cb
,
121 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
122 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A3E")
124 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
128 /* another SKU of Dell Latitude 9520 */
129 .callback
= sof_sdw_quirk_cb
,
131 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
132 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A3F")
134 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
139 .callback
= sof_sdw_quirk_cb
,
141 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
142 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A5D")
144 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
148 .callback
= sof_sdw_quirk_cb
,
150 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
151 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A5E")
153 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
157 .callback
= sof_sdw_quirk_cb
,
159 DMI_MATCH(DMI_SYS_VENDOR
, "Google"),
160 DMI_MATCH(DMI_PRODUCT_NAME
, "Volteer"),
162 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
164 SOF_BT_OFFLOAD_SSP(2) |
165 SOF_SSP_BT_OFFLOAD_PRESENT
),
168 .callback
= sof_sdw_quirk_cb
,
170 DMI_MATCH(DMI_SYS_VENDOR
, "Google"),
171 DMI_MATCH(DMI_PRODUCT_NAME
, "Ripto"),
173 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
178 * this entry covers multiple HP SKUs. The family name
179 * does not seem robust enough, so we use a partial
180 * match that ignores the product name suffix
181 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
183 .callback
= sof_sdw_quirk_cb
,
185 DMI_MATCH(DMI_SYS_VENDOR
, "HP"),
186 DMI_MATCH(DMI_PRODUCT_NAME
, "HP Spectre x360 Conv"),
188 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
194 * this entry covers HP Spectre x360 where the DMI information
197 .callback
= sof_sdw_quirk_cb
,
199 DMI_MATCH(DMI_SYS_VENDOR
, "HP"),
200 DMI_MATCH(DMI_BOARD_NAME
, "8709"),
202 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
207 /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
208 .callback
= sof_sdw_quirk_cb
,
210 DMI_MATCH(DMI_SYS_VENDOR
, "Intel(R) Client Systems"),
211 DMI_MATCH(DMI_PRODUCT_NAME
, "LAPBC"),
213 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
218 /* NUC15 LAPBC710 skews */
219 .callback
= sof_sdw_quirk_cb
,
221 DMI_MATCH(DMI_BOARD_VENDOR
, "Intel Corporation"),
222 DMI_MATCH(DMI_BOARD_NAME
, "LAPBC710"),
224 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
229 /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
230 .callback
= sof_sdw_quirk_cb
,
232 DMI_MATCH(DMI_SYS_VENDOR
, "Intel(R) Client Systems"),
233 DMI_MATCH(DMI_PRODUCT_NAME
, "LAPRC"),
235 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
240 /* NUC15 LAPRC710 skews */
241 .callback
= sof_sdw_quirk_cb
,
243 DMI_MATCH(DMI_BOARD_VENDOR
, "Intel Corporation"),
244 DMI_MATCH(DMI_BOARD_NAME
, "LAPRC710"),
246 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
250 /* TigerLake-SDCA devices */
252 .callback
= sof_sdw_quirk_cb
,
254 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
255 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A32")
257 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
261 .callback
= sof_sdw_quirk_cb
,
263 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
264 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0A45")
266 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
269 /* AlderLake devices */
271 .callback
= sof_sdw_quirk_cb
,
273 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
274 DMI_MATCH(DMI_PRODUCT_NAME
, "Alder Lake Client Platform"),
276 .driver_data
= (void *)(RT711_JD2_100K
|
278 SOF_BT_OFFLOAD_SSP(2) |
279 SOF_SSP_BT_OFFLOAD_PRESENT
),
282 .callback
= sof_sdw_quirk_cb
,
284 DMI_MATCH(DMI_BOARD_VENDOR
, "Intel Corporation"),
285 DMI_MATCH(DMI_PRODUCT_SKU
, "0000000000070000"),
287 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
291 .callback
= sof_sdw_quirk_cb
,
293 DMI_MATCH(DMI_SYS_VENDOR
, "Google"),
294 DMI_MATCH(DMI_PRODUCT_NAME
, "Brya"),
296 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
298 SOF_BT_OFFLOAD_SSP(2) |
299 SOF_SSP_BT_OFFLOAD_PRESENT
),
302 .callback
= sof_sdw_quirk_cb
,
304 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
305 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0AF0")
307 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
311 .callback
= sof_sdw_quirk_cb
,
313 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
314 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0AF3"),
317 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
),
320 .callback
= sof_sdw_quirk_cb
,
322 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
323 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0AFE")
325 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
329 .callback
= sof_sdw_quirk_cb
,
331 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
332 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0AFF")
334 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
338 .callback
= sof_sdw_quirk_cb
,
340 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
341 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B00")
343 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
347 .callback
= sof_sdw_quirk_cb
,
349 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
350 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B01")
352 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
356 .callback
= sof_sdw_quirk_cb
,
358 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
359 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B11")
361 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
365 .callback
= sof_sdw_quirk_cb
,
367 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
368 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B12")
370 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
374 .callback
= sof_sdw_quirk_cb
,
376 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
377 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B13"),
380 .driver_data
= (void *)SOF_SDW_TGL_HDMI
,
383 .callback
= sof_sdw_quirk_cb
,
385 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
386 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B14"),
389 .driver_data
= (void *)SOF_SDW_TGL_HDMI
,
393 .callback
= sof_sdw_quirk_cb
,
395 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
396 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B29"),
398 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
402 .callback
= sof_sdw_quirk_cb
,
404 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
405 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B34"),
408 .driver_data
= (void *)SOF_SDW_TGL_HDMI
,
411 .callback
= sof_sdw_quirk_cb
,
413 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
414 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0B8C"),
416 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
420 .callback
= sof_sdw_quirk_cb
,
422 DMI_MATCH(DMI_SYS_VENDOR
, "HP"),
423 DMI_MATCH(DMI_PRODUCT_NAME
, "OMEN by HP Gaming Laptop 16"),
425 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
428 /* RaptorLake devices */
430 .callback
= sof_sdw_quirk_cb
,
432 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
433 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0BDA")
435 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
439 .callback
= sof_sdw_quirk_cb
,
441 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
442 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0C0F")
444 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
448 .callback
= sof_sdw_quirk_cb
,
450 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
451 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0C10"),
454 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
),
457 .callback
= sof_sdw_quirk_cb
,
459 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
460 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0C11")
462 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
466 .callback
= sof_sdw_quirk_cb
,
468 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
469 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0C40")
471 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
475 .callback
= sof_sdw_quirk_cb
,
477 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
478 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0C4F")
480 .driver_data
= (void *)(SOF_SDW_TGL_HDMI
|
484 .callback
= sof_sdw_quirk_cb
,
486 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
487 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF6")
489 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
492 .callback
= sof_sdw_quirk_cb
,
494 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
495 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF9")
497 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
500 .callback
= sof_sdw_quirk_cb
,
502 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
503 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CFA")
505 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
507 /* MeteorLake devices */
509 .callback
= sof_sdw_quirk_cb
,
511 DMI_MATCH(DMI_PRODUCT_FAMILY
, "Intel_mtlrvp"),
513 .driver_data
= (void *)(RT711_JD1
),
516 .callback
= sof_sdw_quirk_cb
,
518 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
519 DMI_MATCH(DMI_PRODUCT_NAME
, "Meteor Lake Client Platform"),
521 .driver_data
= (void *)(RT711_JD2_100K
),
524 .callback
= sof_sdw_quirk_cb
,
526 DMI_MATCH(DMI_SYS_VENDOR
, "Google"),
527 DMI_MATCH(DMI_PRODUCT_NAME
, "Rex"),
529 .driver_data
= (void *)(SOC_SDW_PCH_DMIC
|
530 SOF_BT_OFFLOAD_SSP(1) |
531 SOF_SSP_BT_OFFLOAD_PRESENT
),
534 .callback
= sof_sdw_quirk_cb
,
536 DMI_MATCH(DMI_SYS_VENDOR
, "HP"),
537 DMI_MATCH(DMI_PRODUCT_NAME
, "OMEN Transcend Gaming Laptop"),
539 .driver_data
= (void *)(RT711_JD2
),
542 /* LunarLake devices */
544 .callback
= sof_sdw_quirk_cb
,
546 DMI_MATCH(DMI_SYS_VENDOR
, "Intel Corporation"),
547 DMI_MATCH(DMI_PRODUCT_NAME
, "Lunar Lake Client Platform"),
549 .driver_data
= (void *)(RT711_JD2
),
552 .callback
= sof_sdw_quirk_cb
,
554 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
555 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CE3")
557 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
560 .callback
= sof_sdw_quirk_cb
,
562 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
563 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CE4")
565 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
568 .callback
= sof_sdw_quirk_cb
,
570 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
571 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CDB")
573 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
576 .callback
= sof_sdw_quirk_cb
,
578 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
579 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CDC")
581 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
584 .callback
= sof_sdw_quirk_cb
,
586 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
587 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CDD")
589 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
592 .callback
= sof_sdw_quirk_cb
,
594 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
595 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0D36")
597 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
600 .callback
= sof_sdw_quirk_cb
,
602 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
603 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF8")
605 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
608 .callback
= sof_sdw_quirk_cb
,
610 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
611 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "3838")
613 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
616 .callback
= sof_sdw_quirk_cb
,
618 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
619 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "3832")
621 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
624 .callback
= sof_sdw_quirk_cb
,
626 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
627 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "380E")
629 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
632 .callback
= sof_sdw_quirk_cb
,
634 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
635 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "233C")
637 /* Note this quirk excludes the CODEC mic */
638 .driver_data
= (void *)(SOC_SDW_CODEC_MIC
),
641 .callback
= sof_sdw_quirk_cb
,
643 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
644 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "233B")
646 .driver_data
= (void *)(SOC_SDW_SIDECAR_AMPS
),
649 /* ArrowLake devices */
651 .callback
= sof_sdw_quirk_cb
,
653 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
654 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CE8")
656 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
659 .callback
= sof_sdw_quirk_cb
,
661 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
662 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF1")
664 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
667 .callback
= sof_sdw_quirk_cb
,
669 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
670 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF7")
672 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
675 .callback
= sof_sdw_quirk_cb
,
677 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
678 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF0")
680 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
683 .callback
= sof_sdw_quirk_cb
,
685 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
686 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF3")
688 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
691 .callback
= sof_sdw_quirk_cb
,
693 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
694 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF4")
696 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
699 .callback
= sof_sdw_quirk_cb
,
701 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc"),
702 DMI_EXACT_MATCH(DMI_PRODUCT_SKU
, "0CF5")
704 .driver_data
= (void *)(SOC_SDW_CODEC_SPKR
),
706 /* Pantherlake devices*/
708 .callback
= sof_sdw_quirk_cb
,
710 DMI_MATCH(DMI_PRODUCT_FAMILY
, "Intel_ptlrvp"),
712 .driver_data
= (void *)(SOC_SDW_PCH_DMIC
),
717 static struct snd_soc_dai_link_component platform_component
[] = {
719 /* name might be overridden during probe */
720 .name
= "0000:00:1f.3"
724 static const struct snd_soc_ops sdw_ops
= {
725 .startup
= asoc_sdw_startup
,
726 .prepare
= asoc_sdw_prepare
,
727 .trigger
= asoc_sdw_trigger
,
728 .hw_params
= asoc_sdw_hw_params
,
729 .hw_free
= asoc_sdw_hw_free
,
730 .shutdown
= asoc_sdw_shutdown
,
733 static const char * const type_strings
[] = {"SimpleJack", "SmartAmp", "SmartMic"};
735 static int create_sdw_dailink(struct snd_soc_card
*card
,
736 struct asoc_sdw_dailink
*sof_dai
,
737 struct snd_soc_dai_link
**dai_links
,
738 int *be_id
, struct snd_soc_codec_conf
**codec_conf
)
740 struct device
*dev
= card
->dev
;
741 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
742 struct intel_mc_ctx
*intel_ctx
= (struct intel_mc_ctx
*)ctx
->private;
743 struct asoc_sdw_endpoint
*sof_end
;
747 list_for_each_entry(sof_end
, &sof_dai
->endpoints
, list
) {
748 if (sof_end
->name_prefix
) {
749 (*codec_conf
)->dlc
.name
= sof_end
->codec_name
;
750 (*codec_conf
)->name_prefix
= sof_end
->name_prefix
;
754 if (sof_end
->include_sidecar
) {
755 ret
= sof_end
->codec_info
->add_sidecar(card
, dai_links
, codec_conf
);
761 for_each_pcm_streams(stream
) {
762 static const char * const sdw_stream_name
[] = {
768 struct snd_soc_dai_link_ch_map
*codec_maps
;
769 struct snd_soc_dai_link_component
*codecs
;
770 struct snd_soc_dai_link_component
*cpus
;
771 int num_cpus
= hweight32(sof_dai
->link_mask
[stream
]);
772 int num_codecs
= sof_dai
->num_devs
[stream
];
773 int playback
, capture
;
778 if (!sof_dai
->num_devs
[stream
])
781 sof_end
= list_first_entry(&sof_dai
->endpoints
,
782 struct asoc_sdw_endpoint
, list
);
784 *be_id
= sof_end
->dai_info
->dailink
[stream
];
786 dev_err(dev
, "Invalid dailink id %d\n", *be_id
);
790 /* create stream name according to first link id */
791 if (ctx
->append_dai_type
)
792 name
= devm_kasprintf(dev
, GFP_KERNEL
,
793 sdw_stream_name
[stream
+ 2],
794 ffs(sof_end
->link_mask
) - 1,
795 type_strings
[sof_end
->dai_info
->dai_type
]);
797 name
= devm_kasprintf(dev
, GFP_KERNEL
,
798 sdw_stream_name
[stream
],
799 ffs(sof_end
->link_mask
) - 1);
803 cpus
= devm_kcalloc(dev
, num_cpus
, sizeof(*cpus
), GFP_KERNEL
);
807 codecs
= devm_kcalloc(dev
, num_codecs
, sizeof(*codecs
), GFP_KERNEL
);
811 codec_maps
= devm_kcalloc(dev
, num_codecs
, sizeof(*codec_maps
), GFP_KERNEL
);
815 list_for_each_entry(sof_end
, &sof_dai
->endpoints
, list
) {
816 if (!sof_end
->dai_info
->direction
[stream
])
819 if (cur_link
!= sof_end
->link_mask
) {
820 int link_num
= ffs(sof_end
->link_mask
) - 1;
821 int pin_num
= intel_ctx
->sdw_pin_index
[link_num
]++;
823 cur_link
= sof_end
->link_mask
;
825 cpus
[i
].dai_name
= devm_kasprintf(dev
, GFP_KERNEL
,
828 if (!cpus
[i
].dai_name
)
833 codec_maps
[j
].cpu
= i
- 1;
834 codec_maps
[j
].codec
= j
;
836 codecs
[j
].name
= sof_end
->codec_name
;
837 codecs
[j
].dai_name
= sof_end
->dai_info
->dai_name
;
841 WARN_ON(i
!= num_cpus
|| j
!= num_codecs
);
843 playback
= (stream
== SNDRV_PCM_STREAM_PLAYBACK
);
844 capture
= (stream
== SNDRV_PCM_STREAM_CAPTURE
);
846 asoc_sdw_init_dai_link(dev
, *dai_links
, be_id
, name
, playback
, capture
,
847 cpus
, num_cpus
, platform_component
,
848 ARRAY_SIZE(platform_component
), codecs
, num_codecs
,
849 1, asoc_sdw_rtd_init
, &sdw_ops
);
852 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
853 * based on wait_for_completion(), tag them as 'nonatomic'.
855 (*dai_links
)->nonatomic
= true;
856 (*dai_links
)->ch_maps
= codec_maps
;
858 list_for_each_entry(sof_end
, &sof_dai
->endpoints
, list
) {
859 if (sof_end
->dai_info
->init
)
860 sof_end
->dai_info
->init(card
, *dai_links
,
871 static int create_sdw_dailinks(struct snd_soc_card
*card
,
872 struct snd_soc_dai_link
**dai_links
, int *be_id
,
873 struct asoc_sdw_dailink
*sof_dais
,
874 struct snd_soc_codec_conf
**codec_conf
)
876 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
877 struct intel_mc_ctx
*intel_ctx
= (struct intel_mc_ctx
*)ctx
->private;
880 for (i
= 0; i
< SDW_INTEL_MAX_LINKS
; i
++)
881 intel_ctx
->sdw_pin_index
[i
] = SOC_SDW_INTEL_BIDIR_PDI_BASE
;
883 /* generate DAI links by each sdw link */
884 while (sof_dais
->initialised
) {
887 ret
= create_sdw_dailink(card
, sof_dais
, dai_links
,
888 ¤t_be_id
, codec_conf
);
892 /* Update the be_id to match the highest ID used for SDW link */
893 if (*be_id
< current_be_id
)
894 *be_id
= current_be_id
;
902 static int create_ssp_dailinks(struct snd_soc_card
*card
,
903 struct snd_soc_dai_link
**dai_links
, int *be_id
,
904 struct asoc_sdw_codec_info
*ssp_info
,
905 unsigned long ssp_mask
)
907 struct device
*dev
= card
->dev
;
911 for_each_set_bit(i
, &ssp_mask
, BITS_PER_TYPE(ssp_mask
)) {
912 char *name
= devm_kasprintf(dev
, GFP_KERNEL
, "SSP%d-Codec", i
);
913 char *cpu_dai_name
= devm_kasprintf(dev
, GFP_KERNEL
, "SSP%d Pin", i
);
914 char *codec_name
= devm_kasprintf(dev
, GFP_KERNEL
, "i2c-%s:0%d",
915 ssp_info
->acpi_id
, j
++);
916 if (!name
|| !cpu_dai_name
|| !codec_name
)
919 int playback
= ssp_info
->dais
[0].direction
[SNDRV_PCM_STREAM_PLAYBACK
];
920 int capture
= ssp_info
->dais
[0].direction
[SNDRV_PCM_STREAM_CAPTURE
];
922 ret
= asoc_sdw_init_simple_dai_link(dev
, *dai_links
, be_id
, name
,
923 playback
, capture
, cpu_dai_name
,
924 platform_component
->name
,
925 ARRAY_SIZE(platform_component
), codec_name
,
926 ssp_info
->dais
[0].dai_name
, 1, NULL
,
931 ret
= ssp_info
->dais
[0].init(card
, *dai_links
, ssp_info
, 0);
941 static int create_dmic_dailinks(struct snd_soc_card
*card
,
942 struct snd_soc_dai_link
**dai_links
, int *be_id
)
944 struct device
*dev
= card
->dev
;
947 ret
= asoc_sdw_init_simple_dai_link(dev
, *dai_links
, be_id
, "dmic01",
948 0, 1, // DMIC only supports capture
949 "DMIC01 Pin", platform_component
->name
,
950 ARRAY_SIZE(platform_component
),
951 "dmic-codec", "dmic-hifi", 1,
952 asoc_sdw_dmic_init
, NULL
);
958 ret
= asoc_sdw_init_simple_dai_link(dev
, *dai_links
, be_id
, "dmic16k",
959 0, 1, // DMIC only supports capture
960 "DMIC16k Pin", platform_component
->name
,
961 ARRAY_SIZE(platform_component
),
962 "dmic-codec", "dmic-hifi", 1,
963 /* don't call asoc_sdw_dmic_init() twice */
973 static int create_hdmi_dailinks(struct snd_soc_card
*card
,
974 struct snd_soc_dai_link
**dai_links
, int *be_id
,
977 struct device
*dev
= card
->dev
;
978 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
979 struct intel_mc_ctx
*intel_ctx
= (struct intel_mc_ctx
*)ctx
->private;
982 for (i
= 0; i
< hdmi_num
; i
++) {
983 char *name
= devm_kasprintf(dev
, GFP_KERNEL
, "iDisp%d", i
+ 1);
984 char *cpu_dai_name
= devm_kasprintf(dev
, GFP_KERNEL
, "iDisp%d Pin", i
+ 1);
985 if (!name
|| !cpu_dai_name
)
988 char *codec_name
, *codec_dai_name
;
990 if (intel_ctx
->hdmi
.idisp_codec
) {
991 codec_name
= "ehdaudio0D2";
992 codec_dai_name
= devm_kasprintf(dev
, GFP_KERNEL
,
993 "intel-hdmi-hifi%d", i
+ 1);
995 codec_name
= "snd-soc-dummy";
996 codec_dai_name
= "snd-soc-dummy-dai";
1002 ret
= asoc_sdw_init_simple_dai_link(dev
, *dai_links
, be_id
, name
,
1003 1, 0, // HDMI only supports playback
1004 cpu_dai_name
, platform_component
->name
,
1005 ARRAY_SIZE(platform_component
),
1006 codec_name
, codec_dai_name
, 1,
1007 i
== 0 ? sof_sdw_hdmi_init
: NULL
, NULL
);
1017 static int create_bt_dailinks(struct snd_soc_card
*card
,
1018 struct snd_soc_dai_link
**dai_links
, int *be_id
)
1020 struct device
*dev
= card
->dev
;
1021 int port
= (sof_sdw_quirk
& SOF_BT_OFFLOAD_SSP_MASK
) >>
1022 SOF_BT_OFFLOAD_SSP_SHIFT
;
1023 char *name
= devm_kasprintf(dev
, GFP_KERNEL
, "SSP%d-BT", port
);
1024 char *cpu_dai_name
= devm_kasprintf(dev
, GFP_KERNEL
, "SSP%d Pin", port
);
1025 if (!name
|| !cpu_dai_name
)
1030 ret
= asoc_sdw_init_simple_dai_link(dev
, *dai_links
, be_id
, name
,
1031 1, 1, cpu_dai_name
, platform_component
->name
,
1032 ARRAY_SIZE(platform_component
),
1033 snd_soc_dummy_dlc
.name
, snd_soc_dummy_dlc
.dai_name
,
1043 static int sof_card_dai_links_create(struct snd_soc_card
*card
)
1045 struct device
*dev
= card
->dev
;
1046 struct snd_soc_acpi_mach
*mach
= dev_get_platdata(card
->dev
);
1047 int sdw_be_num
= 0, ssp_num
= 0, dmic_num
= 0, bt_num
= 0;
1048 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
1049 struct intel_mc_ctx
*intel_ctx
= (struct intel_mc_ctx
*)ctx
->private;
1050 struct snd_soc_acpi_mach_params
*mach_params
= &mach
->mach_params
;
1051 struct snd_soc_codec_conf
*codec_conf
;
1052 struct asoc_sdw_codec_info
*ssp_info
;
1053 struct asoc_sdw_endpoint
*sof_ends
;
1054 struct asoc_sdw_dailink
*sof_dais
;
1057 struct snd_soc_dai_link
*dai_links
;
1061 unsigned long ssp_mask
;
1064 ret
= asoc_sdw_count_sdw_endpoints(card
, &num_devs
, &num_ends
);
1066 dev_err(dev
, "failed to count devices/endpoints: %d\n", ret
);
1070 /* One per DAI link, worst case is a DAI link for every endpoint */
1071 sof_dais
= kcalloc(num_ends
, sizeof(*sof_dais
), GFP_KERNEL
);
1075 /* One per endpoint, ie. each DAI on each codec/amp */
1076 sof_ends
= kcalloc(num_ends
, sizeof(*sof_ends
), GFP_KERNEL
);
1082 ret
= asoc_sdw_parse_sdw_endpoints(card
, sof_dais
, sof_ends
, &num_devs
);
1089 * on generic tgl platform, I2S or sdw mode is supported
1090 * based on board rework. A ACPI device is registered in
1091 * system only when I2S mode is supported, not sdw mode.
1092 * Here check ACPI ID to confirm I2S is supported.
1094 ssp_info
= asoc_sdw_find_codec_info_acpi(mach
->id
);
1096 ssp_mask
= SOF_SSP_GET_PORT(sof_sdw_quirk
);
1097 ssp_num
= hweight_long(ssp_mask
);
1100 if (mach_params
->codec_mask
& IDISP_CODEC_MASK
)
1101 intel_ctx
->hdmi
.idisp_codec
= true;
1103 if (sof_sdw_quirk
& SOF_SDW_TGL_HDMI
)
1104 hdmi_num
= SOF_TGL_HDMI_COUNT
;
1106 hdmi_num
= SOF_PRE_TGL_HDMI_COUNT
;
1108 /* enable dmic01 & dmic16k */
1109 if (sof_sdw_quirk
& SOC_SDW_PCH_DMIC
|| mach_params
->dmic_num
) {
1110 if (ctx
->ignore_internal_dmic
)
1111 dev_warn(dev
, "Ignoring PCH DMIC\n");
1116 * mach_params->dmic_num will be used to set the cfg-mics value of card->components
1117 * string. Overwrite it to the actual number of PCH DMICs used in the device.
1119 mach_params
->dmic_num
= dmic_num
;
1121 if (sof_sdw_quirk
& SOF_SSP_BT_OFFLOAD_PRESENT
)
1124 dev_dbg(dev
, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
1125 sdw_be_num
, ssp_num
, dmic_num
,
1126 intel_ctx
->hdmi
.idisp_codec
? hdmi_num
: 0, bt_num
);
1128 codec_conf
= devm_kcalloc(dev
, num_devs
, sizeof(*codec_conf
), GFP_KERNEL
);
1134 /* allocate BE dailinks */
1135 num_links
= sdw_be_num
+ ssp_num
+ dmic_num
+ hdmi_num
+ bt_num
;
1136 dai_links
= devm_kcalloc(dev
, num_links
, sizeof(*dai_links
), GFP_KERNEL
);
1142 card
->codec_conf
= codec_conf
;
1143 card
->num_configs
= num_devs
;
1144 card
->dai_link
= dai_links
;
1145 card
->num_links
= num_links
;
1149 ret
= create_sdw_dailinks(card
, &dai_links
, &be_id
,
1150 sof_dais
, &codec_conf
);
1157 ret
= create_ssp_dailinks(card
, &dai_links
, &be_id
,
1158 ssp_info
, ssp_mask
);
1165 ret
= create_dmic_dailinks(card
, &dai_links
, &be_id
);
1171 ret
= create_hdmi_dailinks(card
, &dai_links
, &be_id
, hdmi_num
);
1176 if (sof_sdw_quirk
& SOF_SSP_BT_OFFLOAD_PRESENT
) {
1177 ret
= create_bt_dailinks(card
, &dai_links
, &be_id
);
1182 WARN_ON(codec_conf
!= card
->codec_conf
+ card
->num_configs
);
1183 WARN_ON(dai_links
!= card
->dai_link
+ card
->num_links
);
1193 static int sof_sdw_card_late_probe(struct snd_soc_card
*card
)
1195 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
1196 struct intel_mc_ctx
*intel_ctx
= (struct intel_mc_ctx
*)ctx
->private;
1199 ret
= asoc_sdw_card_late_probe(card
);
1203 if (intel_ctx
->hdmi
.idisp_codec
)
1204 ret
= sof_sdw_hdmi_card_late_probe(card
);
1209 static int mc_probe(struct platform_device
*pdev
)
1211 struct snd_soc_acpi_mach
*mach
= dev_get_platdata(&pdev
->dev
);
1212 struct snd_soc_card
*card
;
1213 struct asoc_sdw_mc_private
*ctx
;
1214 struct intel_mc_ctx
*intel_ctx
;
1218 dev_dbg(&pdev
->dev
, "Entry\n");
1220 intel_ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*intel_ctx
), GFP_KERNEL
);
1224 ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*ctx
), GFP_KERNEL
);
1228 ctx
->private = intel_ctx
;
1229 ctx
->codec_info_list_count
= asoc_sdw_get_codec_info_list_count();
1231 card
->dev
= &pdev
->dev
;
1232 card
->name
= "soundwire";
1233 card
->owner
= THIS_MODULE
;
1234 card
->late_probe
= sof_sdw_card_late_probe
;
1236 snd_soc_card_set_drvdata(card
, ctx
);
1238 dmi_check_system(sof_sdw_quirk_table
);
1240 if (quirk_override
!= -1) {
1241 dev_info(card
->dev
, "Overriding quirk 0x%lx => 0x%x\n",
1242 sof_sdw_quirk
, quirk_override
);
1243 sof_sdw_quirk
= quirk_override
;
1246 log_quirks(card
->dev
);
1248 ctx
->mc_quirk
= sof_sdw_quirk
;
1249 /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
1250 for (i
= 0; i
< ctx
->codec_info_list_count
; i
++)
1251 codec_info_list
[i
].amp_num
= 0;
1253 if (mach
->mach_params
.subsystem_id_set
) {
1254 snd_soc_card_set_pci_ssid(card
,
1255 mach
->mach_params
.subsystem_vendor
,
1256 mach
->mach_params
.subsystem_device
);
1259 ret
= sof_card_dai_links_create(card
);
1264 * the default amp_num is zero for each codec and
1265 * amp_num will only be increased for active amp
1266 * codecs on used platform
1268 for (i
= 0; i
< ctx
->codec_info_list_count
; i
++)
1269 amp_num
+= codec_info_list
[i
].amp_num
;
1271 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
1272 " cfg-amp:%d", amp_num
);
1273 if (!card
->components
)
1276 if (mach
->mach_params
.dmic_num
) {
1277 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
1278 "%s mic:dmic cfg-mics:%d",
1280 mach
->mach_params
.dmic_num
);
1281 if (!card
->components
)
1285 /* Register the card */
1286 ret
= devm_snd_soc_register_card(card
->dev
, card
);
1288 dev_err_probe(card
->dev
, ret
, "snd_soc_register_card failed %d\n", ret
);
1289 asoc_sdw_mc_dailink_exit_loop(card
);
1293 platform_set_drvdata(pdev
, card
);
1298 static void mc_remove(struct platform_device
*pdev
)
1300 struct snd_soc_card
*card
= platform_get_drvdata(pdev
);
1302 asoc_sdw_mc_dailink_exit_loop(card
);
1305 static const struct platform_device_id mc_id_table
[] = {
1309 MODULE_DEVICE_TABLE(platform
, mc_id_table
);
1311 static struct platform_driver sof_sdw_driver
= {
1314 .pm
= &snd_soc_pm_ops
,
1317 .remove
= mc_remove
,
1318 .id_table
= mc_id_table
,
1321 module_platform_driver(sof_sdw_driver
);
1323 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1324 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1325 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1326 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1327 MODULE_LICENSE("GPL v2");
1328 MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
1329 MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");