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