xref: /linux/sound/soc/sdw_utils/soc_sdw_utils.c (revision c429fbea6174a7dd40c4215288589a50e8a33ff6)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // This file incorporates work covered by the following copyright notice:
3 // Copyright (c) 2020 Intel Corporation
4 // Copyright(c) 2024 Advanced Micro Devices, Inc.
5 /*
6  *  soc-sdw-utils.c - common SoundWire machine driver helper functions
7  */
8 
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/soundwire/sdw.h>
12 #include <linux/soundwire/sdw_type.h>
13 #include <sound/sdca_function.h>
14 #include <sound/soc_sdw_utils.h>
15 
16 static const struct snd_soc_dapm_widget generic_dmic_widgets[] = {
17 	SND_SOC_DAPM_MIC("DMIC", NULL),
18 };
19 
20 static const struct snd_soc_dapm_widget generic_jack_widgets[] = {
21 	SND_SOC_DAPM_HP("Headphone", NULL),
22 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
23 };
24 
25 static const struct snd_kcontrol_new generic_jack_controls[] = {
26 	SOC_DAPM_PIN_SWITCH("Headphone"),
27 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
28 };
29 
30 static const struct snd_soc_dapm_widget generic_spk_widgets[] = {
31 	SND_SOC_DAPM_SPK("Speaker", NULL),
32 };
33 
34 static const struct snd_kcontrol_new generic_spk_controls[] = {
35 	SOC_DAPM_PIN_SWITCH("Speaker"),
36 };
37 
38 static const struct snd_soc_dapm_widget lr_spk_widgets[] = {
39 	SND_SOC_DAPM_SPK("Left Spk", NULL),
40 	SND_SOC_DAPM_SPK("Right Spk", NULL),
41 };
42 
43 static const struct snd_soc_dapm_widget lr_4spk_widgets[] = {
44 	SND_SOC_DAPM_SPK("Left Spk", NULL),
45 	SND_SOC_DAPM_SPK("Right Spk", NULL),
46 	SND_SOC_DAPM_SPK("Left Spk2", NULL),
47 	SND_SOC_DAPM_SPK("Right Spk2", NULL),
48 };
49 
50 static const struct snd_kcontrol_new lr_spk_controls[] = {
51 	SOC_DAPM_PIN_SWITCH("Left Spk"),
52 	SOC_DAPM_PIN_SWITCH("Right Spk"),
53 };
54 
55 static const struct snd_kcontrol_new lr_4spk_controls[] = {
56 	SOC_DAPM_PIN_SWITCH("Left Spk"),
57 	SOC_DAPM_PIN_SWITCH("Right Spk"),
58 	SOC_DAPM_PIN_SWITCH("Left Spk2"),
59 	SOC_DAPM_PIN_SWITCH("Right Spk2"),
60 };
61 
62 static const struct snd_soc_dapm_widget rt700_widgets[] = {
63 	SND_SOC_DAPM_HP("Headphones", NULL),
64 	SND_SOC_DAPM_MIC("AMIC", NULL),
65 	SND_SOC_DAPM_SPK("Speaker", NULL),
66 };
67 
68 static const struct snd_kcontrol_new rt700_controls[] = {
69 	SOC_DAPM_PIN_SWITCH("Headphones"),
70 	SOC_DAPM_PIN_SWITCH("AMIC"),
71 	SOC_DAPM_PIN_SWITCH("Speaker"),
72 };
73 
74 struct asoc_sdw_codec_info codec_info_list[] = {
75 	{
76 		.vendor_id = 0x0102,
77 		.part_id = 0x5572,
78 		.name_prefix = "tac5572",
79 		.dais = {
80 			{
81 				/* speaker */
82 				.direction = {true, false},
83 				.dai_name = "tac5xx2-aif1",
84 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
85 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
86 				.init = asoc_sdw_ti_amp_init,
87 				.rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
88 				.controls = lr_spk_controls,
89 				.num_controls = ARRAY_SIZE(lr_spk_controls),
90 				.widgets = lr_spk_widgets,
91 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
92 			},
93 			{
94 				/* mic */
95 				.direction = {false, true},
96 				.dai_name = "tac5xx2-aif2",
97 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
98 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
99 				.rtd_init = asoc_sdw_ti_dmic_rtd_init,
100 			},
101 			{
102 				/* UAJ */
103 				.direction = {true, true},
104 				.dai_name = "tac5xx2-aif3",
105 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
106 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
107 				.controls = generic_jack_controls,
108 				.num_controls = ARRAY_SIZE(generic_jack_controls),
109 				.widgets = generic_jack_widgets,
110 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
111 				.rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
112 			},
113 		},
114 		.dai_num = 3,
115 	},
116 	{
117 		.vendor_id = 0x0102,
118 		.part_id = 0x5672,
119 		.name_prefix = "tac5672",
120 		.dais = {
121 			{
122 				/* speaker with IV sense feedback */
123 				.direction = {true, true},
124 				.dai_name = "tac5xx2-aif1",
125 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
126 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
127 				.init = asoc_sdw_ti_amp_init,
128 				.rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
129 				.controls = lr_spk_controls,
130 				.num_controls = ARRAY_SIZE(lr_spk_controls),
131 				.widgets = lr_spk_widgets,
132 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
133 			},
134 			{
135 				/* mic */
136 				.direction = {false, true},
137 				.dai_name = "tac5xx2-aif2",
138 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
139 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
140 				.rtd_init = asoc_sdw_ti_dmic_rtd_init,
141 			},
142 			{
143 				/* UAJ */
144 				.direction = {true, true},
145 				.dai_name = "tac5xx2-aif3",
146 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
147 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
148 				.controls = generic_jack_controls,
149 				.num_controls = ARRAY_SIZE(generic_jack_controls),
150 				.widgets = generic_jack_widgets,
151 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
152 				.rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
153 			},
154 		},
155 		.dai_num = 3,
156 	},
157 	{
158 		.vendor_id = 0x0102,
159 		.part_id = 0x5682,
160 		.name_prefix = "tac5682",
161 		.dais = {
162 			{
163 				/* speaker with echo reference feedback */
164 				.direction = {true, true},
165 				.dai_name = "tac5xx2-aif1",
166 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
167 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
168 				.init = asoc_sdw_ti_amp_init,
169 				.rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
170 				.controls = lr_spk_controls,
171 				.num_controls = ARRAY_SIZE(lr_spk_controls),
172 				.widgets = lr_spk_widgets,
173 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
174 			},
175 			{
176 				/* mic */
177 				.direction = {false, true},
178 				.dai_name = "tac5xx2-aif2",
179 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
180 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
181 				.rtd_init = asoc_sdw_ti_dmic_rtd_init,
182 			},
183 			{
184 				/* UAJ */
185 				.direction = {true, true},
186 				.dai_name = "tac5xx2-aif3",
187 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
188 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
189 				.controls = generic_jack_controls,
190 				.num_controls = ARRAY_SIZE(generic_jack_controls),
191 				.widgets = generic_jack_widgets,
192 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
193 				.rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
194 			},
195 		},
196 		.dai_num = 3,
197 	},
198 	{
199 		.vendor_id = 0x0102,
200 		.part_id = 0x2883,
201 		.name_prefix = "tas2883",
202 		.dais = {
203 			{
204 				.direction = {true, false},
205 				.dai_name = "tac5xx2-aif1",
206 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
207 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
208 				.init = asoc_sdw_ti_amp_init,
209 				.rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
210 				.controls = lr_spk_controls,
211 				.num_controls = ARRAY_SIZE(lr_spk_controls),
212 				.widgets = lr_spk_widgets,
213 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
214 			},
215 			{
216 				/* mic */
217 				.direction = {false, true},
218 				.dai_name = "tac5xx2-aif2",
219 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
220 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
221 				.rtd_init = asoc_sdw_ti_dmic_rtd_init,
222 			},
223 		},
224 		.dai_num = 2,
225 	},
226 	{
227 		.vendor_id = 0x0102,
228 		.part_id = 0x0000, /* TAS2783A */
229 		.name_prefix = "tas2783",
230 		.is_amp = true,
231 		.dais = {
232 			{
233 				.direction = {true, true},
234 				.dai_name = "tas2783-codec",
235 				.component_name = "tas2783",
236 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
237 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
238 				.init = asoc_sdw_ti_amp_init,
239 				.rtd_init = asoc_sdw_ti_spk_rtd_init,
240 				.controls = lr_4spk_controls,
241 				.num_controls = ARRAY_SIZE(lr_4spk_controls),
242 				.widgets = lr_4spk_widgets,
243 				.num_widgets = ARRAY_SIZE(lr_4spk_widgets),
244 			},
245 		},
246 		.dai_num = 1,
247 	},
248 	{
249 		.vendor_id = 0x025d,
250 		.part_id = 0x700,
251 		.name_prefix = "rt700",
252 		.dais = {
253 			{
254 				.direction = {true, true},
255 				.dai_name = "rt700-aif1",
256 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
257 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
258 				.rtd_init = asoc_sdw_rt700_rtd_init,
259 				.controls = rt700_controls,
260 				.num_controls = ARRAY_SIZE(rt700_controls),
261 				.widgets = rt700_widgets,
262 				.num_widgets = ARRAY_SIZE(rt700_widgets),
263 			},
264 		},
265 		.dai_num = 1,
266 	},
267 	{
268 		.vendor_id = 0x025d,
269 		.part_id = 0x711,
270 		.name_prefix = "rt711",
271 		.version_id = 3,
272 		.dais = {
273 			{
274 				.direction = {true, true},
275 				.dai_name = "rt711-sdca-aif1",
276 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
277 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
278 				.init = asoc_sdw_rt_sdca_jack_init,
279 				.exit = asoc_sdw_rt_sdca_jack_exit,
280 				.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
281 				.controls = generic_jack_controls,
282 				.num_controls = ARRAY_SIZE(generic_jack_controls),
283 				.widgets = generic_jack_widgets,
284 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
285 			},
286 		},
287 		.dai_num = 1,
288 	},
289 	{
290 		.vendor_id = 0x025d,
291 		.part_id = 0x711,
292 		.name_prefix = "rt711",
293 		.version_id = 2,
294 		.dais = {
295 			{
296 				.direction = {true, true},
297 				.dai_name = "rt711-aif1",
298 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
299 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
300 				.init = asoc_sdw_rt711_init,
301 				.exit = asoc_sdw_rt711_exit,
302 				.rtd_init = asoc_sdw_rt711_rtd_init,
303 				.controls = generic_jack_controls,
304 				.num_controls = ARRAY_SIZE(generic_jack_controls),
305 				.widgets = generic_jack_widgets,
306 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
307 			},
308 		},
309 		.dai_num = 1,
310 	},
311 	{
312 		.vendor_id = 0x025d,
313 		.part_id = 0x712,
314 		.name_prefix = "rt712",
315 		.version_id = 3,
316 		.dais =	{
317 			{
318 				.direction = {true, true},
319 				.dai_name = "rt712-sdca-aif1",
320 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
321 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
322 				.init = asoc_sdw_rt_sdca_jack_init,
323 				.exit = asoc_sdw_rt_sdca_jack_exit,
324 				.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
325 				.controls = generic_jack_controls,
326 				.num_controls = ARRAY_SIZE(generic_jack_controls),
327 				.widgets = generic_jack_widgets,
328 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
329 			},
330 			{
331 				.direction = {true, false},
332 				.dai_name = "rt712-sdca-aif2",
333 				.component_name = "rt712",
334 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
335 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
336 				.init = asoc_sdw_rt_amp_init,
337 				.exit = asoc_sdw_rt_amp_exit,
338 				.rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
339 				.controls = generic_spk_controls,
340 				.num_controls = ARRAY_SIZE(generic_spk_controls),
341 				.widgets = generic_spk_widgets,
342 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
343 			},
344 			{
345 				.direction = {false, true},
346 				.dai_name = "rt712-sdca-aif3",
347 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
348 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
349 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
350 				.quirk = SOC_SDW_CODEC_MIC,
351 				.quirk_exclude = true,
352 			},
353 		},
354 		.dai_num = 3,
355 	},
356 	{
357 		.vendor_id = 0x025d,
358 		.part_id = 0x1712,
359 		.name_prefix = "rt712-dmic",
360 		.version_id = 3,
361 		.dais =	{
362 			{
363 				.direction = {false, true},
364 				.dai_name = "rt712-sdca-dmic-aif1",
365 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
366 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
367 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
368 			},
369 		},
370 		.dai_num = 1,
371 	},
372 	{
373 		.vendor_id = 0x025d,
374 		.part_id = 0x713,
375 		.name_prefix = "rt713",
376 		.version_id = 3,
377 		.dais =	{
378 			{
379 				.direction = {true, true},
380 				.dai_name = "rt712-sdca-aif1",
381 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
382 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
383 				.init = asoc_sdw_rt_sdca_jack_init,
384 				.exit = asoc_sdw_rt_sdca_jack_exit,
385 				.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
386 				.controls = generic_jack_controls,
387 				.num_controls = ARRAY_SIZE(generic_jack_controls),
388 				.widgets = generic_jack_widgets,
389 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
390 			},
391 			{
392 				.direction = {false, true},
393 				.dai_name = "rt712-sdca-aif3",
394 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
395 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
396 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
397 			},
398 		},
399 		.dai_num = 2,
400 	},
401 	{
402 		.vendor_id = 0x025d,
403 		.part_id = 0x1713,
404 		.name_prefix = "rt713-dmic",
405 		.version_id = 3,
406 		.dais =	{
407 			{
408 				.direction = {false, true},
409 				.dai_name = "rt712-sdca-dmic-aif1",
410 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
411 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
412 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
413 			},
414 		},
415 		.dai_num = 1,
416 	},
417 	{
418 		.vendor_id = 0x025d,
419 		.part_id = 0x1308,
420 		.name_prefix = "rt1308",
421 		.acpi_id = "10EC1308",
422 		.is_amp = true,
423 		.dais = {
424 			{
425 				.direction = {true, false},
426 				.dai_name = "rt1308-aif",
427 				.component_name = "rt1308",
428 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
429 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
430 				.init = asoc_sdw_rt_amp_init,
431 				.exit = asoc_sdw_rt_amp_exit,
432 				.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
433 				.controls = generic_spk_controls,
434 				.num_controls = ARRAY_SIZE(generic_spk_controls),
435 				.widgets = generic_spk_widgets,
436 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
437 			},
438 		},
439 		.dai_num = 1,
440 		.ops = &soc_sdw_rt1308_i2s_ops,
441 	},
442 	{
443 		.vendor_id = 0x025d,
444 		.part_id = 0x1316,
445 		.name_prefix = "rt1316",
446 		.is_amp = true,
447 		.dais = {
448 			{
449 				.direction = {true, true},
450 				.dai_name = "rt1316-aif",
451 				.component_name = "rt1316",
452 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
453 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
454 				.init = asoc_sdw_rt_amp_init,
455 				.exit = asoc_sdw_rt_amp_exit,
456 				.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
457 				.controls = generic_spk_controls,
458 				.num_controls = ARRAY_SIZE(generic_spk_controls),
459 				.widgets = generic_spk_widgets,
460 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
461 			},
462 		},
463 		.dai_num = 1,
464 	},
465 	{
466 		.vendor_id = 0x025d,
467 		.part_id = 0x1318,
468 		.name_prefix = "rt1318",
469 		.is_amp = true,
470 		.dais = {
471 			{
472 				.direction = {true, true},
473 				.dai_name = "rt1318-aif",
474 				.component_name = "rt1318",
475 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
476 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
477 				.init = asoc_sdw_rt_amp_init,
478 				.exit = asoc_sdw_rt_amp_exit,
479 				.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
480 				.controls = generic_spk_controls,
481 				.num_controls = ARRAY_SIZE(generic_spk_controls),
482 				.widgets = generic_spk_widgets,
483 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
484 			},
485 		},
486 		.dai_num = 1,
487 	},
488 	{
489 		.vendor_id = 0x025d,
490 		.part_id = 0x1320,
491 		.name_prefix = "rt1320",
492 		.is_amp = true,
493 		.dais = {
494 			{
495 				.direction = {true, false},
496 				.dai_name = "rt1320-aif1",
497 				.component_name = "rt1320",
498 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
499 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
500 				.init = asoc_sdw_rt_amp_init,
501 				.exit = asoc_sdw_rt_amp_exit,
502 				.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
503 				.controls = generic_spk_controls,
504 				.num_controls = ARRAY_SIZE(generic_spk_controls),
505 				.widgets = generic_spk_widgets,
506 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
507 			},
508 			{
509 				.direction = {false, true},
510 				.dai_name = "rt1320-aif2",
511 				.component_name = "rt1320",
512 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
513 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
514 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
515 				.widgets = generic_dmic_widgets,
516 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
517 			},
518 		},
519 		.dai_num = 2,
520 	},
521 	{
522 		.vendor_id = 0x025d,
523 		.part_id = 0x1321,
524 		.name_prefix = "rt1320",
525 		.is_amp = true,
526 		.dais = {
527 			{
528 				.direction = {true, false},
529 				.dai_name = "rt1320-aif1",
530 				.component_name = "rt1320",
531 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
532 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
533 				.init = asoc_sdw_rt_amp_init,
534 				.exit = asoc_sdw_rt_amp_exit,
535 				.rtd_init = asoc_sdw_rt_amp_spk_rtd_init,
536 				.controls = generic_spk_controls,
537 				.num_controls = ARRAY_SIZE(generic_spk_controls),
538 				.widgets = generic_spk_widgets,
539 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
540 			},
541 			{
542 				.direction = {false, true},
543 				.dai_name = "rt1320-aif2",
544 				.component_name = "rt1320",
545 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
546 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
547 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
548 				.widgets = generic_dmic_widgets,
549 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
550 			},
551 		},
552 		.dai_num = 2,
553 	},
554 	{
555 		.vendor_id = 0x025d,
556 		.part_id = 0x714,
557 		.name_prefix = "rt714",
558 		.version_id = 3,
559 		.ignore_internal_dmic = true,
560 		.dais = {
561 			{
562 				.direction = {false, true},
563 				.dai_name = "rt715-sdca-aif2",
564 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
565 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
566 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
567 			},
568 		},
569 		.dai_num = 1,
570 	},
571 	{
572 		.vendor_id = 0x025d,
573 		.part_id = 0x715,
574 		.name_prefix = "rt715",
575 		.version_id = 3,
576 		.ignore_internal_dmic = true,
577 		.dais = {
578 			{
579 				.direction = {false, true},
580 				.dai_name = "rt715-sdca-aif2",
581 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
582 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
583 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
584 			},
585 		},
586 		.dai_num = 1,
587 	},
588 	{
589 		.vendor_id = 0x025d,
590 		.part_id = 0x714,
591 		.name_prefix = "rt714",
592 		.version_id = 2,
593 		.ignore_internal_dmic = true,
594 		.dais = {
595 			{
596 				.direction = {false, true},
597 				.dai_name = "rt715-aif2",
598 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
599 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
600 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
601 			},
602 		},
603 		.dai_num = 1,
604 	},
605 	{
606 		.vendor_id = 0x025d,
607 		.part_id = 0x715,
608 		.name_prefix = "rt715",
609 		.version_id = 2,
610 		.ignore_internal_dmic = true,
611 		.dais = {
612 			{
613 				.direction = {false, true},
614 				.dai_name = "rt715-aif2",
615 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
616 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
617 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
618 			},
619 		},
620 		.dai_num = 1,
621 	},
622 	{
623 		.vendor_id = 0x025d,
624 		.part_id = 0x721,
625 		.name_prefix = "rt721",
626 		.version_id = 3,
627 		.dais = {
628 			{
629 				.direction = {true, true},
630 				.dai_name = "rt721-sdca-aif1",
631 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
632 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
633 				.init = asoc_sdw_rt_sdca_jack_init,
634 				.exit = asoc_sdw_rt_sdca_jack_exit,
635 				.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
636 				.controls = generic_jack_controls,
637 				.num_controls = ARRAY_SIZE(generic_jack_controls),
638 				.widgets = generic_jack_widgets,
639 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
640 			},
641 			{
642 				.direction = {true, false},
643 				.dai_name = "rt721-sdca-aif2",
644 				.component_name = "rt721",
645 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
646 				/* No feedback capability is provided by rt721-sdca codec driver*/
647 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
648 				.init = asoc_sdw_rt_amp_init,
649 				.exit = asoc_sdw_rt_amp_exit,
650 				.rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
651 				.controls = generic_spk_controls,
652 				.num_controls = ARRAY_SIZE(generic_spk_controls),
653 				.widgets = generic_spk_widgets,
654 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
655 			},
656 			{
657 				.direction = {false, true},
658 				.dai_name = "rt721-sdca-aif3",
659 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
660 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
661 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
662 				.quirk = SOC_SDW_CODEC_MIC,
663 				.quirk_exclude = true,
664 			},
665 		},
666 		.dai_num = 3,
667 	},
668 	{
669 		.vendor_id = 0x025d,
670 		.part_id = 0x722,
671 		.name_prefix = "rt722",
672 		.version_id = 3,
673 		.dais = {
674 			{
675 				.direction = {true, true},
676 				.dai_name = "rt722-sdca-aif1",
677 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
678 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
679 				.init = asoc_sdw_rt_sdca_jack_init,
680 				.exit = asoc_sdw_rt_sdca_jack_exit,
681 				.rtd_init = asoc_sdw_rt_sdca_jack_rtd_init,
682 				.controls = generic_jack_controls,
683 				.num_controls = ARRAY_SIZE(generic_jack_controls),
684 				.widgets = generic_jack_widgets,
685 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
686 			},
687 			{
688 				.direction = {true, false},
689 				.dai_name = "rt722-sdca-aif2",
690 				.component_name = "rt722",
691 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
692 				/* No feedback capability is provided by rt722-sdca codec driver*/
693 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
694 				.init = asoc_sdw_rt_amp_init,
695 				.exit = asoc_sdw_rt_amp_exit,
696 				.rtd_init = asoc_sdw_rt_mf_sdca_spk_rtd_init,
697 				.controls = generic_spk_controls,
698 				.num_controls = ARRAY_SIZE(generic_spk_controls),
699 				.widgets = generic_spk_widgets,
700 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
701 				.quirk = SOC_SDW_CODEC_SPKR,
702 				.quirk_exclude = true,
703 			},
704 			{
705 				.direction = {false, true},
706 				.dai_name = "rt722-sdca-aif3",
707 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
708 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
709 				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
710 				.quirk = SOC_SDW_CODEC_MIC,
711 				.quirk_exclude = true,
712 			},
713 		},
714 		.dai_num = 3,
715 	},
716 	{
717 		.vendor_id = 0x019f,
718 		.part_id = 0x8373,
719 		.name_prefix = "Left",
720 		.is_amp = true,
721 		.dais = {
722 			{
723 				.direction = {true, true},
724 				.dai_name = "max98373-aif1",
725 				.component_name = "mx8373",
726 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
727 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
728 				.init = asoc_sdw_maxim_init,
729 				.rtd_init = asoc_sdw_maxim_spk_rtd_init,
730 				.controls = lr_spk_controls,
731 				.num_controls = ARRAY_SIZE(lr_spk_controls),
732 				.widgets = lr_spk_widgets,
733 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
734 			},
735 		},
736 		.dai_num = 1,
737 	},
738 	{
739 		.vendor_id = 0x019f,
740 		.part_id = 0x8363,
741 		.name_prefix = "Left",
742 		.is_amp = true,
743 		.dais = {
744 			{
745 				.direction = {true, false},
746 				.dai_name = "max98363-aif1",
747 				.component_name = "mx8363",
748 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
749 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
750 				.init = asoc_sdw_maxim_init,
751 				.rtd_init = asoc_sdw_maxim_spk_rtd_init,
752 				.controls = lr_spk_controls,
753 				.num_controls = ARRAY_SIZE(lr_spk_controls),
754 				.widgets = lr_spk_widgets,
755 				.num_widgets = ARRAY_SIZE(lr_spk_widgets),
756 			},
757 		},
758 		.dai_num = 1,
759 	},
760 	{
761 		.vendor_id = 0x025d,
762 		.part_id = 0x5682,
763 		.name_prefix = "rt5682",
764 		.dais = {
765 			{
766 				.direction = {true, true},
767 				.dai_name = "rt5682-sdw",
768 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
769 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
770 				.rtd_init = asoc_sdw_rt5682_rtd_init,
771 				.controls = generic_jack_controls,
772 				.num_controls = ARRAY_SIZE(generic_jack_controls),
773 				.widgets = generic_jack_widgets,
774 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
775 			},
776 		},
777 		.dai_num = 1,
778 	},
779 	{
780 		.vendor_id = 0x01fa,
781 		.part_id = 0x3556,
782 		.name_prefix = "AMP",
783 		.is_amp = true,
784 		.dais = {
785 			{
786 				.direction = {true, false},
787 				.dai_name = "cs35l56-sdw1",
788 				.component_name = "cs35l56",
789 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
790 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
791 				.init = asoc_sdw_cs_amp_init,
792 				.rtd_init = asoc_sdw_cs_spk_rtd_init,
793 				.controls = generic_spk_controls,
794 				.num_controls = ARRAY_SIZE(generic_spk_controls),
795 				.widgets = generic_spk_widgets,
796 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
797 			},
798 			{
799 				.direction = {false, true},
800 				.dai_name = "cs35l56-sdw1c",
801 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
802 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
803 				.rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
804 			},
805 		},
806 		.dai_num = 2,
807 	},
808 	{
809 		.vendor_id = 0x01fa,
810 		.part_id = 0x3557,
811 		.name_prefix = "AMP",
812 		.is_amp = true,
813 		.dais = {
814 			{
815 				.direction = {true, false},
816 				.dai_name = "cs35l56-sdw1",
817 				.component_name = "cs35l56",
818 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
819 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
820 				.init = asoc_sdw_cs_amp_init,
821 				.rtd_init = asoc_sdw_cs_spk_rtd_init,
822 				.controls = generic_spk_controls,
823 				.num_controls = ARRAY_SIZE(generic_spk_controls),
824 				.widgets = generic_spk_widgets,
825 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
826 			},
827 			{
828 				.direction = {false, true},
829 				.dai_name = "cs35l56-sdw1c",
830 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
831 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
832 				.rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
833 			},
834 		},
835 		.dai_num = 2,
836 	},
837 	{
838 		.vendor_id = 0x01fa,
839 		.part_id = 0x3563,
840 		.name_prefix = "AMP",
841 		.is_amp = true,
842 		.dais = {
843 			{
844 				.direction = {true, false},
845 				.dai_name = "cs35l56-sdw1",
846 				.component_name = "cs35l56",
847 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
848 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
849 				.init = asoc_sdw_cs_amp_init,
850 				.rtd_init = asoc_sdw_cs_spk_rtd_init,
851 				.controls = generic_spk_controls,
852 				.num_controls = ARRAY_SIZE(generic_spk_controls),
853 				.widgets = generic_spk_widgets,
854 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
855 			},
856 			{
857 				.direction = {false, true},
858 				.dai_name = "cs35l56-sdw1c",
859 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
860 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
861 				.rtd_init = asoc_sdw_cs_spk_feedback_rtd_init,
862 			},
863 		},
864 		.dai_num = 2,
865 	},
866 	{
867 		.vendor_id = 0x01fa,
868 		.part_id = 0x4242,
869 		.name_prefix = "cs42l42",
870 		.dais = {
871 			{
872 				.direction = {true, true},
873 				.dai_name = "cs42l42-sdw",
874 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
875 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
876 				.rtd_init = asoc_sdw_cs42l42_rtd_init,
877 				.controls = generic_jack_controls,
878 				.num_controls = ARRAY_SIZE(generic_jack_controls),
879 				.widgets = generic_jack_widgets,
880 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
881 			},
882 		},
883 		.dai_num = 1,
884 	},
885 	{
886 		.vendor_id = 0x01fa,
887 		.part_id = 0x4243,
888 		.name_prefix = "cs42l43",
889 		.count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
890 		.add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
891 		.dais = {
892 			{
893 				.direction = {true, false},
894 				.codec_name = "cs42l43-codec",
895 				.dai_name = "cs42l43-dp5",
896 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
897 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
898 				.rtd_init = asoc_sdw_cs42l43_hs_rtd_init,
899 				.controls = generic_jack_controls,
900 				.num_controls = ARRAY_SIZE(generic_jack_controls),
901 				.widgets = generic_jack_widgets,
902 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
903 			},
904 			{
905 				.direction = {false, true},
906 				.codec_name = "cs42l43-codec",
907 				.dai_name = "cs42l43-dp1",
908 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
909 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
910 				.rtd_init = asoc_sdw_cs42l43_dmic_rtd_init,
911 				.widgets = generic_dmic_widgets,
912 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
913 				.quirk = SOC_SDW_CODEC_MIC,
914 				.quirk_exclude = true,
915 			},
916 			{
917 				.direction = {false, true},
918 				.codec_name = "cs42l43-codec",
919 				.dai_name = "cs42l43-dp2",
920 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
921 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
922 			},
923 			{
924 				.direction = {true, false},
925 				.codec_name = "cs42l43-codec",
926 				.component_name = "cs42l43-spk",
927 				.dai_name = "cs42l43-dp6",
928 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
929 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
930 				.init = asoc_sdw_cs42l43_spk_init,
931 				.rtd_init = asoc_sdw_cs42l43_spk_rtd_init,
932 				.controls = generic_spk_controls,
933 				.num_controls = ARRAY_SIZE(generic_spk_controls),
934 				.widgets = generic_spk_widgets,
935 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
936 				.quirk = SOC_SDW_CODEC_SPKR | SOC_SDW_SIDECAR_AMPS,
937 			},
938 		},
939 		.dai_num = 4,
940 	},
941 	{
942 		.vendor_id = 0x01fa,
943 		.part_id = 0x2A3B,
944 		.name_prefix = "cs42l43",
945 		.count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
946 		.add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
947 		.dais = {
948 			{
949 				.direction = {true, false},
950 				.codec_name = "cs42l43-codec",
951 				.dai_name = "cs42l43-dp5",
952 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
953 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
954 				.rtd_init = asoc_sdw_cs42l43_hs_rtd_init,
955 				.controls = generic_jack_controls,
956 				.num_controls = ARRAY_SIZE(generic_jack_controls),
957 				.widgets = generic_jack_widgets,
958 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
959 			},
960 			{
961 				.direction = {false, true},
962 				.codec_name = "cs42l43-codec",
963 				.dai_name = "cs42l43-dp1",
964 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
965 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
966 				.rtd_init = asoc_sdw_cs42l43_dmic_rtd_init,
967 				.widgets = generic_dmic_widgets,
968 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
969 				.quirk = SOC_SDW_CODEC_MIC,
970 				.quirk_exclude = true,
971 			},
972 			{
973 				.direction = {false, true},
974 				.codec_name = "cs42l43-codec",
975 				.dai_name = "cs42l43-dp2",
976 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
977 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
978 			},
979 			{
980 				.direction = {true, false},
981 				.codec_name = "cs42l43-codec",
982 				.component_name = "cs42l43-spk",
983 				.dai_name = "cs42l43-dp6",
984 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
985 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
986 				.init = asoc_sdw_cs42l43_spk_init,
987 				.rtd_init = asoc_sdw_cs42l43_spk_rtd_init,
988 				.controls = generic_spk_controls,
989 				.num_controls = ARRAY_SIZE(generic_spk_controls),
990 				.widgets = generic_spk_widgets,
991 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
992 				.quirk = SOC_SDW_CODEC_SPKR | SOC_SDW_SIDECAR_AMPS,
993 			},
994 		},
995 		.dai_num = 4,
996 	},
997 	{
998 		.vendor_id = 0x01fa,
999 		.part_id = 0x4245,
1000 		.name_prefix = "cs42l45",
1001 		.dais = {
1002 			{
1003 				.direction = {true, false},
1004 				.codec_name = "snd_soc_sdca.UAJ",
1005 				.dai_name = "IT 41",
1006 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1007 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1008 				.rtd_init = asoc_sdw_cs42l45_hs_rtd_init,
1009 			},
1010 			{
1011 				.direction = {false, true},
1012 				.codec_name = "snd_soc_sdca.SmartMic",
1013 				.dai_name = "OT 113",
1014 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1015 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1016 				.rtd_init = asoc_sdw_cs42l45_dmic_rtd_init,
1017 			},
1018 			{
1019 				.direction = {false, true},
1020 				.codec_name = "snd_soc_sdca.UAJ",
1021 				.dai_name = "OT 36",
1022 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1023 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1024 			},
1025 		},
1026 		.dai_num = 3,
1027 		.auxs = {
1028 			{
1029 				.codec_name = "snd_soc_sdca.HID",
1030 			},
1031 		},
1032 		.aux_num = 1,
1033 	},
1034 	{
1035 		.vendor_id = 0x01fa,
1036 		.part_id = 0x4249,
1037 		.name_prefix = "cs42l45", /* Use same user-space as cs42l45 */
1038 		.dais = {
1039 			{
1040 				.direction = {true, false},
1041 				.codec_name = "snd_soc_sdca.UAJ",
1042 				.dai_name = "IT 41",
1043 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1044 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1045 				.rtd_init = asoc_sdw_cs42l45_hs_rtd_init,
1046 			},
1047 			{
1048 				.direction = {false, true},
1049 				.codec_name = "snd_soc_sdca.SmartMic",
1050 				.dai_name = "OT 113",
1051 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1052 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1053 				.rtd_init = asoc_sdw_cs42l45_dmic_rtd_init,
1054 			},
1055 			{
1056 				.direction = {false, true},
1057 				.codec_name = "snd_soc_sdca.UAJ",
1058 				.dai_name = "OT 36",
1059 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1060 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1061 			},
1062 		},
1063 		.dai_num = 3,
1064 		.auxs = {
1065 			{
1066 				.codec_name = "snd_soc_sdca.HID",
1067 			},
1068 		},
1069 		.aux_num = 1,
1070 	},
1071 	{
1072 		.vendor_id = 0x01fa,
1073 		.part_id = 0x4747,
1074 		.name_prefix = "cs47l47",
1075 		.dais = {
1076 			{
1077 				.direction = {true, false},
1078 				.codec_name = "snd_soc_sdca.UAJ",
1079 				.dai_name = "IT 41",
1080 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1081 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1082 				.rtd_init = asoc_sdw_cs47l47_hs_rtd_init,
1083 			},
1084 			{
1085 				.direction = {false, true},
1086 				.codec_name = "snd_soc_sdca.SmartMic",
1087 				.dai_name = "OT 113",
1088 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1089 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1090 				.rtd_init = asoc_sdw_cs47l47_dmic_rtd_init,
1091 			},
1092 			{
1093 				.direction = {false, true},
1094 				.codec_name = "snd_soc_sdca.UAJ",
1095 				.dai_name = "OT 36",
1096 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1097 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1098 			},
1099 		},
1100 		.dai_num = 3,
1101 		.auxs = {
1102 			{
1103 				.codec_name = "snd_soc_sdca.HID",
1104 			},
1105 		},
1106 		.aux_num = 1,
1107 	},
1108 	{
1109 		.vendor_id = 0x04b3,
1110 		.part_id = 0x9356,
1111 		.name_prefix = "es9356",
1112 		.version_id = 3,
1113 		.dais = {
1114 			{
1115 				.direction = {true, false},
1116 				.dai_name = "es9356-sdp-aif1",
1117 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1118 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1119 				.init = asoc_sdw_es9356_init,
1120 				.exit = asoc_sdw_es9356_exit,
1121 				.rtd_init = asoc_sdw_es9356_rtd_init,
1122 				.controls = generic_jack_controls,
1123 				.num_controls = ARRAY_SIZE(generic_jack_controls),
1124 				.widgets = generic_jack_widgets,
1125 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
1126 			},
1127 			{
1128 				.direction = {false, true},
1129 				.dai_name = "es9356-sdp-aif4",
1130 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1131 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1132 				.rtd_init = asoc_sdw_es9356_dmic_rtd_init,
1133 				.widgets = generic_dmic_widgets,
1134 				.num_widgets = ARRAY_SIZE(generic_dmic_widgets),
1135 			},
1136 			{
1137 				.direction = {false, true},
1138 				.dai_name = "es9356-sdp-aif2",
1139 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1140 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1141 			},
1142 			{
1143 				.direction = {true, false},
1144 				.dai_name = "es9356-sdp-aif3",
1145 				.component_name = "es9356",
1146 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
1147 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1148 				.init = asoc_sdw_es9356_amp_init,
1149 				.rtd_init = asoc_sdw_es9356_spk_rtd_init,
1150 				.controls = generic_spk_controls,
1151 				.num_controls = ARRAY_SIZE(generic_spk_controls),
1152 				.widgets = generic_spk_widgets,
1153 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
1154 			},
1155 		},
1156 		.dai_num = 4,
1157 	},
1158 	{
1159 		.vendor_id = 0x0105,
1160 		.part_id = 0xaaaa, /* generic codec mockup */
1161 		.name_prefix = "sdw_mockup_mmulti-function",
1162 		.version_id = 0,
1163 		.dais = {
1164 			{
1165 				.direction = {true, true},
1166 				.dai_name = "sdw-mockup-aif1",
1167 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1168 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1169 			},
1170 			{
1171 				.direction = {true, false},
1172 				.dai_name = "sdw-mockup-aif1",
1173 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
1174 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
1175 			},
1176 			{
1177 				.direction = {false, true},
1178 				.dai_name = "sdw-mockup-aif1",
1179 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1180 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1181 			},
1182 		},
1183 		.dai_num = 3,
1184 	},
1185 	{
1186 		.vendor_id = 0x0105,
1187 		.part_id = 0xaa55, /* headset codec mockup */
1188 		.name_prefix = "sdw_mockup_headset0",
1189 		.version_id = 0,
1190 		.dais = {
1191 			{
1192 				.direction = {true, true},
1193 				.dai_name = "sdw-mockup-aif1",
1194 				.dai_type = SOC_SDW_DAI_TYPE_JACK,
1195 				.dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
1196 			},
1197 		},
1198 		.dai_num = 1,
1199 	},
1200 	{
1201 		.vendor_id = 0x0105,
1202 		.part_id = 0x55aa, /* amplifier mockup */
1203 		.name_prefix = "sdw_mockup_amp1",
1204 		.is_amp = true,
1205 		.version_id = 0,
1206 		.dais = {
1207 			{
1208 				.direction = {true, true},
1209 				.dai_name = "sdw-mockup-aif1",
1210 				.dai_type = SOC_SDW_DAI_TYPE_AMP,
1211 				.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
1212 			},
1213 		},
1214 		.dai_num = 1,
1215 	},
1216 	{
1217 		.vendor_id = 0x0105,
1218 		.part_id = 0x5555,
1219 		.name_prefix = "sdw_mockup_mic0",
1220 		.version_id = 0,
1221 		.dais = {
1222 			{
1223 				.dai_name = "sdw-mockup-aif1",
1224 				.direction = {false, true},
1225 				.dai_type = SOC_SDW_DAI_TYPE_MIC,
1226 				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
1227 			},
1228 		},
1229 		.dai_num = 1,
1230 	},
1231 };
1232 EXPORT_SYMBOL_NS(codec_info_list, "SND_SOC_SDW_UTILS");
1233 
1234 int asoc_sdw_get_codec_info_list_count(void)
1235 {
1236 	return ARRAY_SIZE(codec_info_list);
1237 };
1238 EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, "SND_SOC_SDW_UTILS");
1239 
1240 struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
1241 {
1242 	unsigned int vendor_id, part_id, sdw_version;
1243 	int i;
1244 
1245 	vendor_id = SDW_MFG_ID(adr);
1246 	part_id = SDW_PART_ID(adr);
1247 	sdw_version = SDW_VERSION(adr);
1248 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1249 		/*
1250 		 * A codec info is for all sdw version with the part id if
1251 		 * version_id is not specified in the codec info.
1252 		 */
1253 		if (part_id == codec_info_list[i].part_id &&
1254 		    vendor_id == codec_info_list[i].vendor_id &&
1255 		    (!codec_info_list[i].version_id ||
1256 		     sdw_version == codec_info_list[i].version_id))
1257 			return &codec_info_list[i];
1258 
1259 	return NULL;
1260 }
1261 EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, "SND_SOC_SDW_UTILS");
1262 
1263 static struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_sdw_id(const struct sdw_slave_id *id)
1264 {
1265 	int i;
1266 
1267 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1268 		if (id->part_id == codec_info_list[i].part_id &&
1269 		    id->mfg_id == codec_info_list[i].vendor_id &&
1270 		    (!codec_info_list[i].version_id ||
1271 		     id->sdw_version == codec_info_list[i].version_id))
1272 			return &codec_info_list[i];
1273 
1274 	return NULL;
1275 }
1276 
1277 struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id)
1278 {
1279 	int i;
1280 
1281 	if (!acpi_id[0])
1282 		return NULL;
1283 
1284 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1285 		if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN))
1286 			return &codec_info_list[i];
1287 
1288 	return NULL;
1289 }
1290 EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_acpi, "SND_SOC_SDW_UTILS");
1291 
1292 struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, int *dai_index)
1293 {
1294 	int i, j;
1295 
1296 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1297 		for (j = 0; j < codec_info_list[i].dai_num; j++) {
1298 			if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
1299 				*dai_index = j;
1300 				return &codec_info_list[i];
1301 			}
1302 		}
1303 	}
1304 
1305 	return NULL;
1306 }
1307 EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, "SND_SOC_SDW_UTILS");
1308 
1309 static int asoc_sdw_find_codec_info_dai_index(const struct asoc_sdw_codec_info *codec_info,
1310 					      const char *dai_name)
1311 {
1312 	int i;
1313 
1314 	for (i = 0; i < codec_info->dai_num; i++) {
1315 		if (!strcmp(codec_info->dais[i].dai_name, dai_name))
1316 			return i;
1317 	}
1318 
1319 	return -ENOENT;
1320 }
1321 
1322 int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
1323 {
1324 	struct snd_soc_card *card = rtd->card;
1325 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1326 	struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
1327 	struct asoc_sdw_codec_info *codec_info;
1328 	struct snd_soc_dai *dai;
1329 	struct sdw_slave *sdw_peripheral;
1330 	const char *spk_components = NULL;
1331 	int dai_index;
1332 	int ret;
1333 	int i;
1334 
1335 	for_each_rtd_codec_dais(rtd, i, dai) {
1336 		if (is_sdw_slave(dai->component->dev))
1337 			sdw_peripheral = dev_to_sdw_dev(dai->component->dev);
1338 		else if (dai->component->dev->parent && is_sdw_slave(dai->component->dev->parent))
1339 			sdw_peripheral = dev_to_sdw_dev(dai->component->dev->parent);
1340 		else
1341 			continue;
1342 
1343 		codec_info = asoc_sdw_find_codec_info_sdw_id(&sdw_peripheral->id);
1344 		if (!codec_info)
1345 			return -EINVAL;
1346 
1347 		dai_index = asoc_sdw_find_codec_info_dai_index(codec_info, dai->name);
1348 		WARN_ON(dai_index < 0);
1349 
1350 		/*
1351 		 * A codec dai can be connected to different dai links for capture and playback,
1352 		 * but we only need to call the rtd_init function once.
1353 		 * The rtd_init for each codec dai is independent. So, the order of rtd_init
1354 		 * doesn't matter.
1355 		 */
1356 		if (codec_info->dais[dai_index].rtd_init_done)
1357 			continue;
1358 
1359 		dev_dbg(card->dev, "%#x/%s initializing for %s/%s\n",
1360 			codec_info->part_id, codec_info->dais[dai_index].dai_name,
1361 			dai->component->name, dai->name);
1362 
1363 		/*
1364 		 * Add card controls and dapm widgets for the first codec dai.
1365 		 * The controls and widgets will be used for all codec dais.
1366 		 */
1367 
1368 		if (i > 0)
1369 			goto skip_add_controls_widgets;
1370 
1371 		if (codec_info->dais[dai_index].controls) {
1372 			ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
1373 							codec_info->dais[dai_index].num_controls);
1374 			if (ret) {
1375 				dev_err(card->dev, "%#x-%#x controls addition failed: %d\n",
1376 					codec_info->vendor_id, codec_info->part_id, ret);
1377 				return ret;
1378 			}
1379 		}
1380 		if (codec_info->dais[dai_index].widgets) {
1381 			ret = snd_soc_dapm_new_controls(dapm,
1382 							codec_info->dais[dai_index].widgets,
1383 							codec_info->dais[dai_index].num_widgets);
1384 			if (ret) {
1385 				dev_err(card->dev, "%#x-%#x widgets addition failed: %d\n",
1386 					codec_info->vendor_id, codec_info->part_id, ret);
1387 				return ret;
1388 			}
1389 		}
1390 
1391 skip_add_controls_widgets:
1392 		if (codec_info->dais[dai_index].rtd_init) {
1393 			ret = codec_info->dais[dai_index].rtd_init(rtd, dai);
1394 			if (ret)
1395 				return ret;
1396 		}
1397 
1398 		/* Generate the spk component string for card->components string */
1399 		if (codec_info->dais[dai_index].dai_type == SOC_SDW_DAI_TYPE_AMP &&
1400 		    codec_info->dais[dai_index].component_name) {
1401 			const char *component;
1402 
1403 			/*
1404 			 * For the special case of cs42l43 with sidecar amps, use only
1405 			 * "cs35l56-bridge" as the component name in card->components
1406 			 */
1407 			if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS &&
1408 			    !strcmp(codec_info->dais[dai_index].component_name, "cs42l43-spk"))
1409 				component = "cs35l56-bridge";
1410 			else
1411 				component = codec_info->dais[dai_index].component_name;
1412 
1413 			if (!spk_components)
1414 				spk_components =
1415 					devm_kasprintf(card->dev, GFP_KERNEL, "%s", component);
1416 			else
1417 				/* Append component name to spk_components */
1418 				spk_components =
1419 					devm_kasprintf(card->dev, GFP_KERNEL,
1420 						       "%s+%s", spk_components, component);
1421 
1422 			if (!spk_components)
1423 				return -ENOMEM;
1424 		}
1425 
1426 		codec_info->dais[dai_index].rtd_init_done = true;
1427 	}
1428 
1429 	if (spk_components) {
1430 		/* Update card components for speaker components */
1431 		card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s",
1432 						  card->components, spk_components);
1433 		if (!card->components)
1434 			return -ENOMEM;
1435 	}
1436 
1437 	return 0;
1438 }
1439 EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, "SND_SOC_SDW_UTILS");
1440 
1441 /* these wrappers are only needed to avoid typecast compilation errors */
1442 int asoc_sdw_startup(struct snd_pcm_substream *substream)
1443 {
1444 	return sdw_startup_stream(substream);
1445 }
1446 EXPORT_SYMBOL_NS(asoc_sdw_startup, "SND_SOC_SDW_UTILS");
1447 
1448 int asoc_sdw_prepare(struct snd_pcm_substream *substream)
1449 {
1450 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1451 	struct sdw_stream_runtime *sdw_stream;
1452 	struct snd_soc_dai *dai;
1453 
1454 	/* Find stream from first CPU DAI */
1455 	dai = snd_soc_rtd_to_cpu(rtd, 0);
1456 
1457 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
1458 	if (IS_ERR(sdw_stream)) {
1459 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
1460 		return PTR_ERR(sdw_stream);
1461 	}
1462 
1463 	return sdw_prepare_stream(sdw_stream);
1464 }
1465 EXPORT_SYMBOL_NS(asoc_sdw_prepare, "SND_SOC_SDW_UTILS");
1466 
1467 int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
1468 {
1469 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1470 	struct sdw_stream_runtime *sdw_stream;
1471 	struct snd_soc_dai *dai;
1472 	int ret;
1473 
1474 	/* Find stream from first CPU DAI */
1475 	dai = snd_soc_rtd_to_cpu(rtd, 0);
1476 
1477 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
1478 	if (IS_ERR(sdw_stream)) {
1479 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
1480 		return PTR_ERR(sdw_stream);
1481 	}
1482 
1483 	switch (cmd) {
1484 	case SNDRV_PCM_TRIGGER_START:
1485 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1486 	case SNDRV_PCM_TRIGGER_RESUME:
1487 		ret = sdw_enable_stream(sdw_stream);
1488 		break;
1489 
1490 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1491 	case SNDRV_PCM_TRIGGER_SUSPEND:
1492 	case SNDRV_PCM_TRIGGER_STOP:
1493 		ret = sdw_disable_stream(sdw_stream);
1494 		break;
1495 	default:
1496 		ret = -EINVAL;
1497 		break;
1498 	}
1499 
1500 	if (ret)
1501 		dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret);
1502 
1503 	return ret;
1504 }
1505 EXPORT_SYMBOL_NS(asoc_sdw_trigger, "SND_SOC_SDW_UTILS");
1506 
1507 int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
1508 		       struct snd_pcm_hw_params *params)
1509 {
1510 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1511 	struct snd_soc_dai_link_ch_map *ch_maps;
1512 	int ch = params_channels(params);
1513 	unsigned int ch_mask;
1514 	int num_codecs;
1515 	int step;
1516 	int i;
1517 
1518 	if (!rtd->dai_link->ch_maps)
1519 		return 0;
1520 
1521 	/* Identical data will be sent to all codecs in playback */
1522 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1523 		ch_mask = GENMASK(ch - 1, 0);
1524 		step = 0;
1525 	} else {
1526 		num_codecs = rtd->dai_link->num_codecs;
1527 
1528 		if (ch < num_codecs || ch % num_codecs != 0) {
1529 			dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n",
1530 				ch, num_codecs);
1531 			return -EINVAL;
1532 		}
1533 
1534 		ch_mask = GENMASK(ch / num_codecs - 1, 0);
1535 		step = hweight_long(ch_mask);
1536 	}
1537 
1538 	/*
1539 	 * The captured data will be combined from each cpu DAI if the dai
1540 	 * link has more than one codec DAIs. Set codec channel mask and
1541 	 * ASoC will set the corresponding channel numbers for each cpu dai.
1542 	 */
1543 	for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
1544 		ch_maps->ch_mask = ch_mask << (i * step);
1545 
1546 	return 0;
1547 }
1548 EXPORT_SYMBOL_NS(asoc_sdw_hw_params, "SND_SOC_SDW_UTILS");
1549 
1550 int asoc_sdw_hw_free(struct snd_pcm_substream *substream)
1551 {
1552 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1553 	struct sdw_stream_runtime *sdw_stream;
1554 	struct snd_soc_dai *dai;
1555 
1556 	/* Find stream from first CPU DAI */
1557 	dai = snd_soc_rtd_to_cpu(rtd, 0);
1558 
1559 	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
1560 	if (IS_ERR(sdw_stream)) {
1561 		dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name);
1562 		return PTR_ERR(sdw_stream);
1563 	}
1564 
1565 	return sdw_deprepare_stream(sdw_stream);
1566 }
1567 EXPORT_SYMBOL_NS(asoc_sdw_hw_free, "SND_SOC_SDW_UTILS");
1568 
1569 void asoc_sdw_shutdown(struct snd_pcm_substream *substream)
1570 {
1571 	sdw_shutdown_stream(substream);
1572 }
1573 EXPORT_SYMBOL_NS(asoc_sdw_shutdown, "SND_SOC_SDW_UTILS");
1574 
1575 static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_link,
1576 				      unsigned int sdw_version,
1577 				      unsigned int mfg_id,
1578 				      unsigned int part_id,
1579 				      unsigned int class_id,
1580 				      int index_in_link)
1581 {
1582 	int i;
1583 
1584 	for (i = 0; i < adr_link->num_adr; i++) {
1585 		unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
1586 		u64 adr;
1587 
1588 		/* skip itself */
1589 		if (i == index_in_link)
1590 			continue;
1591 
1592 		adr = adr_link->adr_d[i].adr;
1593 
1594 		sdw1_version = SDW_VERSION(adr);
1595 		mfg1_id = SDW_MFG_ID(adr);
1596 		part1_id = SDW_PART_ID(adr);
1597 		class1_id = SDW_CLASS_ID(adr);
1598 
1599 		if (sdw_version == sdw1_version &&
1600 		    mfg_id == mfg1_id &&
1601 		    part_id == part1_id &&
1602 		    class_id == class1_id)
1603 			return false;
1604 	}
1605 
1606 	return true;
1607 }
1608 
1609 static const char *_asoc_sdw_get_codec_name(struct device *dev,
1610 					    const struct snd_soc_acpi_link_adr *adr_link,
1611 					    int adr_index)
1612 {
1613 	u64 adr = adr_link->adr_d[adr_index].adr;
1614 	unsigned int sdw_version = SDW_VERSION(adr);
1615 	unsigned int link_id = SDW_DISCO_LINK_ID(adr);
1616 	unsigned int unique_id = SDW_UNIQUE_ID(adr);
1617 	unsigned int mfg_id = SDW_MFG_ID(adr);
1618 	unsigned int part_id = SDW_PART_ID(adr);
1619 	unsigned int class_id = SDW_CLASS_ID(adr);
1620 
1621 	if (asoc_sdw_is_unique_device(adr_link, sdw_version, mfg_id, part_id,
1622 				      class_id, adr_index))
1623 		return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x",
1624 				      link_id, mfg_id, part_id, class_id);
1625 
1626 	return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x",
1627 			      link_id, mfg_id, part_id, class_id, unique_id);
1628 }
1629 
1630 const char *asoc_sdw_get_codec_name(struct device *dev,
1631 				    const struct asoc_sdw_dai_info *dai_info,
1632 				    const struct snd_soc_acpi_link_adr *adr_link,
1633 				    int adr_index)
1634 {
1635 	if (dai_info->codec_name) {
1636 		struct snd_soc_component *component;
1637 
1638 		component = snd_soc_lookup_component_by_name(dai_info->codec_name);
1639 		if (component) {
1640 			dev_dbg(dev, "%s found component %s for codec_name %s\n",
1641 				__func__, component->name, dai_info->codec_name);
1642 			return devm_kstrdup(dev, component->name, GFP_KERNEL);
1643 		} else {
1644 			dev_dbg(dev, "%s component %s is not registered yet\n",
1645 				__func__, dai_info->codec_name);
1646 			return ERR_PTR(-EPROBE_DEFER);
1647 		}
1648 	}
1649 
1650 	return _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
1651 }
1652 EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, "SND_SOC_SDW_UTILS");
1653 
1654 /* helper to get the link that the codec DAI is used */
1655 struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card,
1656 							 const char *dai_name)
1657 {
1658 	struct snd_soc_dai_link *dai_link;
1659 	int i;
1660 	int j;
1661 
1662 	for_each_card_prelinks(card, i, dai_link) {
1663 		for (j = 0; j < dai_link->num_codecs; j++) {
1664 			/* Check each codec in a link */
1665 			if (!strcmp(dai_link->codecs[j].dai_name, dai_name))
1666 				return dai_link;
1667 		}
1668 	}
1669 	return NULL;
1670 }
1671 EXPORT_SYMBOL_NS(asoc_sdw_mc_find_codec_dai_used, "SND_SOC_SDW_UTILS");
1672 
1673 void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card)
1674 {
1675 	struct snd_soc_dai_link *dai_link;
1676 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1677 	int ret;
1678 	int i, j;
1679 
1680 	for (i = 0; i < ctx->codec_info_list_count; i++) {
1681 		for (j = 0; j < codec_info_list[i].dai_num; j++) {
1682 			codec_info_list[i].dais[j].rtd_init_done = false;
1683 			/* Check each dai in codec_info_lis to see if it is used in the link */
1684 			if (!codec_info_list[i].dais[j].exit)
1685 				continue;
1686 			/*
1687 			 * We don't need to call .exit function if there is no matched
1688 			 * dai link found.
1689 			 */
1690 			dai_link = asoc_sdw_mc_find_codec_dai_used(card,
1691 							  codec_info_list[i].dais[j].dai_name);
1692 			if (dai_link) {
1693 				/* Do the .exit function if the codec dai is used in the link */
1694 				ret = codec_info_list[i].dais[j].exit(card, dai_link);
1695 				if (ret)
1696 					dev_warn(card->dev,
1697 						 "codec exit failed %d\n",
1698 						 ret);
1699 				break;
1700 			}
1701 		}
1702 	}
1703 }
1704 EXPORT_SYMBOL_NS(asoc_sdw_mc_dailink_exit_loop, "SND_SOC_SDW_UTILS");
1705 
1706 int asoc_sdw_card_late_probe(struct snd_soc_card *card)
1707 {
1708 	int ret = 0;
1709 	int i;
1710 
1711 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1712 		if (codec_info_list[i].codec_card_late_probe) {
1713 			ret = codec_info_list[i].codec_card_late_probe(card);
1714 			if (ret < 0)
1715 				return ret;
1716 		}
1717 	}
1718 	return ret;
1719 }
1720 EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, "SND_SOC_SDW_UTILS");
1721 
1722 void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1723 			    int *be_id, char *name, int playback, int capture,
1724 			    struct snd_soc_dai_link_component *cpus, int cpus_num,
1725 			    struct snd_soc_dai_link_component *platform_component,
1726 			    int num_platforms, struct snd_soc_dai_link_component *codecs,
1727 			    int codecs_num, int no_pcm,
1728 			    int (*init)(struct snd_soc_pcm_runtime *rtd),
1729 			    const struct snd_soc_ops *ops)
1730 {
1731 	dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id);
1732 	dai_links->id = (*be_id)++;
1733 	dai_links->name = name;
1734 	dai_links->stream_name = name;
1735 	dai_links->platforms = platform_component;
1736 	dai_links->num_platforms = num_platforms;
1737 	dai_links->no_pcm = no_pcm;
1738 	dai_links->cpus = cpus;
1739 	dai_links->num_cpus = cpus_num;
1740 	dai_links->codecs = codecs;
1741 	dai_links->num_codecs = codecs_num;
1742 	dai_links->playback_only =  playback && !capture;
1743 	dai_links->capture_only  = !playback &&  capture;
1744 	dai_links->init = init;
1745 	dai_links->ops = ops;
1746 }
1747 EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, "SND_SOC_SDW_UTILS");
1748 
1749 int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1750 				  int *be_id, char *name, int playback, int capture,
1751 				  const char *cpu_dai_name, const char *platform_comp_name,
1752 				  const char *codec_name, const char *codec_dai_name,
1753 				  int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd),
1754 				  const struct snd_soc_ops *ops)
1755 {
1756 	struct snd_soc_dai_link_component *dlc;
1757 
1758 	/* Allocate three DLCs one for the CPU, one for platform and one for the CODEC */
1759 	dlc = devm_kcalloc(dev, 3, sizeof(*dlc), GFP_KERNEL);
1760 	if (!dlc || !name || !cpu_dai_name || !platform_comp_name || !codec_name || !codec_dai_name)
1761 		return -ENOMEM;
1762 
1763 	dlc[0].dai_name = cpu_dai_name;
1764 	dlc[1].name = platform_comp_name;
1765 
1766 	dlc[2].name = codec_name;
1767 	dlc[2].dai_name = codec_dai_name;
1768 
1769 	asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture,
1770 			       &dlc[0], 1, &dlc[1], 1, &dlc[2], 1,
1771 			       no_pcm, init, ops);
1772 
1773 	return 0;
1774 }
1775 EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS");
1776 
1777 /**
1778  * is_sdca_aux_dev_present - Check if an SDCA aux device is present on the SDW peripheral
1779  * @dev: Device pointer
1780  * @aux_codec_name: Aux codec name from the codec info (e.g. "snd_soc_sdca.HID.2")
1781  * @adr_link: ACPI link address
1782  * @adr_index: Index of the ACPI link address
1783  *
1784  * Return: 1 if the aux is present, 0 if the aux is not present, or negative error code.
1785  */
1786 static int is_sdca_aux_dev_present(struct device *dev,
1787 				   const char *aux_codec_name,
1788 				   const struct snd_soc_acpi_link_adr *adr_link,
1789 				   int adr_index)
1790 {
1791 	struct sdw_slave *slave;
1792 	struct device *sdw_dev;
1793 	const char *sdw_codec_name;
1794 	int ret = 0;
1795 	int i;
1796 
1797 	if (!aux_codec_name)
1798 		return 0;
1799 
1800 	sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
1801 	if (!sdw_codec_name)
1802 		return -ENOMEM;
1803 
1804 	sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name);
1805 	if (!sdw_dev) {
1806 		dev_err(dev, "codec %s not found\n", sdw_codec_name);
1807 		return -EINVAL;
1808 	}
1809 
1810 	slave = dev_to_sdw_dev(sdw_dev);
1811 
1812 	if (!slave->sdca_data.interface_revision) {
1813 		dev_warn(dev, "No SDCA properties, assuming aux '%s' present\n", aux_codec_name);
1814 		ret = 1;
1815 		goto put_dev;
1816 	}
1817 
1818 	for (i = 0; i < slave->sdca_data.num_functions; i++) {
1819 		const char *fname = slave->sdca_data.function[i].name;
1820 
1821 		if (fname && strstr(aux_codec_name, fname)) {
1822 			ret = 1;
1823 			goto put_dev;
1824 		}
1825 	}
1826 
1827 	dev_dbg(dev, "SDCA function for aux '%s' NOT FOUND on slave, skipping\n", aux_codec_name);
1828 
1829 put_dev:
1830 	put_device(sdw_dev);
1831 	return ret;
1832 }
1833 
1834 int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
1835 				 int *num_devs, int *num_ends, int *num_aux)
1836 {
1837 	struct device *dev = card->dev;
1838 	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
1839 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1840 	const struct snd_soc_acpi_link_adr *adr_link;
1841 	int i, j, ret;
1842 
1843 	for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
1844 		*num_devs += adr_link->num_adr;
1845 
1846 		for (i = 0; i < adr_link->num_adr; i++) {
1847 			const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
1848 			struct asoc_sdw_codec_info *codec_info;
1849 
1850 			*num_ends += adr_dev->num_endpoints;
1851 
1852 			codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr);
1853 			if (!codec_info)
1854 				return -EINVAL;
1855 
1856 			for (j = 0; j < codec_info->aux_num; j++) {
1857 				ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name,
1858 							      adr_link, i);
1859 				if (ret < 0)
1860 					return ret;
1861 				if (ret)
1862 					(*num_aux)++;
1863 			}
1864 		}
1865 	}
1866 
1867 	dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);
1868 
1869 	return 0;
1870 }
1871 EXPORT_SYMBOL_NS(asoc_sdw_count_sdw_endpoints, "SND_SOC_SDW_UTILS");
1872 
1873 struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
1874 					       const struct snd_soc_acpi_endpoint *new)
1875 {
1876 	while (dailinks->initialised) {
1877 		if (new->aggregated && dailinks->group_id == new->group_id)
1878 			return dailinks;
1879 
1880 		dailinks++;
1881 	}
1882 
1883 	INIT_LIST_HEAD(&dailinks->endpoints);
1884 	dailinks->group_id = new->group_id;
1885 	dailinks->initialised = true;
1886 
1887 	return dailinks;
1888 }
1889 EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, "SND_SOC_SDW_UTILS");
1890 
1891 int asoc_sdw_get_dai_type(u32 type)
1892 {
1893 	switch (type) {
1894 	case SDCA_FUNCTION_TYPE_SMART_AMP:
1895 	case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
1896 	case SDCA_FUNCTION_TYPE_COMPANION_AMP:
1897 		return SOC_SDW_DAI_TYPE_AMP;
1898 	case SDCA_FUNCTION_TYPE_SMART_MIC:
1899 	case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
1900 	case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
1901 		return SOC_SDW_DAI_TYPE_MIC;
1902 	case SDCA_FUNCTION_TYPE_UAJ:
1903 	case SDCA_FUNCTION_TYPE_RJ:
1904 	case SDCA_FUNCTION_TYPE_SIMPLE_JACK:
1905 		return SOC_SDW_DAI_TYPE_JACK;
1906 	default:
1907 		return -EINVAL;
1908 	}
1909 }
1910 EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
1911 
1912 /**
1913  * is_sdca_endpoint_present - Check if an SDCA endpoint is present on the SDW peripheral
1914  * @dev: Device pointer
1915  * @codec_info: Codec info pointer
1916  * @adr_link: ACPI link address
1917  * @adr_index: Index of the ACPI link address
1918  * @end_index: Index of the endpoint
1919  *
1920  * Return: 1 if the endpoint is present, 0 if the endpoint is not present, or negative error code.
1921  */
1922 static int is_sdca_endpoint_present(struct device *dev,
1923 				    struct asoc_sdw_codec_info *codec_info,
1924 				    const struct snd_soc_acpi_link_adr *adr_link,
1925 				    int adr_index, int end_index)
1926 {
1927 	const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[adr_index];
1928 	const struct snd_soc_acpi_endpoint *adr_end;
1929 	const struct asoc_sdw_dai_info *dai_info;
1930 	struct sdw_slave *slave;
1931 	struct device *sdw_dev;
1932 	const char *sdw_codec_name;
1933 	int ret, i;
1934 
1935 	adr_end = &adr_dev->endpoints[end_index];
1936 	dai_info = &codec_info->dais[adr_end->num];
1937 
1938 	sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
1939 	if (!sdw_codec_name)
1940 		return -ENOMEM;
1941 
1942 	sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name);
1943 	if (!sdw_dev) {
1944 		dev_err(dev, "codec %s not found\n", sdw_codec_name);
1945 		return -EINVAL;
1946 	}
1947 
1948 	slave = dev_to_sdw_dev(sdw_dev);
1949 
1950 	/* Make sure BIOS provides SDCA properties */
1951 	if (!slave->sdca_data.interface_revision) {
1952 		dev_warn(&slave->dev, "SDCA properties not found in the BIOS\n");
1953 		ret = 1;
1954 		goto put_device;
1955 	}
1956 
1957 	for (i = 0; i < slave->sdca_data.num_functions; i++) {
1958 		int dai_type = asoc_sdw_get_dai_type(slave->sdca_data.function[i].type);
1959 
1960 		if (dai_type == dai_info->dai_type) {
1961 			dev_dbg(&slave->dev, "DAI type %d sdca function %s found\n",
1962 				dai_type, slave->sdca_data.function[i].name);
1963 			ret = 1;
1964 			goto put_device;
1965 		}
1966 	}
1967 
1968 	dev_dbg(&slave->dev,
1969 		"SDCA device function for DAI type %d not supported, skip endpoint\n",
1970 		dai_info->dai_type);
1971 
1972 	ret = 0;
1973 
1974 put_device:
1975 	put_device(sdw_dev);
1976 	return ret;
1977 }
1978 
1979 int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
1980 				 struct snd_soc_aux_dev *soc_aux,
1981 				 struct asoc_sdw_dailink *soc_dais,
1982 				 struct asoc_sdw_endpoint *soc_ends,
1983 				 int *num_devs)
1984 {
1985 	struct device *dev = card->dev;
1986 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1987 	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
1988 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1989 	const struct snd_soc_acpi_link_adr *adr_link;
1990 	struct asoc_sdw_endpoint *soc_end = soc_ends;
1991 	int num_dais = 0;
1992 	int i, j;
1993 	int ret;
1994 
1995 	for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
1996 		int num_link_dailinks = 0;
1997 
1998 		if (!is_power_of_2(adr_link->mask)) {
1999 			dev_err(dev, "link with multiple mask bits: 0x%x\n",
2000 				adr_link->mask);
2001 			return -EINVAL;
2002 		}
2003 
2004 		for (i = 0; i < adr_link->num_adr; i++) {
2005 			const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
2006 			struct asoc_sdw_codec_info *codec_info;
2007 			const char *codec_name;
2008 			bool check_sdca = false;
2009 
2010 			if (!adr_dev->name_prefix) {
2011 				dev_err(dev, "codec 0x%llx does not have a name prefix\n",
2012 					adr_dev->adr);
2013 				return -EINVAL;
2014 			}
2015 
2016 			codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr);
2017 			if (!codec_info)
2018 				return -EINVAL;
2019 
2020 			for (j = 0; j < codec_info->aux_num; j++) {
2021 				struct snd_soc_component *component;
2022 
2023 				ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name,
2024 							      adr_link, i);
2025 				if (ret < 0)
2026 					return ret;
2027 
2028 				if (ret == 0)
2029 					continue;
2030 
2031 				component = snd_soc_lookup_component_by_name(codec_info->auxs[j].codec_name);
2032 				if (component) {
2033 					dev_dbg(dev, "%s found component %s for aux name %s\n",
2034 						__func__, component->name,
2035 						codec_info->auxs[j].codec_name);
2036 					soc_aux->dlc.name = component->name;
2037 				} else {
2038 					dev_dbg(dev, "%s the aux component %s is not registered yet\n",
2039 						__func__, codec_info->auxs[j].codec_name);
2040 					return -EPROBE_DEFER;
2041 				}
2042 				soc_aux++;
2043 			}
2044 
2045 			ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;
2046 
2047 			if (codec_info->count_sidecar && codec_info->add_sidecar) {
2048 				ret = codec_info->count_sidecar(card, &num_dais, num_devs);
2049 				if (ret)
2050 					return ret;
2051 
2052 				soc_end->include_sidecar = true;
2053 			}
2054 
2055 			if (SDW_CLASS_ID(adr_dev->adr) && adr_dev->num_endpoints > 1)
2056 				check_sdca = true;
2057 
2058 			for (j = 0; j < adr_dev->num_endpoints; j++) {
2059 				const struct snd_soc_acpi_endpoint *adr_end;
2060 				const struct asoc_sdw_dai_info *dai_info;
2061 				struct asoc_sdw_dailink *soc_dai;
2062 				int stream;
2063 
2064 				adr_end = &adr_dev->endpoints[j];
2065 				dai_info = &codec_info->dais[adr_end->num];
2066 				soc_dai = asoc_sdw_find_dailink(soc_dais, adr_end);
2067 
2068 				/*
2069 				 * quirk should have higher priority than the sdca properties
2070 				 * in the BIOS. We can't always check the DAI quirk because we
2071 				 * will set the mc_quirk when the BIOS doesn't provide the right
2072 				 * information. The endpoint will be skipped if the dai_info->
2073 				 * quirk_exclude and mc_quirk are both not set if we always skip
2074 				 * the endpoint according to the quirk information. We need to
2075 				 * keep the endpoint if it is present in the BIOS. So, only
2076 				 * check the DAI quirk when the mc_quirk is set or SDCA endpoint
2077 				 * present check is not needed.
2078 				 */
2079 				if (dai_info->quirk & ctx->mc_quirk || !check_sdca) {
2080 					/*
2081 					 * Check the endpoint if a matching quirk is set or SDCA
2082 					 * endpoint check is not necessary
2083 					 */
2084 					if (dai_info->quirk &&
2085 					    !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk))) {
2086 						(*num_devs)--;
2087 						continue;
2088 					}
2089 				} else {
2090 					/* Check SDCA codec endpoint if there is no matching quirk */
2091 					ret = is_sdca_endpoint_present(dev, codec_info, adr_link, i, j);
2092 					if (ret < 0)
2093 						return ret;
2094 
2095 					/* The endpoint is not present, skip */
2096 					if (!ret) {
2097 						(*num_devs)--;
2098 						continue;
2099 					}
2100 				}
2101 
2102 				dev_dbg(dev,
2103 					"Add dev: %d, 0x%llx end: %d, dai: %d, %c/%c to %s: %d\n",
2104 					ffs(adr_link->mask) - 1, adr_dev->adr,
2105 					adr_end->num, dai_info->dai_type,
2106 					dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
2107 					dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
2108 					adr_end->aggregated ? "group" : "solo",
2109 					adr_end->group_id);
2110 
2111 				if (adr_end->num >= codec_info->dai_num) {
2112 					dev_err(dev,
2113 						"%d is too many endpoints for codec: 0x%x\n",
2114 						adr_end->num, codec_info->part_id);
2115 					return -EINVAL;
2116 				}
2117 
2118 				for_each_pcm_streams(stream) {
2119 					if (dai_info->direction[stream] &&
2120 					    dai_info->dailink[stream] < 0) {
2121 						dev_err(dev,
2122 							"Invalid dailink id %d for codec: 0x%x\n",
2123 							dai_info->dailink[stream],
2124 							codec_info->part_id);
2125 						return -EINVAL;
2126 					}
2127 
2128 					if (dai_info->direction[stream]) {
2129 						num_dais += !soc_dai->num_devs[stream];
2130 						soc_dai->num_devs[stream]++;
2131 						soc_dai->link_mask[stream] |= adr_link->mask;
2132 					}
2133 				}
2134 
2135 				num_link_dailinks += !!list_empty(&soc_dai->endpoints);
2136 				list_add_tail(&soc_end->list, &soc_dai->endpoints);
2137 
2138 				codec_name = asoc_sdw_get_codec_name(dev, dai_info,
2139 								     adr_link, i);
2140 				if (IS_ERR(codec_name))
2141 					return PTR_ERR(codec_name);
2142 				if (!codec_name)
2143 					return -ENOMEM;
2144 
2145 				dev_dbg(dev, "Adding prefix %s for %s\n",
2146 					adr_dev->name_prefix, codec_name);
2147 
2148 				soc_end->name_prefix = adr_dev->name_prefix;
2149 
2150 				soc_end->link_mask = adr_link->mask;
2151 				soc_end->codec_name = codec_name;
2152 				soc_end->codec_info = codec_info;
2153 				soc_end->dai_info = dai_info;
2154 				soc_end++;
2155 			}
2156 		}
2157 
2158 		ctx->append_dai_type |= (num_link_dailinks > 1);
2159 	}
2160 
2161 	return num_dais;
2162 }
2163 EXPORT_SYMBOL_NS(asoc_sdw_parse_sdw_endpoints, "SND_SOC_SDW_UTILS");
2164 
2165 MODULE_LICENSE("GPL");
2166 MODULE_DESCRIPTION("SoundWire ASoC helpers");
2167