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