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