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