xref: /linux/sound/soc/intel/boards/sof_sdw.c (revision c93913c70809898aa5e450e4aad0b99750d9f082)
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/acpi.h>
9 #include <linux/bitmap.h>
10 #include <linux/device.h>
11 #include <linux/dmi.h>
12 #include <linux/module.h>
13 #include <linux/soundwire/sdw.h>
14 #include <linux/soundwire/sdw_type.h>
15 #include <linux/soundwire/sdw_intel.h>
16 #include <sound/core.h>
17 #include <sound/soc-acpi.h>
18 #include "sof_sdw_common.h"
19 #include "../../codecs/rt711.h"
20 
21 static unsigned long sof_sdw_quirk = RT711_JD1;
22 static int quirk_override = -1;
23 module_param_named(quirk, quirk_override, int, 0444);
24 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
25 
26 #define DMIC_DEFAULT_CHANNELS 2
27 
log_quirks(struct device * dev)28 static void log_quirks(struct device *dev)
29 {
30 	if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk))
31 		dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
32 			SOC_SDW_JACK_JDSRC(sof_sdw_quirk));
33 	if (sof_sdw_quirk & SOC_SDW_FOUR_SPK)
34 		dev_err(dev, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\n");
35 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
36 		dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
37 	if (sof_sdw_quirk & SOC_SDW_PCH_DMIC)
38 		dev_dbg(dev, "quirk SOC_SDW_PCH_DMIC enabled\n");
39 	if (SOF_SSP_GET_PORT(sof_sdw_quirk))
40 		dev_dbg(dev, "SSP port %ld\n",
41 			SOF_SSP_GET_PORT(sof_sdw_quirk));
42 	if (sof_sdw_quirk & SOC_SDW_NO_AGGREGATION)
43 		dev_err(dev, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n");
44 	if (sof_sdw_quirk & SOC_SDW_CODEC_SPKR)
45 		dev_dbg(dev, "quirk SOC_SDW_CODEC_SPKR enabled\n");
46 	if (sof_sdw_quirk & SOC_SDW_SIDECAR_AMPS)
47 		dev_dbg(dev, "quirk SOC_SDW_SIDECAR_AMPS enabled\n");
48 	if (sof_sdw_quirk & SOC_SDW_CODEC_MIC)
49 		dev_dbg(dev, "quirk SOC_SDW_CODEC_MIC enabled\n");
50 }
51 
sof_sdw_quirk_cb(const struct dmi_system_id * id)52 static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
53 {
54 	sof_sdw_quirk = (unsigned long)id->driver_data;
55 	return 1;
56 }
57 
58 static const struct dmi_system_id sof_sdw_quirk_table[] = {
59 	/* CometLake devices */
60 	{
61 		.callback = sof_sdw_quirk_cb,
62 		.matches = {
63 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
64 			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
65 		},
66 		.driver_data = (void *)SOC_SDW_PCH_DMIC,
67 	},
68 	{
69 		.callback = sof_sdw_quirk_cb,
70 		.matches = {
71 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
72 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
73 		},
74 		.driver_data = (void *)RT711_JD2,
75 	},
76 	{
77 		/* early version of SKU 09C6 */
78 		.callback = sof_sdw_quirk_cb,
79 		.matches = {
80 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
81 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
82 		},
83 		.driver_data = (void *)RT711_JD2,
84 	},
85 	{
86 		.callback = sof_sdw_quirk_cb,
87 		.matches = {
88 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
89 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
90 		},
91 		.driver_data = (void *)(RT711_JD2),
92 	},
93 	{
94 		.callback = sof_sdw_quirk_cb,
95 		.matches = {
96 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
97 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
98 		},
99 		.driver_data = (void *)(RT711_JD2),
100 	},
101 	/* IceLake devices */
102 	{
103 		.callback = sof_sdw_quirk_cb,
104 		.matches = {
105 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
106 			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
107 		},
108 		.driver_data = (void *)SOC_SDW_PCH_DMIC,
109 	},
110 	/* TigerLake devices */
111 	{
112 		.callback = sof_sdw_quirk_cb,
113 		.matches = {
114 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
115 			DMI_MATCH(DMI_PRODUCT_NAME,
116 				  "Tiger Lake Client Platform"),
117 		},
118 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
119 					RT711_JD1 |
120 					SOC_SDW_PCH_DMIC |
121 					SOF_SSP_PORT(SOF_I2S_SSP2)),
122 	},
123 	{
124 		.callback = sof_sdw_quirk_cb,
125 		.matches = {
126 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
127 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
128 		},
129 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
130 					RT711_JD2),
131 	},
132 	{
133 		/* another SKU of Dell Latitude 9520 */
134 		.callback = sof_sdw_quirk_cb,
135 		.matches = {
136 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
137 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
138 		},
139 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
140 					RT711_JD2),
141 	},
142 	{
143 		/* Dell XPS 9710 */
144 		.callback = sof_sdw_quirk_cb,
145 		.matches = {
146 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
147 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
148 		},
149 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
150 					RT711_JD2),
151 	},
152 	{
153 		.callback = sof_sdw_quirk_cb,
154 		.matches = {
155 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
156 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
157 		},
158 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
159 					RT711_JD2),
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 					SOC_SDW_PCH_DMIC |
169 					SOF_BT_OFFLOAD_SSP(2) |
170 					SOF_SSP_BT_OFFLOAD_PRESENT),
171 	},
172 	{
173 		.callback = sof_sdw_quirk_cb,
174 		.matches = {
175 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
176 			DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
177 		},
178 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
179 					SOC_SDW_PCH_DMIC),
180 	},
181 	{
182 		/*
183 		 * this entry covers multiple HP SKUs. The family name
184 		 * does not seem robust enough, so we use a partial
185 		 * match that ignores the product name suffix
186 		 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
187 		 */
188 		.callback = sof_sdw_quirk_cb,
189 		.matches = {
190 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
191 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
192 		},
193 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
194 					SOC_SDW_PCH_DMIC |
195 					RT711_JD1),
196 	},
197 	{
198 		/*
199 		 * this entry covers HP Spectre x360 where the DMI information
200 		 * changed somehow
201 		 */
202 		.callback = sof_sdw_quirk_cb,
203 		.matches = {
204 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
205 			DMI_MATCH(DMI_BOARD_NAME, "8709"),
206 		},
207 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
208 					SOC_SDW_PCH_DMIC |
209 					RT711_JD1),
210 	},
211 	{
212 		/* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
213 		.callback = sof_sdw_quirk_cb,
214 		.matches = {
215 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
216 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
217 		},
218 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
219 					SOC_SDW_PCH_DMIC |
220 					RT711_JD1),
221 	},
222 	{
223 		/* NUC15 LAPBC710 skews */
224 		.callback = sof_sdw_quirk_cb,
225 		.matches = {
226 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
227 			DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
228 		},
229 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
230 					SOC_SDW_PCH_DMIC |
231 					RT711_JD1),
232 	},
233 	{
234 		/* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
235 		.callback = sof_sdw_quirk_cb,
236 		.matches = {
237 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
238 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
239 		},
240 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
241 					SOC_SDW_PCH_DMIC |
242 					RT711_JD2_100K),
243 	},
244 	{
245 		/* NUC15 LAPRC710 skews */
246 		.callback = sof_sdw_quirk_cb,
247 		.matches = {
248 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
249 			DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
250 		},
251 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
252 					SOC_SDW_PCH_DMIC |
253 					RT711_JD2_100K),
254 	},
255 	/* TigerLake-SDCA devices */
256 	{
257 		.callback = sof_sdw_quirk_cb,
258 		.matches = {
259 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
260 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
261 		},
262 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
263 					RT711_JD2),
264 	},
265 	{
266 		.callback = sof_sdw_quirk_cb,
267 		.matches = {
268 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
269 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
270 		},
271 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
272 					RT711_JD2),
273 	},
274 	/* AlderLake devices */
275 	{
276 		.callback = sof_sdw_quirk_cb,
277 		.matches = {
278 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
279 			DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
280 		},
281 		.driver_data = (void *)(RT711_JD2_100K |
282 					SOF_SDW_TGL_HDMI |
283 					SOF_BT_OFFLOAD_SSP(2) |
284 					SOF_SSP_BT_OFFLOAD_PRESENT),
285 	},
286 	{
287 		.callback = sof_sdw_quirk_cb,
288 		.matches = {
289 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
290 			DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"),
291 		},
292 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
293 					RT711_JD2_100K),
294 	},
295 	{
296 		.callback = sof_sdw_quirk_cb,
297 		.matches = {
298 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
299 			DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
300 		},
301 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
302 					SOC_SDW_PCH_DMIC |
303 					SOF_BT_OFFLOAD_SSP(2) |
304 					SOF_SSP_BT_OFFLOAD_PRESENT),
305 	},
306 	{
307 		.callback = sof_sdw_quirk_cb,
308 		.matches = {
309 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
310 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
311 		},
312 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
313 					RT711_JD2),
314 	},
315 	{
316 		.callback = sof_sdw_quirk_cb,
317 		.matches = {
318 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
319 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
320 		},
321 		/* No Jack */
322 		.driver_data = (void *)(SOF_SDW_TGL_HDMI),
323 	},
324 	{
325 		.callback = sof_sdw_quirk_cb,
326 		.matches = {
327 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
328 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
329 		},
330 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
331 					RT711_JD2),
332 	},
333 	{
334 		.callback = sof_sdw_quirk_cb,
335 		.matches = {
336 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
337 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
338 		},
339 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
340 					RT711_JD2),
341 	},
342 	{
343 		.callback = sof_sdw_quirk_cb,
344 		.matches = {
345 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
346 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
347 		},
348 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
349 					RT711_JD2),
350 	},
351 	{
352 		.callback = sof_sdw_quirk_cb,
353 		.matches = {
354 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
355 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
356 		},
357 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
358 					RT711_JD2),
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, "0B11")
365 		},
366 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
367 					RT711_JD2),
368 	},
369 	{
370 		.callback = sof_sdw_quirk_cb,
371 		.matches = {
372 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
373 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12")
374 		},
375 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
376 					RT711_JD2),
377 	},
378 	{
379 		.callback = sof_sdw_quirk_cb,
380 		.matches = {
381 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
382 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
383 		},
384 		/* No Jack */
385 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
386 	},
387 	{
388 		.callback = sof_sdw_quirk_cb,
389 		.matches = {
390 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
391 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"),
392 		},
393 		/* No Jack */
394 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
395 	},
396 
397 	{
398 		.callback = sof_sdw_quirk_cb,
399 		.matches = {
400 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
401 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
402 		},
403 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
404 					RT711_JD2),
405 	},
406 	{
407 		.callback = sof_sdw_quirk_cb,
408 		.matches = {
409 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
410 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
411 		},
412 		/* No Jack */
413 		.driver_data = (void *)SOF_SDW_TGL_HDMI,
414 	},
415 	{
416 		.callback = sof_sdw_quirk_cb,
417 		.matches = {
418 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
419 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B8C"),
420 		},
421 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
422 					RT711_JD2),
423 	},
424 	{
425 		.callback = sof_sdw_quirk_cb,
426 		.matches = {
427 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
428 			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
429 		},
430 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
431 					RT711_JD2),
432 	},
433 	/* RaptorLake devices */
434 	{
435 		.callback = sof_sdw_quirk_cb,
436 		.matches = {
437 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
438 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
439 		},
440 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
441 					RT711_JD2),
442 	},
443 	{
444 		.callback = sof_sdw_quirk_cb,
445 		.matches = {
446 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
447 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
448 		},
449 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
450 					RT711_JD2),
451 	},
452 	{
453 		.callback = sof_sdw_quirk_cb,
454 		.matches = {
455 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
456 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"),
457 		},
458 		/* No Jack */
459 		.driver_data = (void *)(SOF_SDW_TGL_HDMI),
460 	},
461 	{
462 		.callback = sof_sdw_quirk_cb,
463 		.matches = {
464 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
465 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11")
466 		},
467 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
468 					RT711_JD2),
469 	},
470 	{
471 		.callback = sof_sdw_quirk_cb,
472 		.matches = {
473 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
474 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40")
475 		},
476 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
477 					RT711_JD2),
478 	},
479 	{
480 		.callback = sof_sdw_quirk_cb,
481 		.matches = {
482 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
483 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F")
484 		},
485 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
486 					RT711_JD2),
487 	},
488 	{
489 		.callback = sof_sdw_quirk_cb,
490 		.matches = {
491 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
492 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF6")
493 		},
494 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
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, "0CF9")
501 		},
502 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
503 	},
504 	{
505 		.callback = sof_sdw_quirk_cb,
506 		.matches = {
507 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
508 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CFA")
509 		},
510 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
511 	},
512 	/* MeteorLake devices */
513 	{
514 		.callback = sof_sdw_quirk_cb,
515 		.matches = {
516 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
517 		},
518 		.driver_data = (void *)(RT711_JD1),
519 	},
520 	{
521 		.callback = sof_sdw_quirk_cb,
522 		.matches = {
523 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
524 			DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"),
525 		},
526 		.driver_data = (void *)(RT711_JD2_100K),
527 	},
528 	{
529 		.callback = sof_sdw_quirk_cb,
530 		.matches = {
531 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
532 			DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
533 		},
534 		.driver_data = (void *)(SOC_SDW_PCH_DMIC |
535 					SOF_BT_OFFLOAD_SSP(1) |
536 					SOF_SSP_BT_OFFLOAD_PRESENT),
537 	},
538 	{
539 		.callback = sof_sdw_quirk_cb,
540 		.matches = {
541 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
542 			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"),
543 		},
544 		.driver_data = (void *)(RT711_JD2),
545 	},
546 
547 	/* LunarLake devices */
548 	{
549 		.callback = sof_sdw_quirk_cb,
550 		.matches = {
551 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
552 			DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
553 		},
554 		.driver_data = (void *)(RT711_JD2),
555 	},
556 	{
557 		.callback = sof_sdw_quirk_cb,
558 		.matches = {
559 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
560 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3")
561 		},
562 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
563 	},
564 	{
565 		.callback = sof_sdw_quirk_cb,
566 		.matches = {
567 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
568 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4")
569 		},
570 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
571 	},
572 	{
573 		.callback = sof_sdw_quirk_cb,
574 		.matches = {
575 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
576 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDB")
577 		},
578 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
579 	},
580 	{
581 		.callback = sof_sdw_quirk_cb,
582 		.matches = {
583 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
584 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDC")
585 		},
586 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
587 	},
588 	{
589 		.callback = sof_sdw_quirk_cb,
590 		.matches = {
591 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
592 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDD")
593 		},
594 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
595 	},
596 	{
597 		.callback = sof_sdw_quirk_cb,
598 		.matches = {
599 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
600 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D36")
601 		},
602 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
603 	},
604 	{
605 		.callback = sof_sdw_quirk_cb,
606 		.matches = {
607 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
608 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8")
609 		},
610 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
611 	},
612 	{
613 		.callback = sof_sdw_quirk_cb,
614 		.matches = {
615 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
616 			DMI_MATCH(DMI_PRODUCT_NAME, "83JX")
617 		},
618 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
619 	},
620 	{
621 		.callback = sof_sdw_quirk_cb,
622 		.matches = {
623 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
624 			DMI_MATCH(DMI_PRODUCT_NAME, "83LC")
625 		},
626 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
627 	},
628 	{
629 		.callback = sof_sdw_quirk_cb,
630 		.matches = {
631 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
632 			DMI_MATCH(DMI_PRODUCT_NAME, "83MC")
633 		},
634 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
635 	},	{
636 		.callback = sof_sdw_quirk_cb,
637 		.matches = {
638 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
639 			DMI_MATCH(DMI_PRODUCT_NAME, "83NM")
640 		},
641 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
642 	},
643 	{
644 		.callback = sof_sdw_quirk_cb,
645 		.matches = {
646 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
647 			DMI_MATCH(DMI_PRODUCT_NAME, "83HM")
648 		},
649 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS |
650 					SOC_SDW_CODEC_MIC),
651 	},
652 	{
653 		.callback = sof_sdw_quirk_cb,
654 		.matches = {
655 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
656 			DMI_MATCH(DMI_PRODUCT_NAME, "21QB")
657 		},
658 		/* Note this quirk excludes the CODEC mic */
659 		.driver_data = (void *)(SOC_SDW_CODEC_MIC),
660 	},
661 	{
662 		.callback = sof_sdw_quirk_cb,
663 		.matches = {
664 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
665 			DMI_MATCH(DMI_PRODUCT_NAME, "21QA")
666 		},
667 		/* Note this quirk excludes the CODEC mic */
668 		.driver_data = (void *)(SOC_SDW_CODEC_MIC),
669 	},
670 	{
671 		.callback = sof_sdw_quirk_cb,
672 		.matches = {
673 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
674 			DMI_MATCH(DMI_PRODUCT_NAME, "21Q6")
675 		},
676 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
677 	},
678 	{
679 		.callback = sof_sdw_quirk_cb,
680 		.matches = {
681 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
682 			DMI_MATCH(DMI_PRODUCT_NAME, "21Q7")
683 		},
684 		.driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
685 	},
686 
687 	/* ArrowLake devices */
688 	{
689 		.callback = sof_sdw_quirk_cb,
690 		.matches = {
691 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
692 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE8")
693 		},
694 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
695 	},
696 	{
697 		.callback = sof_sdw_quirk_cb,
698 		.matches = {
699 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
700 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF1")
701 		},
702 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
703 	},
704 	{
705 		.callback = sof_sdw_quirk_cb,
706 		.matches = {
707 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
708 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
709 		},
710 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
711 	},
712 	{
713 		.callback = sof_sdw_quirk_cb,
714 		.matches = {
715 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
716 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF0")
717 		},
718 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
719 	},
720 	{
721 		.callback = sof_sdw_quirk_cb,
722 		.matches = {
723 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
724 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF3")
725 		},
726 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
727 	},
728 	{
729 		.callback = sof_sdw_quirk_cb,
730 		.matches = {
731 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
732 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF4")
733 		},
734 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
735 	},
736 	{
737 		.callback = sof_sdw_quirk_cb,
738 		.matches = {
739 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
740 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF5")
741 		},
742 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
743 	},
744 	{
745 		.callback = sof_sdw_quirk_cb,
746 		.matches = {
747 			DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
748 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CCC")
749 		},
750 		.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
751 	},
752 	/* Pantherlake devices*/
753 	{
754 		.callback = sof_sdw_quirk_cb,
755 		.matches = {
756 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_ptlrvp"),
757 		},
758 		.driver_data = (void *)(SOC_SDW_PCH_DMIC),
759 	},
760 	{
761 		.callback = sof_sdw_quirk_cb,
762 		.matches = {
763 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
764 			DMI_MATCH(DMI_PRODUCT_NAME, "Fatcat"),
765 		},
766 		.driver_data = (void *)(SOC_SDW_PCH_DMIC |
767 					SOF_BT_OFFLOAD_SSP(2) |
768 					SOF_SSP_BT_OFFLOAD_PRESENT),
769 	},
770 	/* Wildcatlake devices*/
771 	{
772 		.callback = sof_sdw_quirk_cb,
773 		.matches = {
774 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_wclrvp"),
775 		},
776 		.driver_data = (void *)(SOC_SDW_PCH_DMIC),
777 	},
778 	{
779 		.callback = sof_sdw_quirk_cb,
780 		.matches = {
781 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
782 			DMI_MATCH(DMI_PRODUCT_NAME, "Ocelot"),
783 		},
784 		.driver_data = (void *)(SOC_SDW_PCH_DMIC |
785 					SOF_BT_OFFLOAD_SSP(2) |
786 					SOF_SSP_BT_OFFLOAD_PRESENT),
787 	},
788 	{}
789 };
790 
791 static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = {
792 	SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC),
793 	SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC),
794 	SND_PCI_QUIRK(0x17aa, 0x2347, "Lenovo P16", SOC_SDW_CODEC_MIC),
795 	SND_PCI_QUIRK(0x17aa, 0x2348, "Lenovo P16", SOC_SDW_CODEC_MIC),
796 	SND_PCI_QUIRK(0x17aa, 0x2349, "Lenovo P1", SOC_SDW_CODEC_MIC),
797 	{}
798 };
799 
sof_sdw_check_ssid_quirk(const struct snd_soc_acpi_mach * mach)800 static void sof_sdw_check_ssid_quirk(const struct snd_soc_acpi_mach *mach)
801 {
802 	const struct snd_pci_quirk *quirk_entry;
803 
804 	quirk_entry = snd_pci_quirk_lookup_id(mach->mach_params.subsystem_vendor,
805 					      mach->mach_params.subsystem_device,
806 					      sof_sdw_ssid_quirk_table);
807 
808 	if (quirk_entry)
809 		sof_sdw_quirk = quirk_entry->value;
810 }
811 
812 static const struct snd_soc_ops sdw_ops = {
813 	.startup = asoc_sdw_startup,
814 	.prepare = asoc_sdw_prepare,
815 	.trigger = asoc_sdw_trigger,
816 	.hw_params = asoc_sdw_hw_params,
817 	.hw_free = asoc_sdw_hw_free,
818 	.shutdown = asoc_sdw_shutdown,
819 };
820 
821 static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
822 
create_sdw_dailink(struct snd_soc_card * card,struct asoc_sdw_dailink * sof_dai,struct snd_soc_dai_link ** dai_links,int * be_id,struct snd_soc_codec_conf ** codec_conf)823 static int create_sdw_dailink(struct snd_soc_card *card,
824 			      struct asoc_sdw_dailink *sof_dai,
825 			      struct snd_soc_dai_link **dai_links,
826 			      int *be_id, struct snd_soc_codec_conf **codec_conf)
827 {
828 	struct device *dev = card->dev;
829 	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
830 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
831 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
832 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
833 	struct asoc_sdw_endpoint *sof_end;
834 	int stream;
835 	int ret;
836 
837 	list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
838 		if (sof_end->name_prefix) {
839 			(*codec_conf)->dlc.name = sof_end->codec_name;
840 			(*codec_conf)->name_prefix = sof_end->name_prefix;
841 			(*codec_conf)++;
842 		}
843 
844 		if (sof_end->include_sidecar) {
845 			ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
846 			if (ret)
847 				return ret;
848 		}
849 	}
850 
851 	for_each_pcm_streams(stream) {
852 		static const char * const sdw_stream_name[] = {
853 			"SDW%d-Playback",
854 			"SDW%d-Capture",
855 			"SDW%d-Playback-%s",
856 			"SDW%d-Capture-%s",
857 		};
858 		struct snd_soc_dai_link_ch_map *codec_maps;
859 		struct snd_soc_dai_link_component *codecs;
860 		struct snd_soc_dai_link_component *cpus;
861 		struct snd_soc_dai_link_component *platform;
862 		int num_cpus = hweight32(sof_dai->link_mask[stream]);
863 		int num_codecs = sof_dai->num_devs[stream];
864 		int playback, capture;
865 		int cur_link = 0;
866 		int i = 0, j = 0;
867 		char *name;
868 
869 		if (!sof_dai->num_devs[stream])
870 			continue;
871 
872 		sof_end = list_first_entry(&sof_dai->endpoints,
873 					   struct asoc_sdw_endpoint, list);
874 
875 		*be_id = sof_end->dai_info->dailink[stream];
876 		if (*be_id < 0) {
877 			dev_err(dev, "Invalid dailink id %d\n", *be_id);
878 			return -EINVAL;
879 		}
880 
881 		/* create stream name according to first link id */
882 		if (ctx->append_dai_type)
883 			name = devm_kasprintf(dev, GFP_KERNEL,
884 					      sdw_stream_name[stream + 2],
885 					      ffs(sof_end->link_mask) - 1,
886 					      type_strings[sof_end->dai_info->dai_type]);
887 		else
888 			name = devm_kasprintf(dev, GFP_KERNEL,
889 					      sdw_stream_name[stream],
890 					      ffs(sof_end->link_mask) - 1);
891 		if (!name)
892 			return -ENOMEM;
893 
894 		cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
895 		if (!cpus)
896 			return -ENOMEM;
897 
898 		codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
899 		if (!codecs)
900 			return -ENOMEM;
901 
902 		platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL);
903 		if (!platform)
904 			return -ENOMEM;
905 
906 		codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
907 		if (!codec_maps)
908 			return -ENOMEM;
909 
910 		list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
911 			if (!sof_end->dai_info->direction[stream])
912 				continue;
913 
914 			if (cur_link != sof_end->link_mask) {
915 				int link_num = ffs(sof_end->link_mask) - 1;
916 				int pin_num = intel_ctx->sdw_pin_index[link_num]++;
917 
918 				cur_link = sof_end->link_mask;
919 
920 				cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
921 								  "SDW%d Pin%d",
922 								  link_num, pin_num);
923 				if (!cpus[i].dai_name)
924 					return -ENOMEM;
925 				i++;
926 			}
927 
928 			codec_maps[j].cpu = i - 1;
929 			codec_maps[j].codec = j;
930 
931 			codecs[j].name = sof_end->codec_name;
932 			codecs[j].dai_name = sof_end->dai_info->dai_name;
933 			if (sof_end->dai_info->dai_type == SOC_SDW_DAI_TYPE_MIC &&
934 			    mach_params->dmic_num > 0) {
935 				dev_warn(dev,
936 					 "Both SDW DMIC and PCH DMIC are present, if incorrect, please set kernel params snd_sof_intel_hda_generic dmic_num=0 to disable PCH DMIC\n");
937 			}
938 			j++;
939 		}
940 
941 		WARN_ON(i != num_cpus || j != num_codecs);
942 
943 		playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
944 		capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
945 
946 		asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
947 				       cpus, num_cpus, platform, 1, codecs, num_codecs,
948 				       1, asoc_sdw_rtd_init, &sdw_ops);
949 
950 		/*
951 		 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
952 		 * based on wait_for_completion(), tag them as 'nonatomic'.
953 		 */
954 		(*dai_links)->nonatomic = true;
955 		(*dai_links)->ch_maps = codec_maps;
956 
957 		list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
958 			if (sof_end->dai_info->init)
959 				sof_end->dai_info->init(card, *dai_links,
960 							sof_end->codec_info,
961 							playback);
962 		}
963 
964 		(*dai_links)++;
965 	}
966 
967 	return 0;
968 }
969 
create_sdw_dailinks(struct snd_soc_card * card,struct snd_soc_dai_link ** dai_links,int * be_id,struct asoc_sdw_dailink * sof_dais,struct snd_soc_codec_conf ** codec_conf)970 static int create_sdw_dailinks(struct snd_soc_card *card,
971 			       struct snd_soc_dai_link **dai_links, int *be_id,
972 			       struct asoc_sdw_dailink *sof_dais,
973 			       struct snd_soc_codec_conf **codec_conf)
974 {
975 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
976 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
977 	int ret, i;
978 
979 	for (i = 0; i < SDW_INTEL_MAX_LINKS; i++)
980 		intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE;
981 
982 	/* generate DAI links by each sdw link */
983 	while (sof_dais->initialised) {
984 		int current_be_id = 0;
985 
986 		ret = create_sdw_dailink(card, sof_dais, dai_links,
987 					 &current_be_id, codec_conf);
988 		if (ret)
989 			return ret;
990 
991 		/* Update the be_id to match the highest ID used for SDW link */
992 		if (*be_id < current_be_id)
993 			*be_id = current_be_id;
994 
995 		sof_dais++;
996 	}
997 
998 	return 0;
999 }
1000 
create_ssp_dailinks(struct snd_soc_card * card,struct snd_soc_dai_link ** dai_links,int * be_id,struct asoc_sdw_codec_info * ssp_info,unsigned long ssp_mask)1001 static int create_ssp_dailinks(struct snd_soc_card *card,
1002 			       struct snd_soc_dai_link **dai_links, int *be_id,
1003 			       struct asoc_sdw_codec_info *ssp_info,
1004 			       unsigned long ssp_mask)
1005 {
1006 	struct device *dev = card->dev;
1007 	int i, j = 0;
1008 	int ret;
1009 
1010 	for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) {
1011 		char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
1012 		char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
1013 		char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
1014 						  ssp_info->acpi_id, j++);
1015 		if (!name || !cpu_dai_name || !codec_name)
1016 			return -ENOMEM;
1017 
1018 		int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
1019 		int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
1020 
1021 		ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
1022 						    playback, capture, cpu_dai_name,
1023 						    "dummy", codec_name,
1024 						    ssp_info->dais[0].dai_name, 1, NULL,
1025 						    ssp_info->ops);
1026 		if (ret)
1027 			return ret;
1028 
1029 		ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0);
1030 		if (ret < 0)
1031 			return ret;
1032 
1033 		(*dai_links)++;
1034 	}
1035 
1036 	return 0;
1037 }
1038 
create_dmic_dailinks(struct snd_soc_card * card,struct snd_soc_dai_link ** dai_links,int * be_id)1039 static int create_dmic_dailinks(struct snd_soc_card *card,
1040 				struct snd_soc_dai_link **dai_links, int *be_id)
1041 {
1042 	struct device *dev = card->dev;
1043 	int ret;
1044 
1045 	ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01",
1046 					    0, 1, // DMIC only supports capture
1047 					    "DMIC01 Pin", "dummy",
1048 					    "dmic-codec", "dmic-hifi", 1,
1049 					    asoc_sdw_dmic_init, NULL);
1050 	if (ret)
1051 		return ret;
1052 
1053 	(*dai_links)++;
1054 
1055 	ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k",
1056 					    0, 1, // DMIC only supports capture
1057 					    "DMIC16k Pin", "dummy",
1058 					    "dmic-codec", "dmic-hifi", 1,
1059 					    /* don't call asoc_sdw_dmic_init() twice */
1060 					    NULL, NULL);
1061 	if (ret)
1062 		return ret;
1063 
1064 	(*dai_links)++;
1065 
1066 	return 0;
1067 }
1068 
create_hdmi_dailinks(struct snd_soc_card * card,struct snd_soc_dai_link ** dai_links,int * be_id,int hdmi_num)1069 static int create_hdmi_dailinks(struct snd_soc_card *card,
1070 				struct snd_soc_dai_link **dai_links, int *be_id,
1071 				int hdmi_num)
1072 {
1073 	struct device *dev = card->dev;
1074 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1075 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
1076 	int i, ret;
1077 
1078 	for (i = 0; i < hdmi_num; i++) {
1079 		char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
1080 		char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
1081 		if (!name || !cpu_dai_name)
1082 			return -ENOMEM;
1083 
1084 		char *codec_name, *codec_dai_name;
1085 
1086 		if (intel_ctx->hdmi.idisp_codec) {
1087 			codec_name = "ehdaudio0D2";
1088 			codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
1089 							"intel-hdmi-hifi%d", i + 1);
1090 		} else {
1091 			codec_name = "snd-soc-dummy";
1092 			codec_dai_name = "snd-soc-dummy-dai";
1093 		}
1094 
1095 		if (!codec_dai_name)
1096 			return -ENOMEM;
1097 
1098 		ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
1099 						    1, 0, // HDMI only supports playback
1100 						    cpu_dai_name, "dummy",
1101 						    codec_name, codec_dai_name, 1,
1102 						    i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
1103 		if (ret)
1104 			return ret;
1105 
1106 		(*dai_links)++;
1107 	}
1108 
1109 	return 0;
1110 }
1111 
create_bt_dailinks(struct snd_soc_card * card,struct snd_soc_dai_link ** dai_links,int * be_id)1112 static int create_bt_dailinks(struct snd_soc_card *card,
1113 			      struct snd_soc_dai_link **dai_links, int *be_id)
1114 {
1115 	struct device *dev = card->dev;
1116 	int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
1117 			SOF_BT_OFFLOAD_SSP_SHIFT;
1118 	char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
1119 	char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
1120 	if (!name || !cpu_dai_name)
1121 		return -ENOMEM;
1122 
1123 	int ret;
1124 
1125 	ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
1126 					    1, 1, cpu_dai_name, "dummy",
1127 					    snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name,
1128 					    1, NULL, NULL);
1129 	if (ret)
1130 		return ret;
1131 
1132 	(*dai_links)++;
1133 
1134 	return 0;
1135 }
1136 
sof_card_dai_links_create(struct snd_soc_card * card)1137 static int sof_card_dai_links_create(struct snd_soc_card *card)
1138 {
1139 	struct device *dev = card->dev;
1140 	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
1141 	int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
1142 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1143 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
1144 	struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
1145 	struct snd_soc_codec_conf *codec_conf;
1146 	struct asoc_sdw_codec_info *ssp_info;
1147 	struct asoc_sdw_endpoint *sof_ends;
1148 	struct asoc_sdw_dailink *sof_dais;
1149 	int num_devs = 0;
1150 	int num_ends = 0;
1151 	struct snd_soc_dai_link *dai_links;
1152 	int num_links;
1153 	int be_id = 0;
1154 	int hdmi_num;
1155 	unsigned long ssp_mask;
1156 	int ret;
1157 
1158 	ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
1159 	if (ret < 0) {
1160 		dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
1161 		return ret;
1162 	}
1163 
1164 	/*
1165 	 * One per DAI link, worst case is a DAI link for every endpoint, also
1166 	 * add one additional to act as a terminator such that code can iterate
1167 	 * until it hits an uninitialised DAI.
1168 	 */
1169 	sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL);
1170 	if (!sof_dais)
1171 		return -ENOMEM;
1172 
1173 	/* One per endpoint, ie. each DAI on each codec/amp */
1174 	sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
1175 	if (!sof_ends) {
1176 		ret = -ENOMEM;
1177 		goto err_dai;
1178 	}
1179 
1180 	ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
1181 	if (ret < 0)
1182 		goto err_end;
1183 
1184 	sdw_be_num = ret;
1185 
1186 	/*
1187 	 * on generic tgl platform, I2S or sdw mode is supported
1188 	 * based on board rework. A ACPI device is registered in
1189 	 * system only when I2S mode is supported, not sdw mode.
1190 	 * Here check ACPI ID to confirm I2S is supported.
1191 	 */
1192 	ssp_info = asoc_sdw_find_codec_info_acpi(mach->id);
1193 	if (ssp_info) {
1194 		ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
1195 		ssp_num = hweight_long(ssp_mask);
1196 	}
1197 
1198 	if (mach_params->codec_mask & IDISP_CODEC_MASK)
1199 		intel_ctx->hdmi.idisp_codec = true;
1200 
1201 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
1202 		hdmi_num = SOF_TGL_HDMI_COUNT;
1203 	else
1204 		hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
1205 
1206 	/* enable dmic01 & dmic16k */
1207 	if (ctx->ignore_internal_dmic) {
1208 		dev_dbg(dev, "SoundWire DMIC is used, ignoring internal DMIC\n");
1209 		mach_params->dmic_num = 0;
1210 	} else if (mach_params->dmic_num) {
1211 		dmic_num = 2;
1212 	} else if (sof_sdw_quirk & SOC_SDW_PCH_DMIC) {
1213 		dmic_num = 2;
1214 		/*
1215 		 * mach_params->dmic_num will be used to set the cfg-mics value of
1216 		 * card->components string. Set it to the default value.
1217 		 */
1218 		mach_params->dmic_num = DMIC_DEFAULT_CHANNELS;
1219 	}
1220 
1221 	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
1222 		bt_num = 1;
1223 
1224 	dev_dbg(dev, "DAI link numbers: sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
1225 		sdw_be_num, ssp_num, dmic_num,
1226 		intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
1227 
1228 	codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
1229 	if (!codec_conf) {
1230 		ret = -ENOMEM;
1231 		goto err_end;
1232 	}
1233 
1234 	/* allocate BE dailinks */
1235 	num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
1236 	dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
1237 	if (!dai_links) {
1238 		ret = -ENOMEM;
1239 		goto err_end;
1240 	}
1241 
1242 	card->codec_conf = codec_conf;
1243 	card->num_configs = num_devs;
1244 	card->dai_link = dai_links;
1245 	card->num_links = num_links;
1246 
1247 	/* SDW */
1248 	if (sdw_be_num) {
1249 		ret = create_sdw_dailinks(card, &dai_links, &be_id,
1250 					  sof_dais, &codec_conf);
1251 		if (ret)
1252 			goto err_end;
1253 	}
1254 
1255 	/* SSP */
1256 	if (ssp_num) {
1257 		ret = create_ssp_dailinks(card, &dai_links, &be_id,
1258 					  ssp_info, ssp_mask);
1259 		if (ret)
1260 			goto err_end;
1261 	}
1262 
1263 	/* dmic */
1264 	if (dmic_num) {
1265 		ret = create_dmic_dailinks(card, &dai_links, &be_id);
1266 		if (ret)
1267 			goto err_end;
1268 	}
1269 
1270 	/* HDMI */
1271 	ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num);
1272 	if (ret)
1273 		goto err_end;
1274 
1275 	/* BT */
1276 	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
1277 		ret = create_bt_dailinks(card, &dai_links, &be_id);
1278 		if (ret)
1279 			goto err_end;
1280 	}
1281 
1282 	WARN_ON(codec_conf != card->codec_conf + card->num_configs);
1283 	WARN_ON(dai_links != card->dai_link + card->num_links);
1284 
1285 err_end:
1286 	kfree(sof_ends);
1287 err_dai:
1288 	kfree(sof_dais);
1289 
1290 	return ret;
1291 }
1292 
sof_sdw_card_late_probe(struct snd_soc_card * card)1293 static int sof_sdw_card_late_probe(struct snd_soc_card *card)
1294 {
1295 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1296 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
1297 	int ret = 0;
1298 
1299 	ret = asoc_sdw_card_late_probe(card);
1300 	if (ret < 0)
1301 		return ret;
1302 
1303 	if (intel_ctx->hdmi.idisp_codec)
1304 		ret = sof_sdw_hdmi_card_late_probe(card);
1305 
1306 	return ret;
1307 }
1308 
sof_sdw_add_dai_link(struct snd_soc_card * card,struct snd_soc_dai_link * link)1309 static int sof_sdw_add_dai_link(struct snd_soc_card *card,
1310 				struct snd_soc_dai_link *link)
1311 {
1312 	struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
1313 	struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
1314 
1315 	/* Ignore the HDMI PCM link if iDisp is not present */
1316 	if (strstr(link->stream_name, "HDMI") && !intel_ctx->hdmi.idisp_codec)
1317 		link->ignore = true;
1318 
1319 	return 0;
1320 }
1321 
mc_probe(struct platform_device * pdev)1322 static int mc_probe(struct platform_device *pdev)
1323 {
1324 	struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
1325 	struct snd_soc_card *card;
1326 	struct asoc_sdw_mc_private *ctx;
1327 	struct intel_mc_ctx *intel_ctx;
1328 	int amp_num = 0, i;
1329 	int ret;
1330 
1331 	dev_dbg(&pdev->dev, "Entry\n");
1332 
1333 	intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL);
1334 	if (!intel_ctx)
1335 		return -ENOMEM;
1336 
1337 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1338 	if (!ctx)
1339 		return -ENOMEM;
1340 
1341 	ctx->private = intel_ctx;
1342 	ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
1343 	card = &ctx->card;
1344 	card->dev = &pdev->dev;
1345 	card->name = "soundwire";
1346 	card->owner = THIS_MODULE;
1347 	card->late_probe = sof_sdw_card_late_probe;
1348 	card->add_dai_link = sof_sdw_add_dai_link;
1349 
1350 	snd_soc_card_set_drvdata(card, ctx);
1351 
1352 	if (mach->mach_params.subsystem_id_set) {
1353 		snd_soc_card_set_pci_ssid(card,
1354 					  mach->mach_params.subsystem_vendor,
1355 					  mach->mach_params.subsystem_device);
1356 		sof_sdw_check_ssid_quirk(mach);
1357 	}
1358 
1359 	dmi_check_system(sof_sdw_quirk_table);
1360 
1361 	if (quirk_override != -1) {
1362 		dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
1363 			 sof_sdw_quirk, quirk_override);
1364 		sof_sdw_quirk = quirk_override;
1365 	}
1366 
1367 	log_quirks(card->dev);
1368 
1369 	ctx->mc_quirk = sof_sdw_quirk;
1370 	/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
1371 	for (i = 0; i < ctx->codec_info_list_count; i++)
1372 		codec_info_list[i].amp_num = 0;
1373 
1374 	ret = sof_card_dai_links_create(card);
1375 	if (ret < 0)
1376 		return ret;
1377 
1378 	/*
1379 	 * the default amp_num is zero for each codec and
1380 	 * amp_num will only be increased for active amp
1381 	 * codecs on used platform
1382 	 */
1383 	for (i = 0; i < ctx->codec_info_list_count; i++)
1384 		amp_num += codec_info_list[i].amp_num;
1385 
1386 	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1387 					  " cfg-amp:%d", amp_num);
1388 	if (!card->components)
1389 		return -ENOMEM;
1390 
1391 	if (mach->mach_params.dmic_num) {
1392 		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1393 						  "%s mic:dmic cfg-mics:%d",
1394 						  card->components,
1395 						  mach->mach_params.dmic_num);
1396 		if (!card->components)
1397 			return -ENOMEM;
1398 	}
1399 
1400 	/* Register the card */
1401 	ret = devm_snd_soc_register_card(card->dev, card);
1402 	if (ret) {
1403 		dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
1404 		asoc_sdw_mc_dailink_exit_loop(card);
1405 		return ret;
1406 	}
1407 
1408 	platform_set_drvdata(pdev, card);
1409 
1410 	return ret;
1411 }
1412 
mc_remove(struct platform_device * pdev)1413 static void mc_remove(struct platform_device *pdev)
1414 {
1415 	struct snd_soc_card *card = platform_get_drvdata(pdev);
1416 
1417 	asoc_sdw_mc_dailink_exit_loop(card);
1418 }
1419 
1420 static const struct platform_device_id mc_id_table[] = {
1421 	{ "sof_sdw", },
1422 	{}
1423 };
1424 MODULE_DEVICE_TABLE(platform, mc_id_table);
1425 
1426 static struct platform_driver sof_sdw_driver = {
1427 	.driver = {
1428 		.name = "sof_sdw",
1429 		.pm = &snd_soc_pm_ops,
1430 	},
1431 	.probe = mc_probe,
1432 	.remove = mc_remove,
1433 	.id_table = mc_id_table,
1434 };
1435 
1436 module_platform_driver(sof_sdw_driver);
1437 
1438 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1439 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1440 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1441 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1442 MODULE_LICENSE("GPL v2");
1443 MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
1444 MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
1445