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