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