xref: /linux/sound/soc/intel/boards/sof_sdw.c (revision 9557b4376d02088a33e5f4116bcc324d35a3b64c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2020 Intel Corporation
3 
4 /*
5  *  sof_sdw - ASOC Machine driver for Intel SoundWire platforms
6  */
7 
8 #include <linux/bitmap.h>
9 #include <linux/device.h>
10 #include <linux/dmi.h>
11 #include <linux/module.h>
12 #include <linux/soundwire/sdw.h>
13 #include <linux/soundwire/sdw_type.h>
14 #include <sound/soc.h>
15 #include <sound/soc-acpi.h>
16 #include "sof_sdw_common.h"
17 #include "../../codecs/rt711.h"
18 
19 unsigned long sof_sdw_quirk = RT711_JD1;
20 static int quirk_override = -1;
21 module_param_named(quirk, quirk_override, int, 0444);
22 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
23 
24 static void log_quirks(struct device *dev)
25 {
26 	if (SOF_JACK_JDSRC(sof_sdw_quirk))
27 		dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
28 			SOF_JACK_JDSRC(sof_sdw_quirk));
29 	if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
30 		dev_err(dev, "quirk SOF_SDW_FOUR_SPK enabled but no longer supported\n");
31 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
32 		dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
33 	if (sof_sdw_quirk & SOF_SDW_PCH_DMIC)
34 		dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n");
35 	if (SOF_SSP_GET_PORT(sof_sdw_quirk))
36 		dev_dbg(dev, "SSP port %ld\n",
37 			SOF_SSP_GET_PORT(sof_sdw_quirk));
38 	if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
39 		dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n");
40 	if (sof_sdw_quirk & SOF_CODEC_SPKR)
41 		dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n");
42 	if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
43 		dev_dbg(dev, "quirk SOF_SIDECAR_AMPS enabled\n");
44 }
45 
46 static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
47 {
48 	sof_sdw_quirk = (unsigned long)id->driver_data;
49 	return 1;
50 }
51 
52 static const struct dmi_system_id sof_sdw_quirk_table[] = {
53 	/* CometLake devices */
54 	{
55 		.callback = sof_sdw_quirk_cb,
56 		.matches = {
57 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
58 			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
59 		},
60 		.driver_data = (void *)SOF_SDW_PCH_DMIC,
61 	},
62 	{
63 		.callback = sof_sdw_quirk_cb,
64 		.matches = {
65 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
66 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
67 		},
68 		.driver_data = (void *)RT711_JD2,
69 	},
70 	{
71 		/* early version of SKU 09C6 */
72 		.callback = sof_sdw_quirk_cb,
73 		.matches = {
74 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
75 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
76 		},
77 		.driver_data = (void *)RT711_JD2,
78 	},
79 	{
80 		.callback = sof_sdw_quirk_cb,
81 		.matches = {
82 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
83 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
84 		},
85 		.driver_data = (void *)(RT711_JD2),
86 	},
87 	{
88 		.callback = sof_sdw_quirk_cb,
89 		.matches = {
90 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
91 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
92 		},
93 		.driver_data = (void *)(RT711_JD2),
94 	},
95 	/* IceLake devices */
96 	{
97 		.callback = sof_sdw_quirk_cb,
98 		.matches = {
99 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
100 			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
101 		},
102 		.driver_data = (void *)SOF_SDW_PCH_DMIC,
103 	},
104 	/* TigerLake devices */
105 	{
106 		.callback = sof_sdw_quirk_cb,
107 		.matches = {
108 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
109 			DMI_MATCH(DMI_PRODUCT_NAME,
110 				  "Tiger Lake Client Platform"),
111 		},
112 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
113 					RT711_JD1 |
114 					SOF_SDW_PCH_DMIC |
115 					SOF_SSP_PORT(SOF_I2S_SSP2)),
116 	},
117 	{
118 		.callback = sof_sdw_quirk_cb,
119 		.matches = {
120 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
121 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
122 		},
123 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
124 					RT711_JD2),
125 	},
126 	{
127 		/* another SKU of Dell Latitude 9520 */
128 		.callback = sof_sdw_quirk_cb,
129 		.matches = {
130 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
131 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
132 		},
133 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
134 					RT711_JD2),
135 	},
136 	{
137 		/* Dell XPS 9710 */
138 		.callback = sof_sdw_quirk_cb,
139 		.matches = {
140 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
141 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
142 		},
143 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
144 					RT711_JD2),
145 	},
146 	{
147 		.callback = sof_sdw_quirk_cb,
148 		.matches = {
149 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
150 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
151 		},
152 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
153 					RT711_JD2),
154 	},
155 	{
156 		.callback = sof_sdw_quirk_cb,
157 		.matches = {
158 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
159 			DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
160 		},
161 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
162 					SOF_SDW_PCH_DMIC |
163 					SOF_BT_OFFLOAD_SSP(2) |
164 					SOF_SSP_BT_OFFLOAD_PRESENT),
165 	},
166 	{
167 		.callback = sof_sdw_quirk_cb,
168 		.matches = {
169 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
170 			DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
171 		},
172 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
173 					SOF_SDW_PCH_DMIC),
174 	},
175 	{
176 		/*
177 		 * this entry covers multiple HP SKUs. The family name
178 		 * does not seem robust enough, so we use a partial
179 		 * match that ignores the product name suffix
180 		 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
181 		 */
182 		.callback = sof_sdw_quirk_cb,
183 		.matches = {
184 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
185 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
186 		},
187 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
188 					SOF_SDW_PCH_DMIC |
189 					RT711_JD1),
190 	},
191 	{
192 		/*
193 		 * this entry covers HP Spectre x360 where the DMI information
194 		 * changed somehow
195 		 */
196 		.callback = sof_sdw_quirk_cb,
197 		.matches = {
198 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
199 			DMI_MATCH(DMI_BOARD_NAME, "8709"),
200 		},
201 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
202 					SOF_SDW_PCH_DMIC |
203 					RT711_JD1),
204 	},
205 	{
206 		/* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
207 		.callback = sof_sdw_quirk_cb,
208 		.matches = {
209 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
210 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
211 		},
212 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
213 					SOF_SDW_PCH_DMIC |
214 					RT711_JD1),
215 	},
216 	{
217 		/* NUC15 LAPBC710 skews */
218 		.callback = sof_sdw_quirk_cb,
219 		.matches = {
220 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
221 			DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
222 		},
223 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
224 					SOF_SDW_PCH_DMIC |
225 					RT711_JD1),
226 	},
227 	{
228 		/* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
229 		.callback = sof_sdw_quirk_cb,
230 		.matches = {
231 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
232 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
233 		},
234 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
235 					SOF_SDW_PCH_DMIC |
236 					RT711_JD2_100K),
237 	},
238 	{
239 		/* NUC15 LAPRC710 skews */
240 		.callback = sof_sdw_quirk_cb,
241 		.matches = {
242 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
243 			DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
244 		},
245 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
246 					SOF_SDW_PCH_DMIC |
247 					RT711_JD2_100K),
248 	},
249 	/* TigerLake-SDCA devices */
250 	{
251 		.callback = sof_sdw_quirk_cb,
252 		.matches = {
253 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
254 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
255 		},
256 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
257 					RT711_JD2),
258 	},
259 	{
260 		.callback = sof_sdw_quirk_cb,
261 		.matches = {
262 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
263 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
264 		},
265 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
266 					RT711_JD2),
267 	},
268 	/* AlderLake devices */
269 	{
270 		.callback = sof_sdw_quirk_cb,
271 		.matches = {
272 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
273 			DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
274 		},
275 		.driver_data = (void *)(RT711_JD2_100K |
276 					SOF_SDW_TGL_HDMI |
277 					SOF_BT_OFFLOAD_SSP(2) |
278 					SOF_SSP_BT_OFFLOAD_PRESENT),
279 	},
280 	{
281 		.callback = sof_sdw_quirk_cb,
282 		.matches = {
283 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
284 			DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"),
285 		},
286 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
287 					RT711_JD2_100K),
288 	},
289 	{
290 		.callback = sof_sdw_quirk_cb,
291 		.matches = {
292 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
293 			DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
294 		},
295 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
296 					SOF_SDW_PCH_DMIC |
297 					SOF_BT_OFFLOAD_SSP(2) |
298 					SOF_SSP_BT_OFFLOAD_PRESENT),
299 	},
300 	{
301 		.callback = sof_sdw_quirk_cb,
302 		.matches = {
303 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
304 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
305 		},
306 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
307 					RT711_JD2),
308 	},
309 	{
310 		.callback = sof_sdw_quirk_cb,
311 		.matches = {
312 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
313 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
314 		},
315 		/* No Jack */
316 		.driver_data = (void *)(SOF_SDW_TGL_HDMI),
317 	},
318 	{
319 		.callback = sof_sdw_quirk_cb,
320 		.matches = {
321 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
322 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
323 		},
324 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
325 					RT711_JD2),
326 	},
327 	{
328 		.callback = sof_sdw_quirk_cb,
329 		.matches = {
330 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
331 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
332 		},
333 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
334 					RT711_JD2),
335 	},
336 	{
337 		.callback = sof_sdw_quirk_cb,
338 		.matches = {
339 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
340 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
341 		},
342 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
343 					RT711_JD2),
344 	},
345 	{
346 		.callback = sof_sdw_quirk_cb,
347 		.matches = {
348 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
349 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
350 		},
351 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
352 					RT711_JD2),
353 	},
354 	{
355 		.callback = sof_sdw_quirk_cb,
356 		.matches = {
357 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
358 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11")
359 		},
360 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
361 					RT711_JD2),
362 	},
363 	{
364 		.callback = sof_sdw_quirk_cb,
365 		.matches = {
366 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
367 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12")
368 		},
369 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
370 					RT711_JD2),
371 	},
372 	{
373 		.callback = sof_sdw_quirk_cb,
374 		.matches = {
375 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
376 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
377 		},
378 		/* No Jack */
379 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
380 	},
381 	{
382 		.callback = sof_sdw_quirk_cb,
383 		.matches = {
384 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
385 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"),
386 		},
387 		/* No Jack */
388 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
389 	},
390 
391 	{
392 		.callback = sof_sdw_quirk_cb,
393 		.matches = {
394 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
395 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
396 		},
397 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
398 					RT711_JD2),
399 	},
400 	{
401 		.callback = sof_sdw_quirk_cb,
402 		.matches = {
403 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
404 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
405 		},
406 		/* No Jack */
407 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
408 	},
409 	{
410 		.callback = sof_sdw_quirk_cb,
411 		.matches = {
412 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
413 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B8C"),
414 		},
415 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
416 					RT711_JD2),
417 	},
418 	{
419 		.callback = sof_sdw_quirk_cb,
420 		.matches = {
421 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
422 			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
423 		},
424 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
425 					RT711_JD2),
426 	},
427 	/* RaptorLake devices */
428 	{
429 		.callback = sof_sdw_quirk_cb,
430 		.matches = {
431 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
432 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
433 		},
434 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
435 					RT711_JD2),
436 	},
437 	{
438 		.callback = sof_sdw_quirk_cb,
439 		.matches = {
440 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
441 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
442 		},
443 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
444 					RT711_JD2),
445 	},
446 	{
447 		.callback = sof_sdw_quirk_cb,
448 		.matches = {
449 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
450 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"),
451 		},
452 		/* No Jack */
453 		.driver_data = (void *)(SOF_SDW_TGL_HDMI),
454 	},
455 	{
456 		.callback = sof_sdw_quirk_cb,
457 		.matches = {
458 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
459 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11")
460 		},
461 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
462 					RT711_JD2),
463 	},
464 	{
465 		.callback = sof_sdw_quirk_cb,
466 		.matches = {
467 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
468 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40")
469 		},
470 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
471 					RT711_JD2),
472 	},
473 	{
474 		.callback = sof_sdw_quirk_cb,
475 		.matches = {
476 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
477 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F")
478 		},
479 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
480 					RT711_JD2),
481 	},
482 	/* MeteorLake devices */
483 	{
484 		.callback = sof_sdw_quirk_cb,
485 		.matches = {
486 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
487 		},
488 		.driver_data = (void *)(RT711_JD1),
489 	},
490 	{
491 		.callback = sof_sdw_quirk_cb,
492 		.matches = {
493 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
494 			DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"),
495 		},
496 		.driver_data = (void *)(RT711_JD2_100K),
497 	},
498 	{
499 		.callback = sof_sdw_quirk_cb,
500 		.matches = {
501 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
502 			DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
503 		},
504 		.driver_data = (void *)(SOF_SDW_PCH_DMIC |
505 					SOF_BT_OFFLOAD_SSP(1) |
506 					SOF_SSP_BT_OFFLOAD_PRESENT),
507 	},
508 	{
509 		.callback = sof_sdw_quirk_cb,
510 		.matches = {
511 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
512 			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"),
513 		},
514 		.driver_data = (void *)(RT711_JD2),
515 	},
516 
517 	/* LunarLake devices */
518 	{
519 		.callback = sof_sdw_quirk_cb,
520 		.matches = {
521 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
522 			DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
523 		},
524 		.driver_data = (void *)(RT711_JD2),
525 	},
526 	{
527 		.callback = sof_sdw_quirk_cb,
528 		.matches = {
529 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
530 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3")
531 		},
532 		.driver_data = (void *)(SOF_SIDECAR_AMPS),
533 	},
534 	{
535 		.callback = sof_sdw_quirk_cb,
536 		.matches = {
537 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
538 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4")
539 		},
540 		.driver_data = (void *)(SOF_SIDECAR_AMPS),
541 	},
542 	{}
543 };
544 
545 static struct snd_soc_dai_link_component platform_component[] = {
546 	{
547 		/* name might be overridden during probe */
548 		.name = "0000:00:1f.3"
549 	}
550 };
551 
552 static const struct snd_soc_dapm_widget generic_dmic_widgets[] = {
553 	SND_SOC_DAPM_MIC("DMIC", NULL),
554 };
555 
556 static const struct snd_soc_dapm_widget generic_jack_widgets[] = {
557 	SND_SOC_DAPM_HP("Headphone", NULL),
558 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
559 };
560 
561 static const struct snd_kcontrol_new generic_jack_controls[] = {
562 	SOC_DAPM_PIN_SWITCH("Headphone"),
563 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
564 };
565 
566 static const struct snd_soc_dapm_widget generic_spk_widgets[] = {
567 	SND_SOC_DAPM_SPK("Speaker", NULL),
568 };
569 
570 static const struct snd_kcontrol_new generic_spk_controls[] = {
571 	SOC_DAPM_PIN_SWITCH("Speaker"),
572 };
573 
574 static const struct snd_soc_dapm_widget maxim_widgets[] = {
575 	SND_SOC_DAPM_SPK("Left Spk", NULL),
576 	SND_SOC_DAPM_SPK("Right Spk", NULL),
577 };
578 
579 static const struct snd_kcontrol_new maxim_controls[] = {
580 	SOC_DAPM_PIN_SWITCH("Left Spk"),
581 	SOC_DAPM_PIN_SWITCH("Right Spk"),
582 };
583 
584 static const struct snd_soc_dapm_widget rt700_widgets[] = {
585 	SND_SOC_DAPM_HP("Headphones", NULL),
586 	SND_SOC_DAPM_MIC("AMIC", NULL),
587 	SND_SOC_DAPM_SPK("Speaker", NULL),
588 };
589 
590 static const struct snd_kcontrol_new rt700_controls[] = {
591 	SOC_DAPM_PIN_SWITCH("Headphones"),
592 	SOC_DAPM_PIN_SWITCH("AMIC"),
593 	SOC_DAPM_PIN_SWITCH("Speaker"),
594 };
595 
596 /* these wrappers are only needed to avoid typecast compilation errors */
597 int sdw_startup(struct snd_pcm_substream *substream)
598 {
599 	return sdw_startup_stream(substream);
600 }
601 
602 int sdw_prepare(struct snd_pcm_substream *substream)
603 {
604 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
605 	struct sdw_stream_runtime *sdw_stream;
606 	struct snd_soc_dai *dai;
607 
608 	/* Find stream from first CPU DAI */
609 	dai = snd_soc_rtd_to_cpu(rtd, 0);
610 
611 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
612 	if (IS_ERR(sdw_stream)) {
613 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
614 		return PTR_ERR(sdw_stream);
615 	}
616 
617 	return sdw_prepare_stream(sdw_stream);
618 }
619 
620 int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
621 {
622 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
623 	struct sdw_stream_runtime *sdw_stream;
624 	struct snd_soc_dai *dai;
625 	int ret;
626 
627 	/* Find stream from first CPU DAI */
628 	dai = snd_soc_rtd_to_cpu(rtd, 0);
629 
630 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
631 	if (IS_ERR(sdw_stream)) {
632 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
633 		return PTR_ERR(sdw_stream);
634 	}
635 
636 	switch (cmd) {
637 	case SNDRV_PCM_TRIGGER_START:
638 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
639 	case SNDRV_PCM_TRIGGER_RESUME:
640 		ret = sdw_enable_stream(sdw_stream);
641 		break;
642 
643 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
644 	case SNDRV_PCM_TRIGGER_SUSPEND:
645 	case SNDRV_PCM_TRIGGER_STOP:
646 		ret = sdw_disable_stream(sdw_stream);
647 		break;
648 	default:
649 		ret = -EINVAL;
650 		break;
651 	}
652 
653 	if (ret)
654 		dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret);
655 
656 	return ret;
657 }
658 
659 int sdw_hw_params(struct snd_pcm_substream *substream,
660 		  struct snd_pcm_hw_params *params)
661 {
662 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
663 	struct snd_soc_dai_link_ch_map *ch_maps;
664 	int ch = params_channels(params);
665 	unsigned int ch_mask;
666 	int num_codecs;
667 	int step;
668 	int i;
669 
670 	if (!rtd->dai_link->ch_maps)
671 		return 0;
672 
673 	/* Identical data will be sent to all codecs in playback */
674 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
675 		ch_mask = GENMASK(ch - 1, 0);
676 		step = 0;
677 	} else {
678 		num_codecs = rtd->dai_link->num_codecs;
679 
680 		if (ch < num_codecs || ch % num_codecs != 0) {
681 			dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n",
682 				ch, num_codecs);
683 			return -EINVAL;
684 		}
685 
686 		ch_mask = GENMASK(ch / num_codecs - 1, 0);
687 		step = hweight_long(ch_mask);
688 
689 	}
690 
691 	/*
692 	 * The captured data will be combined from each cpu DAI if the dai
693 	 * link has more than one codec DAIs. Set codec channel mask and
694 	 * ASoC will set the corresponding channel numbers for each cpu dai.
695 	 */
696 	for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
697 		ch_maps->ch_mask = ch_mask << (i * step);
698 
699 	return 0;
700 }
701 
702 int sdw_hw_free(struct snd_pcm_substream *substream)
703 {
704 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
705 	struct sdw_stream_runtime *sdw_stream;
706 	struct snd_soc_dai *dai;
707 
708 	/* Find stream from first CPU DAI */
709 	dai = snd_soc_rtd_to_cpu(rtd, 0);
710 
711 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
712 	if (IS_ERR(sdw_stream)) {
713 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
714 		return PTR_ERR(sdw_stream);
715 	}
716 
717 	return sdw_deprepare_stream(sdw_stream);
718 }
719 
720 void sdw_shutdown(struct snd_pcm_substream *substream)
721 {
722 	sdw_shutdown_stream(substream);
723 }
724 
725 static const struct snd_soc_ops sdw_ops = {
726 	.startup = sdw_startup,
727 	.prepare = sdw_prepare,
728 	.trigger = sdw_trigger,
729 	.hw_params = sdw_hw_params,
730 	.hw_free = sdw_hw_free,
731 	.shutdown = sdw_shutdown,
732 };
733 
734 static struct sof_sdw_codec_info codec_info_list[] = {
735 	{
736 		.part_id = 0x700,
737 		.dais = {
738 			{
739 				.direction = {true, true},
740 				.dai_name = "rt700-aif1",
741 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
742 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
743 				.rtd_init = rt700_rtd_init,
744 				.controls = rt700_controls,
745 				.num_controls = ARRAY_SIZE(rt700_controls),
746 				.widgets = rt700_widgets,
747 				.num_widgets = ARRAY_SIZE(rt700_widgets),
748 			},
749 		},
750 		.dai_num = 1,
751 	},
752 	{
753 		.part_id = 0x711,
754 		.version_id = 3,
755 		.dais = {
756 			{
757 				.direction = {true, true},
758 				.dai_name = "rt711-sdca-aif1",
759 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
760 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
761 				.init = sof_sdw_rt_sdca_jack_init,
762 				.exit = sof_sdw_rt_sdca_jack_exit,
763 				.rtd_init = rt_sdca_jack_rtd_init,
764 				.controls = generic_jack_controls,
765 				.num_controls = ARRAY_SIZE(generic_jack_controls),
766 				.widgets = generic_jack_widgets,
767 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
768 			},
769 		},
770 		.dai_num = 1,
771 	},
772 	{
773 		.part_id = 0x711,
774 		.version_id = 2,
775 		.dais = {
776 			{
777 				.direction = {true, true},
778 				.dai_name = "rt711-aif1",
779 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
780 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
781 				.init = sof_sdw_rt711_init,
782 				.exit = sof_sdw_rt711_exit,
783 				.rtd_init = rt711_rtd_init,
784 				.controls = generic_jack_controls,
785 				.num_controls = ARRAY_SIZE(generic_jack_controls),
786 				.widgets = generic_jack_widgets,
787 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
788 			},
789 		},
790 		.dai_num = 1,
791 	},
792 	{
793 		.part_id = 0x712,
794 		.version_id = 3,
795 		.dais =	{
796 			{
797 				.direction = {true, true},
798 				.dai_name = "rt712-sdca-aif1",
799 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
800 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
801 				.init = sof_sdw_rt_sdca_jack_init,
802 				.exit = sof_sdw_rt_sdca_jack_exit,
803 				.rtd_init = rt_sdca_jack_rtd_init,
804 				.controls = generic_jack_controls,
805 				.num_controls = ARRAY_SIZE(generic_jack_controls),
806 				.widgets = generic_jack_widgets,
807 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
808 			},
809 			{
810 				.direction = {true, false},
811 				.dai_name = "rt712-sdca-aif2",
812 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
813 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
814 				.init = sof_sdw_rt_amp_init,
815 				.exit = sof_sdw_rt_amp_exit,
816 				.rtd_init = rt712_spk_rtd_init,
817 				.controls = generic_spk_controls,
818 				.num_controls = ARRAY_SIZE(generic_spk_controls),
819 				.widgets = generic_spk_widgets,
820 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
821 			},
822 		},
823 		.dai_num = 2,
824 	},
825 	{
826 		.part_id = 0x1712,
827 		.version_id = 3,
828 		.dais =	{
829 			{
830 				.direction = {false, true},
831 				.dai_name = "rt712-sdca-dmic-aif1",
832 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
833 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
834 				.rtd_init = rt_dmic_rtd_init,
835 			},
836 		},
837 		.dai_num = 1,
838 	},
839 	{
840 		.part_id = 0x713,
841 		.version_id = 3,
842 		.dais =	{
843 			{
844 				.direction = {true, true},
845 				.dai_name = "rt712-sdca-aif1",
846 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
847 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
848 				.init = sof_sdw_rt_sdca_jack_init,
849 				.exit = sof_sdw_rt_sdca_jack_exit,
850 				.rtd_init = rt_sdca_jack_rtd_init,
851 				.controls = generic_jack_controls,
852 				.num_controls = ARRAY_SIZE(generic_jack_controls),
853 				.widgets = generic_jack_widgets,
854 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
855 			},
856 		},
857 		.dai_num = 1,
858 	},
859 	{
860 		.part_id = 0x1713,
861 		.version_id = 3,
862 		.dais =	{
863 			{
864 				.direction = {false, true},
865 				.dai_name = "rt712-sdca-dmic-aif1",
866 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
867 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
868 				.rtd_init = rt_dmic_rtd_init,
869 			},
870 		},
871 		.dai_num = 1,
872 	},
873 	{
874 		.part_id = 0x1308,
875 		.acpi_id = "10EC1308",
876 		.dais = {
877 			{
878 				.direction = {true, false},
879 				.dai_name = "rt1308-aif",
880 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
881 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
882 				.init = sof_sdw_rt_amp_init,
883 				.exit = sof_sdw_rt_amp_exit,
884 				.rtd_init = rt_amp_spk_rtd_init,
885 				.controls = generic_spk_controls,
886 				.num_controls = ARRAY_SIZE(generic_spk_controls),
887 				.widgets = generic_spk_widgets,
888 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
889 			},
890 		},
891 		.dai_num = 1,
892 		.ops = &sof_sdw_rt1308_i2s_ops,
893 	},
894 	{
895 		.part_id = 0x1316,
896 		.dais = {
897 			{
898 				.direction = {true, true},
899 				.dai_name = "rt1316-aif",
900 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
901 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
902 				.init = sof_sdw_rt_amp_init,
903 				.exit = sof_sdw_rt_amp_exit,
904 				.rtd_init = rt_amp_spk_rtd_init,
905 				.controls = generic_spk_controls,
906 				.num_controls = ARRAY_SIZE(generic_spk_controls),
907 				.widgets = generic_spk_widgets,
908 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
909 			},
910 		},
911 		.dai_num = 1,
912 	},
913 	{
914 		.part_id = 0x1318,
915 		.dais = {
916 			{
917 				.direction = {true, true},
918 				.dai_name = "rt1318-aif",
919 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
920 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
921 				.init = sof_sdw_rt_amp_init,
922 				.exit = sof_sdw_rt_amp_exit,
923 				.rtd_init = rt_amp_spk_rtd_init,
924 				.controls = generic_spk_controls,
925 				.num_controls = ARRAY_SIZE(generic_spk_controls),
926 				.widgets = generic_spk_widgets,
927 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
928 			},
929 		},
930 		.dai_num = 1,
931 	},
932 	{
933 		.part_id = 0x714,
934 		.version_id = 3,
935 		.ignore_pch_dmic = true,
936 		.dais = {
937 			{
938 				.direction = {false, true},
939 				.dai_name = "rt715-sdca-aif2",
940 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
941 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
942 				.rtd_init = rt_dmic_rtd_init,
943 			},
944 		},
945 		.dai_num = 1,
946 	},
947 	{
948 		.part_id = 0x715,
949 		.version_id = 3,
950 		.ignore_pch_dmic = true,
951 		.dais = {
952 			{
953 				.direction = {false, true},
954 				.dai_name = "rt715-sdca-aif2",
955 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
956 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
957 				.rtd_init = rt_dmic_rtd_init,
958 			},
959 		},
960 		.dai_num = 1,
961 	},
962 	{
963 		.part_id = 0x714,
964 		.version_id = 2,
965 		.ignore_pch_dmic = true,
966 		.dais = {
967 			{
968 				.direction = {false, true},
969 				.dai_name = "rt715-aif2",
970 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
971 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
972 				.rtd_init = rt_dmic_rtd_init,
973 			},
974 		},
975 		.dai_num = 1,
976 	},
977 	{
978 		.part_id = 0x715,
979 		.version_id = 2,
980 		.ignore_pch_dmic = true,
981 		.dais = {
982 			{
983 				.direction = {false, true},
984 				.dai_name = "rt715-aif2",
985 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
986 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
987 				.rtd_init = rt_dmic_rtd_init,
988 			},
989 		},
990 		.dai_num = 1,
991 	},
992 	{
993 		.part_id = 0x722,
994 		.version_id = 3,
995 		.dais = {
996 			{
997 				.direction = {true, true},
998 				.dai_name = "rt722-sdca-aif1",
999 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1000 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
1001 				.init = sof_sdw_rt_sdca_jack_init,
1002 				.exit = sof_sdw_rt_sdca_jack_exit,
1003 				.rtd_init = rt_sdca_jack_rtd_init,
1004 				.controls = generic_jack_controls,
1005 				.num_controls = ARRAY_SIZE(generic_jack_controls),
1006 				.widgets = generic_jack_widgets,
1007 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
1008 			},
1009 			{
1010 				.direction = {true, false},
1011 				.dai_name = "rt722-sdca-aif2",
1012 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1013 				/* No feedback capability is provided by rt722-sdca codec driver*/
1014 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
1015 				.init = sof_sdw_rt_amp_init,
1016 				.exit = sof_sdw_rt_amp_exit,
1017 				.rtd_init = rt722_spk_rtd_init,
1018 				.controls = generic_spk_controls,
1019 				.num_controls = ARRAY_SIZE(generic_spk_controls),
1020 				.widgets = generic_spk_widgets,
1021 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
1022 			},
1023 			{
1024 				.direction = {false, true},
1025 				.dai_name = "rt722-sdca-aif3",
1026 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
1027 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
1028 				.rtd_init = rt_dmic_rtd_init,
1029 			},
1030 		},
1031 		.dai_num = 3,
1032 	},
1033 	{
1034 		.part_id = 0x8373,
1035 		.dais = {
1036 			{
1037 				.direction = {true, true},
1038 				.dai_name = "max98373-aif1",
1039 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1040 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
1041 				.init = sof_sdw_maxim_init,
1042 				.rtd_init = maxim_spk_rtd_init,
1043 				.controls = maxim_controls,
1044 				.num_controls = ARRAY_SIZE(maxim_controls),
1045 				.widgets = maxim_widgets,
1046 				.num_widgets = ARRAY_SIZE(maxim_widgets),
1047 			},
1048 		},
1049 		.dai_num = 1,
1050 	},
1051 	{
1052 		.part_id = 0x8363,
1053 		.dais = {
1054 			{
1055 				.direction = {true, false},
1056 				.dai_name = "max98363-aif1",
1057 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1058 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
1059 				.init = sof_sdw_maxim_init,
1060 				.rtd_init = maxim_spk_rtd_init,
1061 				.controls = maxim_controls,
1062 				.num_controls = ARRAY_SIZE(maxim_controls),
1063 				.widgets = maxim_widgets,
1064 				.num_widgets = ARRAY_SIZE(maxim_widgets),
1065 			},
1066 		},
1067 		.dai_num = 1,
1068 	},
1069 	{
1070 		.part_id = 0x5682,
1071 		.dais = {
1072 			{
1073 				.direction = {true, true},
1074 				.dai_name = "rt5682-sdw",
1075 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1076 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
1077 				.rtd_init = rt5682_rtd_init,
1078 				.controls = generic_jack_controls,
1079 				.num_controls = ARRAY_SIZE(generic_jack_controls),
1080 				.widgets = generic_jack_widgets,
1081 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
1082 			},
1083 		},
1084 		.dai_num = 1,
1085 	},
1086 	{
1087 		.part_id = 0x3556,
1088 		.dais = {
1089 			{
1090 				.direction = {true, true},
1091 				.dai_name = "cs35l56-sdw1",
1092 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1093 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
1094 				.init = sof_sdw_cs_amp_init,
1095 				.rtd_init = cs_spk_rtd_init,
1096 				.controls = generic_spk_controls,
1097 				.num_controls = ARRAY_SIZE(generic_spk_controls),
1098 				.widgets = generic_spk_widgets,
1099 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
1100 			},
1101 		},
1102 		.dai_num = 1,
1103 	},
1104 	{
1105 		.part_id = 0x4242,
1106 		.dais = {
1107 			{
1108 				.direction = {true, true},
1109 				.dai_name = "cs42l42-sdw",
1110 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1111 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
1112 				.rtd_init = cs42l42_rtd_init,
1113 				.controls = generic_jack_controls,
1114 				.num_controls = ARRAY_SIZE(generic_jack_controls),
1115 				.widgets = generic_jack_widgets,
1116 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
1117 			},
1118 		},
1119 		.dai_num = 1,
1120 	},
1121 	{
1122 		.part_id = 0x4243,
1123 		.codec_name = "cs42l43-codec",
1124 		.count_sidecar = bridge_cs35l56_count_sidecar,
1125 		.add_sidecar = bridge_cs35l56_add_sidecar,
1126 		.dais = {
1127 			{
1128 				.direction = {true, false},
1129 				.dai_name = "cs42l43-dp5",
1130 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1131 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
1132 				.rtd_init = cs42l43_hs_rtd_init,
1133 				.controls = generic_jack_controls,
1134 				.num_controls = ARRAY_SIZE(generic_jack_controls),
1135 				.widgets = generic_jack_widgets,
1136 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
1137 			},
1138 			{
1139 				.direction = {false, true},
1140 				.dai_name = "cs42l43-dp1",
1141 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
1142 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
1143 				.rtd_init = cs42l43_dmic_rtd_init,
1144 				.widgets = generic_dmic_widgets,
1145 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
1146 			},
1147 			{
1148 				.direction = {false, true},
1149 				.dai_name = "cs42l43-dp2",
1150 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1151 				.dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID},
1152 			},
1153 			{
1154 				.direction = {true, false},
1155 				.dai_name = "cs42l43-dp6",
1156 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1157 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
1158 				.init = sof_sdw_cs42l43_spk_init,
1159 				.rtd_init = cs42l43_spk_rtd_init,
1160 				.controls = generic_spk_controls,
1161 				.num_controls = ARRAY_SIZE(generic_spk_controls),
1162 				.widgets = generic_spk_widgets,
1163 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
1164 				.quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS,
1165 			},
1166 		},
1167 		.dai_num = 4,
1168 	},
1169 	{
1170 		.part_id = 0xaaaa, /* generic codec mockup */
1171 		.version_id = 0,
1172 		.dais = {
1173 			{
1174 				.direction = {true, true},
1175 				.dai_name = "sdw-mockup-aif1",
1176 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1177 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
1178 			},
1179 		},
1180 		.dai_num = 1,
1181 	},
1182 	{
1183 		.part_id = 0xaa55, /* headset codec mockup */
1184 		.version_id = 0,
1185 		.dais = {
1186 			{
1187 				.direction = {true, true},
1188 				.dai_name = "sdw-mockup-aif1",
1189 				.dai_type = SOF_SDW_DAI_TYPE_JACK,
1190 				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
1191 			},
1192 		},
1193 		.dai_num = 1,
1194 	},
1195 	{
1196 		.part_id = 0x55aa, /* amplifier mockup */
1197 		.version_id = 0,
1198 		.dais = {
1199 			{
1200 				.direction = {true, true},
1201 				.dai_name = "sdw-mockup-aif1",
1202 				.dai_type = SOF_SDW_DAI_TYPE_AMP,
1203 				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
1204 			},
1205 		},
1206 		.dai_num = 1,
1207 	},
1208 	{
1209 		.part_id = 0x5555,
1210 		.version_id = 0,
1211 		.dais = {
1212 			{
1213 				.dai_name = "sdw-mockup-aif1",
1214 				.direction = {false, true},
1215 				.dai_type = SOF_SDW_DAI_TYPE_MIC,
1216 				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
1217 			},
1218 		},
1219 		.dai_num = 1,
1220 	},
1221 };
1222 
1223 static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr)
1224 {
1225 	unsigned int part_id, sdw_version;
1226 	int i;
1227 
1228 	part_id = SDW_PART_ID(adr);
1229 	sdw_version = SDW_VERSION(adr);
1230 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1231 		/*
1232 		 * A codec info is for all sdw version with the part id if
1233 		 * version_id is not specified in the codec info.
1234 		 */
1235 		if (part_id == codec_info_list[i].part_id &&
1236 		    (!codec_info_list[i].version_id ||
1237 		     sdw_version == codec_info_list[i].version_id))
1238 			return &codec_info_list[i];
1239 
1240 	return NULL;
1241 
1242 }
1243 
1244 static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id)
1245 {
1246 	int i;
1247 
1248 	if (!acpi_id[0])
1249 		return NULL;
1250 
1251 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1252 		if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN))
1253 			return &codec_info_list[i];
1254 
1255 	return NULL;
1256 }
1257 
1258 static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name,
1259 						      int *dai_index)
1260 {
1261 	int i, j;
1262 
1263 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1264 		for (j = 0; j < codec_info_list[i].dai_num; j++) {
1265 			if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
1266 				*dai_index = j;
1267 				return &codec_info_list[i];
1268 			}
1269 		}
1270 	}
1271 
1272 	return NULL;
1273 }
1274 
1275 static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1276 			  int *be_id, char *name, int playback, int capture,
1277 			  struct snd_soc_dai_link_component *cpus, int cpus_num,
1278 			  struct snd_soc_dai_link_component *codecs, int codecs_num,
1279 			  int (*init)(struct snd_soc_pcm_runtime *rtd),
1280 			  const struct snd_soc_ops *ops)
1281 {
1282 	dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id);
1283 	dai_links->id = (*be_id)++;
1284 	dai_links->name = name;
1285 	dai_links->platforms = platform_component;
1286 	dai_links->num_platforms = ARRAY_SIZE(platform_component);
1287 	dai_links->no_pcm = 1;
1288 	dai_links->cpus = cpus;
1289 	dai_links->num_cpus = cpus_num;
1290 	dai_links->codecs = codecs;
1291 	dai_links->num_codecs = codecs_num;
1292 	dai_links->dpcm_playback = playback;
1293 	dai_links->dpcm_capture = capture;
1294 	dai_links->init = init;
1295 	dai_links->ops = ops;
1296 }
1297 
1298 static int init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1299 				int *be_id, char *name, int playback, int capture,
1300 				const char *cpu_dai_name,
1301 				const char *codec_name, const char *codec_dai_name,
1302 				int (*init)(struct snd_soc_pcm_runtime *rtd),
1303 				const struct snd_soc_ops *ops)
1304 {
1305 	struct snd_soc_dai_link_component *dlc;
1306 
1307 	/* Allocate two DLCs one for the CPU, one for the CODEC */
1308 	dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL);
1309 	if (!dlc || !name || !cpu_dai_name || !codec_name || !codec_dai_name)
1310 		return -ENOMEM;
1311 
1312 	dlc[0].dai_name = cpu_dai_name;
1313 
1314 	dlc[1].name = codec_name;
1315 	dlc[1].dai_name = codec_dai_name;
1316 
1317 	init_dai_link(dev, dai_links, be_id, name, playback, capture,
1318 		      &dlc[0], 1, &dlc[1], 1, init, ops);
1319 
1320 	return 0;
1321 }
1322 
1323 static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link,
1324 			     unsigned int sdw_version,
1325 			     unsigned int mfg_id,
1326 			     unsigned int part_id,
1327 			     unsigned int class_id,
1328 			     int index_in_link)
1329 {
1330 	int i;
1331 
1332 	for (i = 0; i < adr_link->num_adr; i++) {
1333 		unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
1334 		u64 adr;
1335 
1336 		/* skip itself */
1337 		if (i == index_in_link)
1338 			continue;
1339 
1340 		adr = adr_link->adr_d[i].adr;
1341 
1342 		sdw1_version = SDW_VERSION(adr);
1343 		mfg1_id = SDW_MFG_ID(adr);
1344 		part1_id = SDW_PART_ID(adr);
1345 		class1_id = SDW_CLASS_ID(adr);
1346 
1347 		if (sdw_version == sdw1_version &&
1348 		    mfg_id == mfg1_id &&
1349 		    part_id == part1_id &&
1350 		    class_id == class1_id)
1351 			return false;
1352 	}
1353 
1354 	return true;
1355 }
1356 
1357 static const char *get_codec_name(struct device *dev,
1358 				  const struct sof_sdw_codec_info *codec_info,
1359 				  const struct snd_soc_acpi_link_adr *adr_link,
1360 				  int adr_index)
1361 {
1362 	u64 adr = adr_link->adr_d[adr_index].adr;
1363 	unsigned int sdw_version = SDW_VERSION(adr);
1364 	unsigned int link_id = SDW_DISCO_LINK_ID(adr);
1365 	unsigned int unique_id = SDW_UNIQUE_ID(adr);
1366 	unsigned int mfg_id = SDW_MFG_ID(adr);
1367 	unsigned int part_id = SDW_PART_ID(adr);
1368 	unsigned int class_id = SDW_CLASS_ID(adr);
1369 
1370 	if (codec_info->codec_name)
1371 		return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL);
1372 	else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id,
1373 				  class_id, adr_index))
1374 		return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x",
1375 				      link_id, mfg_id, part_id, class_id);
1376 	else
1377 		return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
1378 				      link_id, mfg_id, part_id, class_id, unique_id);
1379 
1380 	return NULL;
1381 }
1382 
1383 static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
1384 {
1385 	struct snd_soc_card *card = rtd->card;
1386 	struct sof_sdw_codec_info *codec_info;
1387 	struct snd_soc_dai *dai;
1388 	int dai_index;
1389 	int ret;
1390 	int i;
1391 
1392 	for_each_rtd_codec_dais(rtd, i, dai) {
1393 		codec_info = find_codec_info_dai(dai->name, &dai_index);
1394 		if (!codec_info)
1395 			return -EINVAL;
1396 
1397 		/*
1398 		 * A codec dai can be connected to different dai links for capture and playback,
1399 		 * but we only need to call the rtd_init function once.
1400 		 * The rtd_init for each codec dai is independent. So, the order of rtd_init
1401 		 * doesn't matter.
1402 		 */
1403 		if (codec_info->dais[dai_index].rtd_init_done)
1404 			continue;
1405 
1406 		/*
1407 		 * Add card controls and dapm widgets for the first codec dai.
1408 		 * The controls and widgets will be used for all codec dais.
1409 		 */
1410 
1411 		if (i > 0)
1412 			goto skip_add_controls_widgets;
1413 
1414 		if (codec_info->dais[dai_index].controls) {
1415 			ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
1416 							codec_info->dais[dai_index].num_controls);
1417 			if (ret) {
1418 				dev_err(card->dev, "%#x controls addition failed: %d\n",
1419 					codec_info->part_id, ret);
1420 				return ret;
1421 			}
1422 		}
1423 		if (codec_info->dais[dai_index].widgets) {
1424 			ret = snd_soc_dapm_new_controls(&card->dapm,
1425 							codec_info->dais[dai_index].widgets,
1426 							codec_info->dais[dai_index].num_widgets);
1427 			if (ret) {
1428 				dev_err(card->dev, "%#x widgets addition failed: %d\n",
1429 					codec_info->part_id, ret);
1430 				return ret;
1431 			}
1432 		}
1433 
1434 skip_add_controls_widgets:
1435 		if (codec_info->dais[dai_index].rtd_init) {
1436 			ret = codec_info->dais[dai_index].rtd_init(rtd, dai);
1437 			if (ret)
1438 				return ret;
1439 		}
1440 		codec_info->dais[dai_index].rtd_init_done = true;
1441 	}
1442 
1443 	return 0;
1444 }
1445 
1446 struct sof_sdw_endpoint {
1447 	struct list_head list;
1448 
1449 	u32 link_mask;
1450 	const char *codec_name;
1451 	const char *name_prefix;
1452 	bool include_sidecar;
1453 
1454 	struct sof_sdw_codec_info *codec_info;
1455 	const struct sof_sdw_dai_info *dai_info;
1456 };
1457 
1458 struct sof_sdw_dailink {
1459 	bool initialised;
1460 
1461 	u8 group_id;
1462 	u32 link_mask[SNDRV_PCM_STREAM_LAST + 1];
1463 	int num_devs[SNDRV_PCM_STREAM_LAST + 1];
1464 	struct list_head endpoints;
1465 };
1466 
1467 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
1468 
1469 static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
1470 {
1471 	struct device *dev = card->dev;
1472 	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
1473 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1474 	const struct snd_soc_acpi_link_adr *adr_link;
1475 	int i;
1476 
1477 	for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
1478 		*num_devs += adr_link->num_adr;
1479 
1480 		for (i = 0; i < adr_link->num_adr; i++)
1481 			*num_ends += adr_link->adr_d[i].num_endpoints;
1482 	}
1483 
1484 	dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);
1485 
1486 	return 0;
1487 }
1488 
1489 static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks,
1490 					    const struct snd_soc_acpi_endpoint *new)
1491 {
1492 	while (dailinks->initialised) {
1493 		if (new->aggregated && dailinks->group_id == new->group_id)
1494 			return dailinks;
1495 
1496 		dailinks++;
1497 	}
1498 
1499 	INIT_LIST_HEAD(&dailinks->endpoints);
1500 	dailinks->group_id = new->group_id;
1501 	dailinks->initialised = true;
1502 
1503 	return dailinks;
1504 }
1505 
1506 static int parse_sdw_endpoints(struct snd_soc_card *card,
1507 			       struct sof_sdw_dailink *sof_dais,
1508 			       struct sof_sdw_endpoint *sof_ends,
1509 			       int *num_devs)
1510 {
1511 	struct device *dev = card->dev;
1512 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1513 	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
1514 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1515 	const struct snd_soc_acpi_link_adr *adr_link;
1516 	struct sof_sdw_endpoint *sof_end = sof_ends;
1517 	int num_dais = 0;
1518 	int i, j;
1519 	int ret;
1520 
1521 	for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
1522 		int num_link_dailinks = 0;
1523 
1524 		if (!is_power_of_2(adr_link->mask)) {
1525 			dev_err(dev, "link with multiple mask bits: 0x%x\n",
1526 				adr_link->mask);
1527 			return -EINVAL;
1528 		}
1529 
1530 		for (i = 0; i < adr_link->num_adr; i++) {
1531 			const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
1532 			struct sof_sdw_codec_info *codec_info;
1533 			const char *codec_name;
1534 
1535 			if (!adr_dev->name_prefix) {
1536 				dev_err(dev, "codec 0x%llx does not have a name prefix\n",
1537 					adr_dev->adr);
1538 				return -EINVAL;
1539 			}
1540 
1541 			codec_info = find_codec_info_part(adr_dev->adr);
1542 			if (!codec_info)
1543 				return -EINVAL;
1544 
1545 			ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic;
1546 
1547 			codec_name = get_codec_name(dev, codec_info, adr_link, i);
1548 			if (!codec_name)
1549 				return -ENOMEM;
1550 
1551 			dev_dbg(dev, "Adding prefix %s for %s\n",
1552 				adr_dev->name_prefix, codec_name);
1553 
1554 			sof_end->name_prefix = adr_dev->name_prefix;
1555 
1556 			if (codec_info->count_sidecar && codec_info->add_sidecar) {
1557 				ret = codec_info->count_sidecar(card, &num_dais, num_devs);
1558 				if (ret)
1559 					return ret;
1560 
1561 				sof_end->include_sidecar = true;
1562 			}
1563 
1564 			for (j = 0; j < adr_dev->num_endpoints; j++) {
1565 				const struct snd_soc_acpi_endpoint *adr_end;
1566 				const struct sof_sdw_dai_info *dai_info;
1567 				struct sof_sdw_dailink *sof_dai;
1568 				int stream;
1569 
1570 				adr_end = &adr_dev->endpoints[j];
1571 				dai_info = &codec_info->dais[adr_end->num];
1572 				sof_dai = find_dailink(sof_dais, adr_end);
1573 
1574 				if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk))
1575 					continue;
1576 
1577 				dev_dbg(dev,
1578 					"Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n",
1579 					ffs(adr_link->mask) - 1, adr_dev->adr,
1580 					adr_end->num, type_strings[dai_info->dai_type],
1581 					dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
1582 					dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
1583 					adr_end->aggregated ? "group" : "solo",
1584 					adr_end->group_id);
1585 
1586 				if (adr_end->num >= codec_info->dai_num) {
1587 					dev_err(dev,
1588 						"%d is too many endpoints for codec: 0x%x\n",
1589 						adr_end->num, codec_info->part_id);
1590 					return -EINVAL;
1591 				}
1592 
1593 				for_each_pcm_streams(stream) {
1594 					if (dai_info->direction[stream] &&
1595 					    dai_info->dailink[stream] < 0) {
1596 						dev_err(dev,
1597 							"Invalid dailink id %d for codec: 0x%x\n",
1598 							dai_info->dailink[stream],
1599 							codec_info->part_id);
1600 						return -EINVAL;
1601 					}
1602 
1603 					if (dai_info->direction[stream]) {
1604 						num_dais += !sof_dai->num_devs[stream];
1605 						sof_dai->num_devs[stream]++;
1606 						sof_dai->link_mask[stream] |= adr_link->mask;
1607 					}
1608 				}
1609 
1610 				num_link_dailinks += !!list_empty(&sof_dai->endpoints);
1611 				list_add_tail(&sof_end->list, &sof_dai->endpoints);
1612 
1613 				sof_end->link_mask = adr_link->mask;
1614 				sof_end->codec_name = codec_name;
1615 				sof_end->codec_info = codec_info;
1616 				sof_end->dai_info = dai_info;
1617 				sof_end++;
1618 			}
1619 		}
1620 
1621 		ctx->append_dai_type |= (num_link_dailinks > 1);
1622 	}
1623 
1624 	return num_dais;
1625 }
1626 
1627 static int create_sdw_dailink(struct snd_soc_card *card,
1628 			      struct sof_sdw_dailink *sof_dai,
1629 			      struct snd_soc_dai_link **dai_links,
1630 			      int *be_id, struct snd_soc_codec_conf **codec_conf)
1631 {
1632 	struct device *dev = card->dev;
1633 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1634 	struct sof_sdw_endpoint *sof_end;
1635 	int stream;
1636 	int ret;
1637 
1638 	list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
1639 		if (sof_end->name_prefix) {
1640 			(*codec_conf)->dlc.name = sof_end->codec_name;
1641 			(*codec_conf)->name_prefix = sof_end->name_prefix;
1642 			(*codec_conf)++;
1643 		}
1644 
1645 		if (sof_end->include_sidecar) {
1646 			ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
1647 			if (ret)
1648 				return ret;
1649 		}
1650 	}
1651 
1652 	for_each_pcm_streams(stream) {
1653 		static const char * const sdw_stream_name[] = {
1654 			"SDW%d-Playback",
1655 			"SDW%d-Capture",
1656 			"SDW%d-Playback-%s",
1657 			"SDW%d-Capture-%s",
1658 		};
1659 		struct snd_soc_dai_link_ch_map *codec_maps;
1660 		struct snd_soc_dai_link_component *codecs;
1661 		struct snd_soc_dai_link_component *cpus;
1662 		int num_cpus = hweight32(sof_dai->link_mask[stream]);
1663 		int num_codecs = sof_dai->num_devs[stream];
1664 		int playback, capture;
1665 		int cur_link = 0;
1666 		int i = 0, j = 0;
1667 		char *name;
1668 
1669 		if (!sof_dai->num_devs[stream])
1670 			continue;
1671 
1672 		sof_end = list_first_entry(&sof_dai->endpoints,
1673 					   struct sof_sdw_endpoint, list);
1674 
1675 		*be_id = sof_end->dai_info->dailink[stream];
1676 		if (*be_id < 0) {
1677 			dev_err(dev, "Invalid dailink id %d\n", *be_id);
1678 			return -EINVAL;
1679 		}
1680 
1681 		/* create stream name according to first link id */
1682 		if (ctx->append_dai_type)
1683 			name = devm_kasprintf(dev, GFP_KERNEL,
1684 					      sdw_stream_name[stream + 2],
1685 					      ffs(sof_end->link_mask) - 1,
1686 					      type_strings[sof_end->dai_info->dai_type]);
1687 		else
1688 			name = devm_kasprintf(dev, GFP_KERNEL,
1689 					      sdw_stream_name[stream],
1690 					      ffs(sof_end->link_mask) - 1);
1691 		if (!name)
1692 			return -ENOMEM;
1693 
1694 		cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
1695 		if (!cpus)
1696 			return -ENOMEM;
1697 
1698 		codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
1699 		if (!codecs)
1700 			return -ENOMEM;
1701 
1702 		codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
1703 		if (!codec_maps)
1704 			return -ENOMEM;
1705 
1706 		list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
1707 			if (!sof_end->dai_info->direction[stream])
1708 				continue;
1709 
1710 			if (cur_link != sof_end->link_mask) {
1711 				int link_num = ffs(sof_end->link_mask) - 1;
1712 				int pin_num = ctx->sdw_pin_index[link_num]++;
1713 
1714 				cur_link = sof_end->link_mask;
1715 
1716 				cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
1717 								  "SDW%d Pin%d",
1718 								  link_num, pin_num);
1719 				if (!cpus[i].dai_name)
1720 					return -ENOMEM;
1721 				i++;
1722 			}
1723 
1724 			codec_maps[j].cpu = i - 1;
1725 			codec_maps[j].codec = j;
1726 
1727 			codecs[j].name = sof_end->codec_name;
1728 			codecs[j].dai_name = sof_end->dai_info->dai_name;
1729 			j++;
1730 		}
1731 
1732 		WARN_ON(i != num_cpus || j != num_codecs);
1733 
1734 		playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
1735 		capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
1736 
1737 		init_dai_link(dev, *dai_links, be_id, name, playback, capture,
1738 			      cpus, num_cpus, codecs, num_codecs,
1739 			      sof_sdw_rtd_init, &sdw_ops);
1740 
1741 		/*
1742 		 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
1743 		 * based on wait_for_completion(), tag them as 'nonatomic'.
1744 		 */
1745 		(*dai_links)->nonatomic = true;
1746 		(*dai_links)->ch_maps = codec_maps;
1747 
1748 		list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
1749 			if (sof_end->dai_info->init)
1750 				sof_end->dai_info->init(card, *dai_links,
1751 							sof_end->codec_info,
1752 							playback);
1753 		}
1754 
1755 		(*dai_links)++;
1756 	}
1757 
1758 	return 0;
1759 }
1760 
1761 static int create_sdw_dailinks(struct snd_soc_card *card,
1762 			       struct snd_soc_dai_link **dai_links, int *be_id,
1763 			       struct sof_sdw_dailink *sof_dais,
1764 			       struct snd_soc_codec_conf **codec_conf)
1765 {
1766 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1767 	int ret, i;
1768 
1769 	for (i = 0; i < SDW_MAX_LINKS; i++)
1770 		ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE;
1771 
1772 	/* generate DAI links by each sdw link */
1773 	while (sof_dais->initialised) {
1774 		int current_be_id;
1775 
1776 		ret = create_sdw_dailink(card, sof_dais, dai_links,
1777 					 &current_be_id, codec_conf);
1778 		if (ret)
1779 			return ret;
1780 
1781 		/* Update the be_id to match the highest ID used for SDW link */
1782 		if (*be_id < current_be_id)
1783 			*be_id = current_be_id;
1784 
1785 		sof_dais++;
1786 	}
1787 
1788 	return 0;
1789 }
1790 
1791 static int create_ssp_dailinks(struct snd_soc_card *card,
1792 			       struct snd_soc_dai_link **dai_links, int *be_id,
1793 			       struct sof_sdw_codec_info *ssp_info,
1794 			       unsigned long ssp_mask)
1795 {
1796 	struct device *dev = card->dev;
1797 	int i, j = 0;
1798 	int ret;
1799 
1800 	for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) {
1801 		char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
1802 		char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
1803 		char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
1804 						  ssp_info->acpi_id, j++);
1805 		int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
1806 		int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
1807 
1808 		ret = init_simple_dai_link(dev, *dai_links, be_id, name,
1809 					   playback, capture, cpu_dai_name,
1810 					   codec_name, ssp_info->dais[0].dai_name,
1811 					   NULL, ssp_info->ops);
1812 		if (ret)
1813 			return ret;
1814 
1815 		ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0);
1816 		if (ret < 0)
1817 			return ret;
1818 
1819 		(*dai_links)++;
1820 	}
1821 
1822 	return 0;
1823 }
1824 
1825 static int create_dmic_dailinks(struct snd_soc_card *card,
1826 				struct snd_soc_dai_link **dai_links, int *be_id)
1827 {
1828 	struct device *dev = card->dev;
1829 	int ret;
1830 
1831 	ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01",
1832 				   0, 1, // DMIC only supports capture
1833 				   "DMIC01 Pin", "dmic-codec", "dmic-hifi",
1834 				   sof_sdw_dmic_init, NULL);
1835 	if (ret)
1836 		return ret;
1837 
1838 	(*dai_links)++;
1839 
1840 	ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k",
1841 				   0, 1, // DMIC only supports capture
1842 				   "DMIC16k Pin", "dmic-codec", "dmic-hifi",
1843 				   /* don't call sof_sdw_dmic_init() twice */
1844 				   NULL, NULL);
1845 	if (ret)
1846 		return ret;
1847 
1848 	(*dai_links)++;
1849 
1850 	return 0;
1851 }
1852 
1853 static int create_hdmi_dailinks(struct snd_soc_card *card,
1854 				struct snd_soc_dai_link **dai_links, int *be_id,
1855 				int hdmi_num)
1856 {
1857 	struct device *dev = card->dev;
1858 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1859 	int i, ret;
1860 
1861 	for (i = 0; i < hdmi_num; i++) {
1862 		char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
1863 		char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
1864 		char *codec_name, *codec_dai_name;
1865 
1866 		if (ctx->hdmi.idisp_codec) {
1867 			codec_name = "ehdaudio0D2";
1868 			codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
1869 							"intel-hdmi-hifi%d", i + 1);
1870 		} else {
1871 			codec_name = "snd-soc-dummy";
1872 			codec_dai_name = "snd-soc-dummy-dai";
1873 		}
1874 
1875 		ret = init_simple_dai_link(dev, *dai_links, be_id, name,
1876 					   1, 0, // HDMI only supports playback
1877 					   cpu_dai_name, codec_name, codec_dai_name,
1878 					   i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
1879 		if (ret)
1880 			return ret;
1881 
1882 		(*dai_links)++;
1883 	}
1884 
1885 	return 0;
1886 }
1887 
1888 static int create_bt_dailinks(struct snd_soc_card *card,
1889 			      struct snd_soc_dai_link **dai_links, int *be_id)
1890 {
1891 	struct device *dev = card->dev;
1892 	int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
1893 			SOF_BT_OFFLOAD_SSP_SHIFT;
1894 	char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
1895 	char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
1896 	int ret;
1897 
1898 	ret = init_simple_dai_link(dev, *dai_links, be_id, name,
1899 				   1, 1, cpu_dai_name, snd_soc_dummy_dlc.name,
1900 				   snd_soc_dummy_dlc.dai_name, NULL, NULL);
1901 	if (ret)
1902 		return ret;
1903 
1904 	(*dai_links)++;
1905 
1906 	return 0;
1907 }
1908 
1909 static int sof_card_dai_links_create(struct snd_soc_card *card)
1910 {
1911 	struct device *dev = card->dev;
1912 	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
1913 	int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
1914 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1915 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1916 	struct snd_soc_codec_conf *codec_conf;
1917 	struct sof_sdw_codec_info *ssp_info;
1918 	struct sof_sdw_endpoint *sof_ends;
1919 	struct sof_sdw_dailink *sof_dais;
1920 	int num_devs = 0;
1921 	int num_ends = 0;
1922 	struct snd_soc_dai_link *dai_links;
1923 	int num_links;
1924 	int be_id = 0;
1925 	int hdmi_num;
1926 	unsigned long ssp_mask;
1927 	int ret;
1928 
1929 	ret = count_sdw_endpoints(card, &num_devs, &num_ends);
1930 	if (ret < 0) {
1931 		dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
1932 		return ret;
1933 	}
1934 
1935 	/* One per DAI link, worst case is a DAI link for every endpoint */
1936 	sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
1937 	if (!sof_dais)
1938 		return -ENOMEM;
1939 
1940 	/* One per endpoint, ie. each DAI on each codec/amp */
1941 	sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
1942 	if (!sof_ends) {
1943 		ret = -ENOMEM;
1944 		goto err_dai;
1945 	}
1946 
1947 	ret = parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
1948 	if (ret < 0)
1949 		goto err_end;
1950 
1951 	sdw_be_num = ret;
1952 
1953 	/*
1954 	 * on generic tgl platform, I2S or sdw mode is supported
1955 	 * based on board rework. A ACPI device is registered in
1956 	 * system only when I2S mode is supported, not sdw mode.
1957 	 * Here check ACPI ID to confirm I2S is supported.
1958 	 */
1959 	ssp_info = find_codec_info_acpi(mach->id);
1960 	if (ssp_info) {
1961 		ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
1962 		ssp_num = hweight_long(ssp_mask);
1963 	}
1964 
1965 	if (mach_params->codec_mask & IDISP_CODEC_MASK)
1966 		ctx->hdmi.idisp_codec = true;
1967 
1968 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
1969 		hdmi_num = SOF_TGL_HDMI_COUNT;
1970 	else
1971 		hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
1972 
1973 	/* enable dmic01 & dmic16k */
1974 	if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num)
1975 		dmic_num = 2;
1976 
1977 	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
1978 		bt_num = 1;
1979 
1980 	dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
1981 		sdw_be_num, ssp_num, dmic_num,
1982 		ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
1983 
1984 	codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
1985 	if (!codec_conf) {
1986 		ret = -ENOMEM;
1987 		goto err_end;
1988 	}
1989 
1990 	/* allocate BE dailinks */
1991 	num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
1992 	dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
1993 	if (!dai_links) {
1994 		ret = -ENOMEM;
1995 		goto err_end;
1996 	}
1997 
1998 	card->codec_conf = codec_conf;
1999 	card->num_configs = num_devs;
2000 	card->dai_link = dai_links;
2001 	card->num_links = num_links;
2002 
2003 	/* SDW */
2004 	if (sdw_be_num) {
2005 		ret = create_sdw_dailinks(card, &dai_links, &be_id,
2006 					  sof_dais, &codec_conf);
2007 		if (ret)
2008 			goto err_end;
2009 	}
2010 
2011 	/* SSP */
2012 	if (ssp_num) {
2013 		ret = create_ssp_dailinks(card, &dai_links, &be_id,
2014 					  ssp_info, ssp_mask);
2015 		if (ret)
2016 			goto err_end;
2017 	}
2018 
2019 	/* dmic */
2020 	if (dmic_num > 0) {
2021 		if (ctx->ignore_pch_dmic) {
2022 			dev_warn(dev, "Ignoring PCH DMIC\n");
2023 		} else {
2024 			ret = create_dmic_dailinks(card, &dai_links, &be_id);
2025 			if (ret)
2026 				goto err_end;
2027 		}
2028 	}
2029 
2030 	/* HDMI */
2031 	ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num);
2032 	if (ret)
2033 		goto err_end;
2034 
2035 	/* BT */
2036 	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
2037 		ret = create_bt_dailinks(card, &dai_links, &be_id);
2038 		if (ret)
2039 			goto err_end;
2040 	}
2041 
2042 	WARN_ON(codec_conf != card->codec_conf + card->num_configs);
2043 	WARN_ON(dai_links != card->dai_link + card->num_links);
2044 
2045 err_end:
2046 	kfree(sof_ends);
2047 err_dai:
2048 	kfree(sof_dais);
2049 
2050 	return ret;
2051 }
2052 
2053 static int sof_sdw_card_late_probe(struct snd_soc_card *card)
2054 {
2055 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
2056 	int ret = 0;
2057 	int i;
2058 
2059 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
2060 		if (codec_info_list[i].codec_card_late_probe) {
2061 			ret = codec_info_list[i].codec_card_late_probe(card);
2062 
2063 			if (ret < 0)
2064 				return ret;
2065 		}
2066 	}
2067 
2068 	if (ctx->hdmi.idisp_codec)
2069 		ret = sof_sdw_hdmi_card_late_probe(card);
2070 
2071 	return ret;
2072 }
2073 
2074 /* helper to get the link that the codec DAI is used */
2075 static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card,
2076 						       const char *dai_name)
2077 {
2078 	struct snd_soc_dai_link *dai_link;
2079 	int i;
2080 	int j;
2081 
2082 	for_each_card_prelinks(card, i, dai_link) {
2083 		for (j = 0; j < dai_link->num_codecs; j++) {
2084 			/* Check each codec in a link */
2085 			if (!strcmp(dai_link->codecs[j].dai_name, dai_name))
2086 				return dai_link;
2087 		}
2088 	}
2089 	return NULL;
2090 }
2091 
2092 static void mc_dailink_exit_loop(struct snd_soc_card *card)
2093 {
2094 	struct snd_soc_dai_link *dai_link;
2095 	int ret;
2096 	int i, j;
2097 
2098 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
2099 		for (j = 0; j < codec_info_list[i].dai_num; j++) {
2100 			codec_info_list[i].dais[j].rtd_init_done = false;
2101 			/* Check each dai in codec_info_lis to see if it is used in the link */
2102 			if (!codec_info_list[i].dais[j].exit)
2103 				continue;
2104 			/*
2105 			 * We don't need to call .exit function if there is no matched
2106 			 * dai link found.
2107 			 */
2108 			dai_link = mc_find_codec_dai_used(card,
2109 							  codec_info_list[i].dais[j].dai_name);
2110 			if (dai_link) {
2111 				/* Do the .exit function if the codec dai is used in the link */
2112 				ret = codec_info_list[i].dais[j].exit(card, dai_link);
2113 				if (ret)
2114 					dev_warn(card->dev,
2115 						 "codec exit failed %d\n",
2116 						 ret);
2117 				break;
2118 			}
2119 		}
2120 	}
2121 }
2122 
2123 static int mc_probe(struct platform_device *pdev)
2124 {
2125 	struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
2126 	struct snd_soc_card *card;
2127 	struct mc_private *ctx;
2128 	int amp_num = 0, i;
2129 	int ret;
2130 
2131 	dev_dbg(&pdev->dev, "Entry\n");
2132 
2133 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
2134 	if (!ctx)
2135 		return -ENOMEM;
2136 
2137 	card = &ctx->card;
2138 	card->dev = &pdev->dev;
2139 	card->name = "soundwire";
2140 	card->owner = THIS_MODULE;
2141 	card->late_probe = sof_sdw_card_late_probe;
2142 
2143 	snd_soc_card_set_drvdata(card, ctx);
2144 
2145 	dmi_check_system(sof_sdw_quirk_table);
2146 
2147 	if (quirk_override != -1) {
2148 		dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
2149 			 sof_sdw_quirk, quirk_override);
2150 		sof_sdw_quirk = quirk_override;
2151 	}
2152 
2153 	log_quirks(card->dev);
2154 
2155 	/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
2156 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
2157 		codec_info_list[i].amp_num = 0;
2158 
2159 	if (mach->mach_params.subsystem_id_set) {
2160 		snd_soc_card_set_pci_ssid(card,
2161 					  mach->mach_params.subsystem_vendor,
2162 					  mach->mach_params.subsystem_device);
2163 	}
2164 
2165 	ret = sof_card_dai_links_create(card);
2166 	if (ret < 0)
2167 		return ret;
2168 
2169 	/*
2170 	 * the default amp_num is zero for each codec and
2171 	 * amp_num will only be increased for active amp
2172 	 * codecs on used platform
2173 	 */
2174 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
2175 		amp_num += codec_info_list[i].amp_num;
2176 
2177 	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
2178 					  " cfg-amp:%d", amp_num);
2179 	if (!card->components)
2180 		return -ENOMEM;
2181 
2182 	if (mach->mach_params.dmic_num) {
2183 		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
2184 						  "%s mic:dmic cfg-mics:%d",
2185 						  card->components,
2186 						  mach->mach_params.dmic_num);
2187 		if (!card->components)
2188 			return -ENOMEM;
2189 	}
2190 
2191 	/* Register the card */
2192 	ret = devm_snd_soc_register_card(card->dev, card);
2193 	if (ret) {
2194 		dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
2195 		mc_dailink_exit_loop(card);
2196 		return ret;
2197 	}
2198 
2199 	platform_set_drvdata(pdev, card);
2200 
2201 	return ret;
2202 }
2203 
2204 static void mc_remove(struct platform_device *pdev)
2205 {
2206 	struct snd_soc_card *card = platform_get_drvdata(pdev);
2207 
2208 	mc_dailink_exit_loop(card);
2209 }
2210 
2211 static const struct platform_device_id mc_id_table[] = {
2212 	{ "sof_sdw", },
2213 	{}
2214 };
2215 MODULE_DEVICE_TABLE(platform, mc_id_table);
2216 
2217 static struct platform_driver sof_sdw_driver = {
2218 	.driver = {
2219 		.name = "sof_sdw",
2220 		.pm = &snd_soc_pm_ops,
2221 	},
2222 	.probe = mc_probe,
2223 	.remove_new = mc_remove,
2224 	.id_table = mc_id_table,
2225 };
2226 
2227 module_platform_driver(sof_sdw_driver);
2228 
2229 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
2230 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
2231 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
2232 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
2233 MODULE_LICENSE("GPL v2");
2234 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
2235