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