1
2
3
4
5
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
17unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
18static int quirk_override = -1;
19module_param_named(quirk, quirk_override, int, 0444);
20MODULE_PARM_DESC(quirk, "Board-specific quirk override");
21
22#define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0)
23
24static void log_quirks(struct device *dev)
25{
26 if (SOF_RT711_JDSRC(sof_sdw_quirk))
27 dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
28 SOF_RT711_JDSRC(sof_sdw_quirk));
29 if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
30 dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
31 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
32 dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
33 if (sof_sdw_quirk & SOF_SDW_PCH_DMIC)
34 dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n");
35 if (SOF_SSP_GET_PORT(sof_sdw_quirk))
36 dev_dbg(dev, "SSP port %ld\n",
37 SOF_SSP_GET_PORT(sof_sdw_quirk));
38 if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX)
39 dev_dbg(dev, "quirk SOF_RT715_DAI_ID_FIX enabled\n");
40 if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
41 dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n");
42}
43
44static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
45{
46 sof_sdw_quirk = (unsigned long)id->driver_data;
47 return 1;
48}
49
50static const struct dmi_system_id sof_sdw_quirk_table[] = {
51 {
52 .callback = sof_sdw_quirk_cb,
53 .matches = {
54 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
55 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
56 },
57 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
58 SOF_RT715_DAI_ID_FIX),
59 },
60 {
61
62 .callback = sof_sdw_quirk_cb,
63 .matches = {
64 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
65 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
66 },
67 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
68 SOF_RT715_DAI_ID_FIX),
69 },
70 {
71 .callback = sof_sdw_quirk_cb,
72 .matches = {
73 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
74 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
75 },
76 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
77 SOF_RT715_DAI_ID_FIX |
78 SOF_SDW_FOUR_SPK),
79 },
80 {
81 .callback = sof_sdw_quirk_cb,
82 .matches = {
83 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
84 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
85 },
86 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
87 SOF_RT715_DAI_ID_FIX |
88 SOF_SDW_FOUR_SPK),
89 },
90 {
91 .callback = sof_sdw_quirk_cb,
92 .matches = {
93 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
94 DMI_MATCH(DMI_PRODUCT_NAME,
95 "Tiger Lake Client Platform"),
96 },
97 .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
98 SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
99 SOF_SSP_PORT(SOF_I2S_SSP2)),
100 },
101 {
102 .callback = sof_sdw_quirk_cb,
103 .matches = {
104 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
105 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
106 },
107 .driver_data = (void *)SOF_SDW_PCH_DMIC,
108 },
109 {
110 .callback = sof_sdw_quirk_cb,
111 .matches = {
112 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
113 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
114 },
115 .driver_data = (void *)SOF_SDW_PCH_DMIC,
116 },
117 {
118 .callback = sof_sdw_quirk_cb,
119 .matches = {
120 DMI_MATCH(DMI_SYS_VENDOR, "Google"),
121 DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
122 },
123 .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
124 SOF_SDW_FOUR_SPK),
125 },
126
127 {}
128};
129
130static struct snd_soc_codec_conf codec_conf[] = {
131 {
132 .dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"),
133 .name_prefix = "rt711",
134 },
135
136 {
137 .dlc = COMP_CODEC_CONF("i2c-10EC1308:00"),
138 .name_prefix = "rt1308-1",
139 },
140
141 {
142 .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0"),
143 .name_prefix = "rt1308-1",
144 },
145
146 {
147 .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:0"),
148 .name_prefix = "rt1308-1",
149 },
150 {
151 .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:2"),
152 .name_prefix = "rt1308-2",
153 },
154
155 {
156 .dlc = COMP_CODEC_CONF("sdw:2:25d:1308:0"),
157 .name_prefix = "rt1308-2",
158 },
159 {
160 .dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"),
161 .name_prefix = "rt715",
162 },
163
164 {
165 .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:3"),
166 .name_prefix = "Right",
167 },
168 {
169 .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:7"),
170 .name_prefix = "Left",
171 },
172 {
173 .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"),
174 .name_prefix = "rt5682",
175 },
176};
177
178static struct snd_soc_dai_link_component dmic_component[] = {
179 {
180 .name = "dmic-codec",
181 .dai_name = "dmic-hifi",
182 }
183};
184
185static struct snd_soc_dai_link_component platform_component[] = {
186 {
187
188 .name = "0000:00:1f.3"
189 }
190};
191
192
193int sdw_startup(struct snd_pcm_substream *substream)
194{
195 return sdw_startup_stream(substream);
196}
197
198void sdw_shutdown(struct snd_pcm_substream *substream)
199{
200 sdw_shutdown_stream(substream);
201}
202
203static const struct snd_soc_ops sdw_ops = {
204 .startup = sdw_startup,
205 .shutdown = sdw_shutdown,
206};
207
208static struct sof_sdw_codec_info codec_info_list[] = {
209 {
210 .id = 0x700,
211 .direction = {true, true},
212 .dai_name = "rt700-aif1",
213 .init = sof_sdw_rt700_init,
214 },
215 {
216 .id = 0x711,
217 .direction = {true, true},
218 .dai_name = "rt711-aif1",
219 .init = sof_sdw_rt711_init,
220 .exit = sof_sdw_rt711_exit,
221 },
222 {
223 .id = 0x1308,
224 .acpi_id = "10EC1308",
225 .direction = {true, false},
226 .dai_name = "rt1308-aif",
227 .ops = &sof_sdw_rt1308_i2s_ops,
228 .init = sof_sdw_rt1308_init,
229 },
230 {
231 .id = 0x715,
232 .direction = {false, true},
233 .dai_name = "rt715-aif2",
234 .init = sof_sdw_rt715_init,
235 },
236 {
237 .id = 0x8373,
238 .direction = {true, true},
239 .dai_name = "max98373-aif1",
240 .init = sof_sdw_mx8373_init,
241 .codec_card_late_probe = sof_sdw_mx8373_late_probe,
242 },
243 {
244 .id = 0x5682,
245 .direction = {true, true},
246 .dai_name = "rt5682-sdw",
247 .init = sof_sdw_rt5682_init,
248 },
249};
250
251static inline int find_codec_info_part(unsigned int part_id)
252{
253 int i;
254
255 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
256 if (part_id == codec_info_list[i].id)
257 break;
258
259 if (i == ARRAY_SIZE(codec_info_list))
260 return -EINVAL;
261
262 return i;
263}
264
265static inline int find_codec_info_acpi(const u8 *acpi_id)
266{
267 int i;
268
269 if (!acpi_id[0])
270 return -EINVAL;
271
272 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
273 if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
274 ACPI_ID_LEN))
275 break;
276
277 if (i == ARRAY_SIZE(codec_info_list))
278 return -EINVAL;
279
280 return i;
281}
282
283
284
285
286
287
288static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
289 int *sdw_be_num, int *sdw_cpu_dai_num)
290{
291 const struct snd_soc_acpi_link_adr *link;
292 bool group_visited[SDW_MAX_GROUPS];
293 bool no_aggregation;
294 int i;
295
296 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
297 *sdw_cpu_dai_num = 0;
298 *sdw_be_num = 0;
299
300 if (!links)
301 return -EINVAL;
302
303 for (i = 0; i < SDW_MAX_GROUPS; i++)
304 group_visited[i] = false;
305
306 for (link = links; link->num_adr; link++) {
307 const struct snd_soc_acpi_endpoint *endpoint;
308 int part_id, codec_index;
309 int stream;
310 u64 adr;
311
312 adr = link->adr_d->adr;
313 part_id = SDW_PART_ID(adr);
314 codec_index = find_codec_info_part(part_id);
315 if (codec_index < 0)
316 return codec_index;
317
318 endpoint = link->adr_d->endpoints;
319
320
321 for_each_pcm_streams(stream) {
322 if (!codec_info_list[codec_index].direction[stream])
323 continue;
324
325 (*sdw_cpu_dai_num)++;
326
327
328 if (!endpoint->aggregated || no_aggregation ||
329 !group_visited[endpoint->group_id])
330 (*sdw_be_num)++;
331 }
332
333 if (endpoint->aggregated)
334 group_visited[endpoint->group_id] = true;
335 }
336
337 return 0;
338}
339
340static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
341 char *name, int playback, int capture,
342 struct snd_soc_dai_link_component *cpus,
343 int cpus_num,
344 struct snd_soc_dai_link_component *codecs,
345 int codecs_num,
346 int (*init)(struct snd_soc_pcm_runtime *rtd),
347 const struct snd_soc_ops *ops)
348{
349 dai_links->id = be_id;
350 dai_links->name = name;
351 dai_links->platforms = platform_component;
352 dai_links->num_platforms = ARRAY_SIZE(platform_component);
353 dai_links->nonatomic = true;
354 dai_links->no_pcm = 1;
355 dai_links->cpus = cpus;
356 dai_links->num_cpus = cpus_num;
357 dai_links->codecs = codecs;
358 dai_links->num_codecs = codecs_num;
359 dai_links->dpcm_playback = playback;
360 dai_links->dpcm_capture = capture;
361 dai_links->init = init;
362 dai_links->ops = ops;
363}
364
365static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
366 unsigned int sdw_version,
367 unsigned int mfg_id,
368 unsigned int part_id,
369 unsigned int class_id,
370 int index_in_link
371 )
372{
373 int i;
374
375 for (i = 0; i < link->num_adr; i++) {
376 unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
377 u64 adr;
378
379
380 if (i == index_in_link)
381 continue;
382
383 adr = link->adr_d[i].adr;
384
385 sdw1_version = SDW_VERSION(adr);
386 mfg1_id = SDW_MFG_ID(adr);
387 part1_id = SDW_PART_ID(adr);
388 class1_id = SDW_CLASS_ID(adr);
389
390 if (sdw_version == sdw1_version &&
391 mfg_id == mfg1_id &&
392 part_id == part1_id &&
393 class_id == class1_id)
394 return false;
395 }
396
397 return true;
398}
399
400static int create_codec_dai_name(struct device *dev,
401 const struct snd_soc_acpi_link_adr *link,
402 struct snd_soc_dai_link_component *codec,
403 int offset)
404{
405 int i;
406
407 for (i = 0; i < link->num_adr; i++) {
408 unsigned int sdw_version, unique_id, mfg_id;
409 unsigned int link_id, part_id, class_id;
410 int codec_index, comp_index;
411 char *codec_str;
412 u64 adr;
413
414 adr = link->adr_d[i].adr;
415
416 sdw_version = SDW_VERSION(adr);
417 link_id = SDW_DISCO_LINK_ID(adr);
418 unique_id = SDW_UNIQUE_ID(adr);
419 mfg_id = SDW_MFG_ID(adr);
420 part_id = SDW_PART_ID(adr);
421 class_id = SDW_CLASS_ID(adr);
422
423 comp_index = i + offset;
424 if (is_unique_device(link, sdw_version, mfg_id, part_id,
425 class_id, i)) {
426 codec_str = "sdw:%x:%x:%x:%x";
427 codec[comp_index].name =
428 devm_kasprintf(dev, GFP_KERNEL, codec_str,
429 link_id, mfg_id, part_id,
430 class_id);
431 } else {
432 codec_str = "sdw:%x:%x:%x:%x:%x";
433 codec[comp_index].name =
434 devm_kasprintf(dev, GFP_KERNEL, codec_str,
435 link_id, mfg_id, part_id,
436 class_id, unique_id);
437 }
438
439 if (!codec[comp_index].name)
440 return -ENOMEM;
441
442 codec_index = find_codec_info_part(part_id);
443 if (codec_index < 0)
444 return codec_index;
445
446 codec[comp_index].dai_name =
447 codec_info_list[codec_index].dai_name;
448 }
449
450 return 0;
451}
452
453static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
454 struct snd_soc_dai_link *dai_links,
455 bool playback, int group_id)
456{
457 int i;
458
459 do {
460
461
462
463
464
465 for (i = 0; i < link->num_adr; i++) {
466 unsigned int part_id;
467 int codec_index;
468
469 part_id = SDW_PART_ID(link->adr_d[i].adr);
470 codec_index = find_codec_info_part(part_id);
471
472 if (codec_index < 0)
473 return codec_index;
474
475 if (link->adr_d[i].endpoints->group_id != group_id)
476 continue;
477 if (codec_info_list[codec_index].init)
478 codec_info_list[codec_index].init(link,
479 dai_links,
480 &codec_info_list[codec_index],
481 playback);
482 }
483 link++;
484 } while (link->mask && group_id);
485
486 return 0;
487}
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
504 struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
505 int *codec_num, int *group_id,
506 bool *group_generated)
507{
508 const struct snd_soc_acpi_adr_device *adr_d;
509 const struct snd_soc_acpi_link_adr *adr_next;
510 bool no_aggregation;
511 int index = 0;
512
513 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
514 *codec_num = adr_link->num_adr;
515 adr_d = adr_link->adr_d;
516
517
518 if (!is_power_of_2(adr_link->mask))
519 return -EINVAL;
520
521 cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
522 if (!adr_d->endpoints->aggregated || no_aggregation) {
523 *cpu_dai_num = 1;
524 *group_id = 0;
525 return 0;
526 }
527
528 *group_id = adr_d->endpoints->group_id;
529
530
531 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
532 adr_next++) {
533 const struct snd_soc_acpi_endpoint *endpoint;
534
535 endpoint = adr_next->adr_d->endpoints;
536 if (!endpoint->aggregated ||
537 endpoint->group_id != *group_id)
538 continue;
539
540
541 if (!is_power_of_2(adr_next->mask))
542 return -EINVAL;
543
544 if (index >= SDW_MAX_CPU_DAIS) {
545 dev_err(dev, " cpu_dai_id array overflows");
546 return -EINVAL;
547 }
548
549 cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
550 *codec_num += adr_next->num_adr;
551 }
552
553
554
555
556
557 group_generated[*group_id] = true;
558 *cpu_dai_num = index;
559
560 return 0;
561}
562
563static int create_sdw_dailink(struct device *dev, int *be_index,
564 struct snd_soc_dai_link *dai_links,
565 int sdw_be_num, int sdw_cpu_dai_num,
566 struct snd_soc_dai_link_component *cpus,
567 const struct snd_soc_acpi_link_adr *link,
568 int *cpu_id, bool *group_generated)
569{
570 const struct snd_soc_acpi_link_adr *link_next;
571 struct snd_soc_dai_link_component *codecs;
572 int cpu_dai_id[SDW_MAX_CPU_DAIS];
573 int cpu_dai_num, cpu_dai_index;
574 unsigned int part_id, group_id;
575 int codec_idx = 0;
576 int i = 0, j = 0;
577 int codec_index;
578 int codec_num;
579 int stream;
580 int ret;
581 int k;
582
583 ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
584 &group_id, group_generated);
585 if (ret)
586 return ret;
587
588 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
589 if (!codecs)
590 return -ENOMEM;
591
592
593 for (link_next = link; link_next && link_next->num_adr &&
594 i < cpu_dai_num; link_next++) {
595 const struct snd_soc_acpi_endpoint *endpoints;
596
597 endpoints = link_next->adr_d->endpoints;
598 if (group_id && (!endpoints->aggregated ||
599 endpoints->group_id != group_id))
600 continue;
601
602
603 if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
604 continue;
605
606 ret = create_codec_dai_name(dev, link_next, codecs, codec_idx);
607 if (ret < 0)
608 return ret;
609
610
611 i++;
612 codec_idx += link_next->num_adr;
613 }
614
615
616 part_id = SDW_PART_ID(link->adr_d[0].adr);
617 codec_index = find_codec_info_part(part_id);
618 if (codec_index < 0)
619 return codec_index;
620
621 cpu_dai_index = *cpu_id;
622 for_each_pcm_streams(stream) {
623 char *name, *cpu_name;
624 int playback, capture;
625 static const char * const sdw_stream_name[] = {
626 "SDW%d-Playback",
627 "SDW%d-Capture",
628 };
629
630 if (!codec_info_list[codec_index].direction[stream])
631 continue;
632
633
634 name = devm_kasprintf(dev, GFP_KERNEL,
635 sdw_stream_name[stream], cpu_dai_id[0]);
636 if (!name)
637 return -ENOMEM;
638
639
640
641
642
643 for (k = 0; k < cpu_dai_num; k++) {
644 cpu_name = devm_kasprintf(dev, GFP_KERNEL,
645 "SDW%d Pin%d", cpu_dai_id[k],
646 j + SDW_INTEL_BIDIR_PDI_BASE);
647 if (!cpu_name)
648 return -ENOMEM;
649
650 if (cpu_dai_index >= sdw_cpu_dai_num) {
651 dev_err(dev, "invalid cpu dai index %d",
652 cpu_dai_index);
653 return -EINVAL;
654 }
655
656 cpus[cpu_dai_index++].dai_name = cpu_name;
657 }
658
659 if (*be_index >= sdw_be_num) {
660 dev_err(dev, " invalid be dai index %d", *be_index);
661 return -EINVAL;
662 }
663
664 if (*cpu_id >= sdw_cpu_dai_num) {
665 dev_err(dev, " invalid cpu dai index %d", *cpu_id);
666 return -EINVAL;
667 }
668
669 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
670 capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
671 init_dai_link(dai_links + *be_index, *be_index, name,
672 playback, capture,
673 cpus + *cpu_id, cpu_dai_num,
674 codecs, codec_num,
675 NULL, &sdw_ops);
676
677 ret = set_codec_init_func(link, dai_links + (*be_index)++,
678 playback, group_id);
679 if (ret < 0) {
680 dev_err(dev, "failed to init codec %d", codec_index);
681 return ret;
682 }
683
684 *cpu_id += cpu_dai_num;
685 j++;
686 }
687
688 return 0;
689}
690
691
692
693
694
695
696static inline int get_next_be_id(struct snd_soc_dai_link *links,
697 int be_id)
698{
699 return links[be_id - 1].id + 1;
700}
701
702#define IDISP_CODEC_MASK 0x4
703
704static int sof_card_dai_links_create(struct device *dev,
705 struct snd_soc_acpi_mach *mach,
706 struct snd_soc_card *card)
707{
708 int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
709 struct mc_private *ctx = snd_soc_card_get_drvdata(card);
710 struct snd_soc_dai_link_component *idisp_components;
711 struct snd_soc_dai_link_component *ssp_components;
712 struct snd_soc_acpi_mach_params *mach_params;
713 const struct snd_soc_acpi_link_adr *adr_link;
714 struct snd_soc_dai_link_component *cpus;
715 bool group_generated[SDW_MAX_GROUPS];
716 int ssp_codec_index, ssp_mask;
717 struct snd_soc_dai_link *links;
718 int num_links, link_id = 0;
719 char *name, *cpu_name;
720 int total_cpu_dai_num;
721 int sdw_cpu_dai_num;
722 int i, j, be_id = 0;
723 int cpu_id = 0;
724 int comp_num;
725 int ret;
726
727
728 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
729 codec_info_list[i].amp_num = 0;
730
731 hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ?
732 SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT;
733
734 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
735
736
737
738
739
740
741 ssp_codec_index = find_codec_info_acpi(mach->id);
742 ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
743 comp_num = hdmi_num + ssp_num;
744
745 mach_params = &mach->mach_params;
746 ret = get_sdw_dailink_info(mach_params->links,
747 &sdw_be_num, &sdw_cpu_dai_num);
748 if (ret < 0) {
749 dev_err(dev, "failed to get sdw link info %d", ret);
750 return ret;
751 }
752
753 if (mach_params->codec_mask & IDISP_CODEC_MASK)
754 ctx->idisp_codec = true;
755
756
757 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0;
758 comp_num += dmic_num;
759
760 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
761 dmic_num, ctx->idisp_codec ? hdmi_num : 0);
762
763
764 num_links = comp_num + sdw_be_num;
765 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
766
767
768 total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
769 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
770 GFP_KERNEL);
771
772 if (!links || !cpus)
773 return -ENOMEM;
774
775
776 if (!sdw_be_num)
777 goto SSP;
778
779 adr_link = mach_params->links;
780 if (!adr_link)
781 return -EINVAL;
782
783
784
785
786
787
788 for (i = 0; i < SDW_MAX_GROUPS; i++)
789 group_generated[i] = false;
790
791
792 for (; adr_link->num_adr; adr_link++) {
793 const struct snd_soc_acpi_endpoint *endpoint;
794
795 endpoint = adr_link->adr_d->endpoints;
796 if (endpoint->aggregated && !endpoint->group_id) {
797 dev_err(dev, "invalid group id on link %x",
798 adr_link->mask);
799 continue;
800 }
801
802
803 if (endpoint->aggregated &&
804 group_generated[endpoint->group_id])
805 continue;
806
807 ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
808 sdw_cpu_dai_num, cpus, adr_link,
809 &cpu_id, group_generated);
810 if (ret < 0) {
811 dev_err(dev, "failed to create dai link %d", be_id);
812 return -ENOMEM;
813 }
814 }
815
816
817 link_id = be_id;
818
819
820 be_id = get_next_be_id(links, be_id);
821
822SSP:
823
824 if (!ssp_num)
825 goto DMIC;
826
827 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
828 struct sof_sdw_codec_info *info;
829 int playback, capture;
830 char *codec_name;
831
832 if (!(ssp_mask & 0x1))
833 continue;
834
835 name = devm_kasprintf(dev, GFP_KERNEL,
836 "SSP%d-Codec", i);
837 if (!name)
838 return -ENOMEM;
839
840 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
841 if (!cpu_name)
842 return -ENOMEM;
843
844 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
845 GFP_KERNEL);
846 if (!ssp_components)
847 return -ENOMEM;
848
849 info = &codec_info_list[ssp_codec_index];
850 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
851 info->acpi_id, j++);
852 if (!codec_name)
853 return -ENOMEM;
854
855 ssp_components->name = codec_name;
856 ssp_components->dai_name = info->dai_name;
857 cpus[cpu_id].dai_name = cpu_name;
858
859 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
860 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
861 init_dai_link(links + link_id, be_id, name,
862 playback, capture,
863 cpus + cpu_id, 1,
864 ssp_components, 1,
865 NULL, info->ops);
866
867 ret = info->init(NULL, links + link_id, info, 0);
868 if (ret < 0)
869 return ret;
870
871 INC_ID(be_id, cpu_id, link_id);
872 }
873
874DMIC:
875
876 if (dmic_num > 0) {
877 cpus[cpu_id].dai_name = "DMIC01 Pin";
878 init_dai_link(links + link_id, be_id, "dmic01",
879 0, 1,
880 cpus + cpu_id, 1,
881 dmic_component, 1,
882 sof_sdw_dmic_init, NULL);
883 INC_ID(be_id, cpu_id, link_id);
884
885 cpus[cpu_id].dai_name = "DMIC16k Pin";
886 init_dai_link(links + link_id, be_id, "dmic16k",
887 0, 1,
888 cpus + cpu_id, 1,
889 dmic_component, 1,
890
891 NULL, NULL);
892 INC_ID(be_id, cpu_id, link_id);
893 }
894
895
896 if (hdmi_num > 0) {
897 idisp_components = devm_kcalloc(dev, hdmi_num,
898 sizeof(*idisp_components),
899 GFP_KERNEL);
900 if (!idisp_components)
901 return -ENOMEM;
902 }
903
904 for (i = 0; i < hdmi_num; i++) {
905 name = devm_kasprintf(dev, GFP_KERNEL,
906 "iDisp%d", i + 1);
907 if (!name)
908 return -ENOMEM;
909
910 if (ctx->idisp_codec) {
911 idisp_components[i].name = "ehdaudio0D2";
912 idisp_components[i].dai_name = devm_kasprintf(dev,
913 GFP_KERNEL,
914 "intel-hdmi-hifi%d",
915 i + 1);
916 if (!idisp_components[i].dai_name)
917 return -ENOMEM;
918 } else {
919 idisp_components[i].name = "snd-soc-dummy";
920 idisp_components[i].dai_name = "snd-soc-dummy-dai";
921 }
922
923 cpu_name = devm_kasprintf(dev, GFP_KERNEL,
924 "iDisp%d Pin", i + 1);
925 if (!cpu_name)
926 return -ENOMEM;
927
928 cpus[cpu_id].dai_name = cpu_name;
929 init_dai_link(links + link_id, be_id, name,
930 1, 0,
931 cpus + cpu_id, 1,
932 idisp_components + i, 1,
933 sof_sdw_hdmi_init, NULL);
934 INC_ID(be_id, cpu_id, link_id);
935 }
936
937 card->dai_link = links;
938 card->num_links = num_links;
939
940 return 0;
941}
942
943static int sof_sdw_card_late_probe(struct snd_soc_card *card)
944{
945 int i, ret;
946
947 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
948 if (!codec_info_list[i].late_probe)
949 continue;
950
951 ret = codec_info_list[i].codec_card_late_probe(card);
952 if (ret < 0)
953 return ret;
954 }
955
956 return sof_sdw_hdmi_card_late_probe(card);
957}
958
959
960static const char sdw_card_long_name[] = "Intel Soundwire SOF";
961
962static struct snd_soc_card card_sof_sdw = {
963 .name = "soundwire",
964 .owner = THIS_MODULE,
965 .late_probe = sof_sdw_card_late_probe,
966 .codec_conf = codec_conf,
967 .num_configs = ARRAY_SIZE(codec_conf),
968};
969
970static int mc_probe(struct platform_device *pdev)
971{
972 struct snd_soc_card *card = &card_sof_sdw;
973 struct snd_soc_acpi_mach *mach;
974 struct mc_private *ctx;
975 int amp_num = 0, i;
976 int ret;
977
978 dev_dbg(&pdev->dev, "Entry %s\n", __func__);
979
980 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
981 if (!ctx)
982 return -ENOMEM;
983
984 dmi_check_system(sof_sdw_quirk_table);
985
986 if (quirk_override != -1) {
987 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
988 sof_sdw_quirk, quirk_override);
989 sof_sdw_quirk = quirk_override;
990 }
991 log_quirks(&pdev->dev);
992
993 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
994
995 card->dev = &pdev->dev;
996 snd_soc_card_set_drvdata(card, ctx);
997
998 mach = pdev->dev.platform_data;
999 ret = sof_card_dai_links_create(&pdev->dev, mach,
1000 card);
1001 if (ret < 0)
1002 return ret;
1003
1004 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
1005
1006
1007
1008
1009
1010
1011 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1012 amp_num += codec_info_list[i].amp_num;
1013
1014 card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1015 "cfg-spk:%d cfg-amp:%d",
1016 (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
1017 ? 4 : 2, amp_num);
1018 if (!card->components)
1019 return -ENOMEM;
1020
1021 card->long_name = sdw_card_long_name;
1022
1023
1024 ret = devm_snd_soc_register_card(&pdev->dev, card);
1025 if (ret) {
1026 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
1027 return ret;
1028 }
1029
1030 platform_set_drvdata(pdev, card);
1031
1032 return ret;
1033}
1034
1035static struct platform_driver sof_sdw_driver = {
1036 .driver = {
1037 .name = "sof_sdw",
1038 .pm = &snd_soc_pm_ops,
1039 },
1040 .probe = mc_probe,
1041};
1042
1043module_platform_driver(sof_sdw_driver);
1044
1045MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1046MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1047MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1048MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1049MODULE_LICENSE("GPL v2");
1050MODULE_ALIAS("platform:sof_sdw");
1051