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