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