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 {
53 .callback = sof_sdw_quirk_cb,
54 .matches = {
55 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
56 DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
57 },
58 .driver_data = (void *)SOF_SDW_PCH_DMIC,
59 },
60 {
61 .callback = sof_sdw_quirk_cb,
62 .matches = {
63 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
64 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
65 },
66 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
67 SOF_RT715_DAI_ID_FIX),
68 },
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, "0983")
75 },
76 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
77 SOF_RT715_DAI_ID_FIX),
78 },
79 {
80 .callback = sof_sdw_quirk_cb,
81 .matches = {
82 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
83 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
84 },
85 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
86 SOF_RT715_DAI_ID_FIX |
87 SOF_SDW_FOUR_SPK),
88 },
89 {
90 .callback = sof_sdw_quirk_cb,
91 .matches = {
92 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
93 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
94 },
95 .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
96 SOF_RT715_DAI_ID_FIX |
97 SOF_SDW_FOUR_SPK),
98 },
99
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
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 SOF_RT711_JD_SRC_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 SOF_RT711_JD_SRC_JD2 |
129 SOF_RT715_DAI_ID_FIX),
130 },
131 {
132 .callback = sof_sdw_quirk_cb,
133 .matches = {
134 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
135 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
136 },
137 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
138 SOF_RT711_JD_SRC_JD2 |
139 SOF_RT715_DAI_ID_FIX |
140 SOF_SDW_FOUR_SPK),
141 },
142 {
143 .callback = sof_sdw_quirk_cb,
144 .matches = {
145 DMI_MATCH(DMI_SYS_VENDOR, "Google"),
146 DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
147 },
148 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
149 SOF_SDW_PCH_DMIC |
150 SOF_SDW_FOUR_SPK |
151 SOF_BT_OFFLOAD_SSP(2) |
152 SOF_SSP_BT_OFFLOAD_PRESENT),
153 },
154 {
155 .callback = sof_sdw_quirk_cb,
156 .matches = {
157 DMI_MATCH(DMI_SYS_VENDOR, "Google"),
158 DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
159 },
160 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
161 SOF_SDW_PCH_DMIC |
162 SOF_SDW_FOUR_SPK),
163 },
164 {
165
166
167
168
169
170
171 .callback = sof_sdw_quirk_cb,
172 .matches = {
173 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
174 DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
175 },
176 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
177 SOF_SDW_PCH_DMIC |
178 SOF_RT711_JD_SRC_JD2),
179 },
180
181 {
182 .callback = sof_sdw_quirk_cb,
183 .matches = {
184 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
185 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
186 },
187 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
188 SOF_RT711_JD_SRC_JD2 |
189 SOF_RT715_DAI_ID_FIX |
190 SOF_SDW_FOUR_SPK),
191 },
192
193 {
194 .callback = sof_sdw_quirk_cb,
195 .matches = {
196 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
197 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
198 },
199 .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
200 SOF_SDW_TGL_HDMI |
201 SOF_RT715_DAI_ID_FIX |
202 SOF_BT_OFFLOAD_SSP(2) |
203 SOF_SSP_BT_OFFLOAD_PRESENT),
204 },
205 {
206 .callback = sof_sdw_quirk_cb,
207 .matches = {
208 DMI_MATCH(DMI_SYS_VENDOR, "Google"),
209 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
210 },
211 .driver_data = (void *)(SOF_SDW_TGL_HDMI |
212 SOF_SDW_PCH_DMIC |
213 SOF_SDW_FOUR_SPK |
214 SOF_BT_OFFLOAD_SSP(2) |
215 SOF_SSP_BT_OFFLOAD_PRESENT),
216 },
217 {}
218};
219
220static struct snd_soc_dai_link_component dmic_component[] = {
221 {
222 .name = "dmic-codec",
223 .dai_name = "dmic-hifi",
224 }
225};
226
227static struct snd_soc_dai_link_component platform_component[] = {
228 {
229
230 .name = "0000:00:1f.3"
231 }
232};
233
234
235int sdw_startup(struct snd_pcm_substream *substream)
236{
237 return sdw_startup_stream(substream);
238}
239
240int sdw_prepare(struct snd_pcm_substream *substream)
241{
242 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
243 struct sdw_stream_runtime *sdw_stream;
244 struct snd_soc_dai *dai;
245
246
247 dai = asoc_rtd_to_cpu(rtd, 0);
248
249 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
250
251 if (IS_ERR(sdw_stream)) {
252 dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
253 return PTR_ERR(sdw_stream);
254 }
255
256 return sdw_prepare_stream(sdw_stream);
257}
258
259int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
260{
261 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
262 struct sdw_stream_runtime *sdw_stream;
263 struct snd_soc_dai *dai;
264 int ret;
265
266
267 dai = asoc_rtd_to_cpu(rtd, 0);
268
269 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
270
271 if (IS_ERR(sdw_stream)) {
272 dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
273 return PTR_ERR(sdw_stream);
274 }
275
276 switch (cmd) {
277 case SNDRV_PCM_TRIGGER_START:
278 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
279 case SNDRV_PCM_TRIGGER_RESUME:
280 ret = sdw_enable_stream(sdw_stream);
281 break;
282
283 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
284 case SNDRV_PCM_TRIGGER_SUSPEND:
285 case SNDRV_PCM_TRIGGER_STOP:
286 ret = sdw_disable_stream(sdw_stream);
287 break;
288 default:
289 ret = -EINVAL;
290 break;
291 }
292
293 if (ret)
294 dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret);
295
296 return ret;
297}
298
299int sdw_hw_free(struct snd_pcm_substream *substream)
300{
301 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
302 struct sdw_stream_runtime *sdw_stream;
303 struct snd_soc_dai *dai;
304
305
306 dai = asoc_rtd_to_cpu(rtd, 0);
307
308 sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
309
310 if (IS_ERR(sdw_stream)) {
311 dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
312 return PTR_ERR(sdw_stream);
313 }
314
315 return sdw_deprepare_stream(sdw_stream);
316}
317
318void sdw_shutdown(struct snd_pcm_substream *substream)
319{
320 sdw_shutdown_stream(substream);
321}
322
323static const struct snd_soc_ops sdw_ops = {
324 .startup = sdw_startup,
325 .prepare = sdw_prepare,
326 .trigger = sdw_trigger,
327 .hw_free = sdw_hw_free,
328 .shutdown = sdw_shutdown,
329};
330
331static struct sof_sdw_codec_info codec_info_list[] = {
332 {
333 .part_id = 0x700,
334 .direction = {true, true},
335 .dai_name = "rt700-aif1",
336 .init = sof_sdw_rt700_init,
337 },
338 {
339 .part_id = 0x711,
340 .version_id = 3,
341 .direction = {true, true},
342 .dai_name = "rt711-sdca-aif1",
343 .init = sof_sdw_rt711_sdca_init,
344 .exit = sof_sdw_rt711_sdca_exit,
345 },
346 {
347 .part_id = 0x711,
348 .version_id = 2,
349 .direction = {true, true},
350 .dai_name = "rt711-aif1",
351 .init = sof_sdw_rt711_init,
352 .exit = sof_sdw_rt711_exit,
353 },
354 {
355 .part_id = 0x1308,
356 .acpi_id = "10EC1308",
357 .direction = {true, false},
358 .dai_name = "rt1308-aif",
359 .ops = &sof_sdw_rt1308_i2s_ops,
360 .init = sof_sdw_rt1308_init,
361 },
362 {
363 .part_id = 0x1316,
364 .direction = {true, true},
365 .dai_name = "rt1316-aif",
366 .init = sof_sdw_rt1316_init,
367 },
368 {
369 .part_id = 0x714,
370 .version_id = 3,
371 .direction = {false, true},
372 .ignore_pch_dmic = true,
373 .dai_name = "rt715-aif2",
374 .init = sof_sdw_rt715_sdca_init,
375 },
376 {
377 .part_id = 0x715,
378 .version_id = 3,
379 .direction = {false, true},
380 .ignore_pch_dmic = true,
381 .dai_name = "rt715-aif2",
382 .init = sof_sdw_rt715_sdca_init,
383 },
384 {
385 .part_id = 0x714,
386 .version_id = 2,
387 .direction = {false, true},
388 .ignore_pch_dmic = true,
389 .dai_name = "rt715-aif2",
390 .init = sof_sdw_rt715_init,
391 },
392 {
393 .part_id = 0x715,
394 .version_id = 2,
395 .direction = {false, true},
396 .ignore_pch_dmic = true,
397 .dai_name = "rt715-aif2",
398 .init = sof_sdw_rt715_init,
399 },
400 {
401 .part_id = 0x8373,
402 .direction = {true, true},
403 .dai_name = "max98373-aif1",
404 .init = sof_sdw_mx8373_init,
405 .codec_card_late_probe = sof_sdw_mx8373_late_probe,
406 },
407 {
408 .part_id = 0x5682,
409 .direction = {true, true},
410 .dai_name = "rt5682-sdw",
411 .init = sof_sdw_rt5682_init,
412 },
413};
414
415static inline int find_codec_info_part(u64 adr)
416{
417 unsigned int part_id, sdw_version;
418 int i;
419
420 part_id = SDW_PART_ID(adr);
421 sdw_version = SDW_VERSION(adr);
422 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
423
424
425
426
427 if (part_id == codec_info_list[i].part_id &&
428 (!codec_info_list[i].version_id ||
429 sdw_version == codec_info_list[i].version_id))
430 return i;
431
432 return -EINVAL;
433
434}
435
436static inline int find_codec_info_acpi(const u8 *acpi_id)
437{
438 int i;
439
440 if (!acpi_id[0])
441 return -EINVAL;
442
443 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
444 if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
445 ACPI_ID_LEN))
446 break;
447
448 if (i == ARRAY_SIZE(codec_info_list))
449 return -EINVAL;
450
451 return i;
452}
453
454
455
456
457
458
459static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
460 int *sdw_be_num, int *sdw_cpu_dai_num)
461{
462 const struct snd_soc_acpi_link_adr *link;
463 bool group_visited[SDW_MAX_GROUPS];
464 bool no_aggregation;
465 int i;
466
467 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
468 *sdw_cpu_dai_num = 0;
469 *sdw_be_num = 0;
470
471 if (!links)
472 return -EINVAL;
473
474 for (i = 0; i < SDW_MAX_GROUPS; i++)
475 group_visited[i] = false;
476
477 for (link = links; link->num_adr; link++) {
478 const struct snd_soc_acpi_endpoint *endpoint;
479 int codec_index;
480 int stream;
481 u64 adr;
482
483 adr = link->adr_d->adr;
484 codec_index = find_codec_info_part(adr);
485 if (codec_index < 0)
486 return codec_index;
487
488 endpoint = link->adr_d->endpoints;
489
490
491 for_each_pcm_streams(stream) {
492 if (!codec_info_list[codec_index].direction[stream])
493 continue;
494
495 (*sdw_cpu_dai_num)++;
496
497
498 if (!endpoint->aggregated || no_aggregation ||
499 !group_visited[endpoint->group_id])
500 (*sdw_be_num)++;
501 }
502
503 if (endpoint->aggregated)
504 group_visited[endpoint->group_id] = true;
505 }
506
507 return 0;
508}
509
510static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
511 int be_id, char *name, int playback, int capture,
512 struct snd_soc_dai_link_component *cpus, int cpus_num,
513 struct snd_soc_dai_link_component *codecs, int codecs_num,
514 int (*init)(struct snd_soc_pcm_runtime *rtd),
515 const struct snd_soc_ops *ops)
516{
517 dev_dbg(dev, "create dai link %s, id %d\n", name, be_id);
518 dai_links->id = be_id;
519 dai_links->name = name;
520 dai_links->platforms = platform_component;
521 dai_links->num_platforms = ARRAY_SIZE(platform_component);
522 dai_links->no_pcm = 1;
523 dai_links->cpus = cpus;
524 dai_links->num_cpus = cpus_num;
525 dai_links->codecs = codecs;
526 dai_links->num_codecs = codecs_num;
527 dai_links->dpcm_playback = playback;
528 dai_links->dpcm_capture = capture;
529 dai_links->init = init;
530 dai_links->ops = ops;
531}
532
533static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
534 unsigned int sdw_version,
535 unsigned int mfg_id,
536 unsigned int part_id,
537 unsigned int class_id,
538 int index_in_link
539 )
540{
541 int i;
542
543 for (i = 0; i < link->num_adr; i++) {
544 unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
545 u64 adr;
546
547
548 if (i == index_in_link)
549 continue;
550
551 adr = link->adr_d[i].adr;
552
553 sdw1_version = SDW_VERSION(adr);
554 mfg1_id = SDW_MFG_ID(adr);
555 part1_id = SDW_PART_ID(adr);
556 class1_id = SDW_CLASS_ID(adr);
557
558 if (sdw_version == sdw1_version &&
559 mfg_id == mfg1_id &&
560 part_id == part1_id &&
561 class_id == class1_id)
562 return false;
563 }
564
565 return true;
566}
567
568static int create_codec_dai_name(struct device *dev,
569 const struct snd_soc_acpi_link_adr *link,
570 struct snd_soc_dai_link_component *codec,
571 int offset,
572 struct snd_soc_codec_conf *codec_conf,
573 int codec_count,
574 int *codec_conf_index)
575{
576 int i;
577
578
579 if (*codec_conf_index + link->num_adr > codec_count) {
580 dev_err(dev, "codec_conf: out-of-bounds access requested\n");
581 return -EINVAL;
582 }
583
584 for (i = 0; i < link->num_adr; i++) {
585 unsigned int sdw_version, unique_id, mfg_id;
586 unsigned int link_id, part_id, class_id;
587 int codec_index, comp_index;
588 char *codec_str;
589 u64 adr;
590
591 adr = link->adr_d[i].adr;
592
593 sdw_version = SDW_VERSION(adr);
594 link_id = SDW_DISCO_LINK_ID(adr);
595 unique_id = SDW_UNIQUE_ID(adr);
596 mfg_id = SDW_MFG_ID(adr);
597 part_id = SDW_PART_ID(adr);
598 class_id = SDW_CLASS_ID(adr);
599
600 comp_index = i + offset;
601 if (is_unique_device(link, sdw_version, mfg_id, part_id,
602 class_id, i)) {
603 codec_str = "sdw:%01x:%04x:%04x:%02x";
604 codec[comp_index].name =
605 devm_kasprintf(dev, GFP_KERNEL, codec_str,
606 link_id, mfg_id, part_id,
607 class_id);
608 } else {
609 codec_str = "sdw:%01x:%04x:%04x:%02x:%01x";
610 codec[comp_index].name =
611 devm_kasprintf(dev, GFP_KERNEL, codec_str,
612 link_id, mfg_id, part_id,
613 class_id, unique_id);
614 }
615
616 if (!codec[comp_index].name)
617 return -ENOMEM;
618
619 codec_index = find_codec_info_part(adr);
620 if (codec_index < 0)
621 return codec_index;
622
623 codec[comp_index].dai_name =
624 codec_info_list[codec_index].dai_name;
625
626 codec_conf[*codec_conf_index].dlc = codec[comp_index];
627 codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
628
629 ++*codec_conf_index;
630 }
631
632 return 0;
633}
634
635static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
636 struct snd_soc_dai_link *dai_links,
637 bool playback, int group_id)
638{
639 int i;
640
641 do {
642
643
644
645
646
647 for (i = 0; i < link->num_adr; i++) {
648 int codec_index;
649
650 codec_index = find_codec_info_part(link->adr_d[i].adr);
651
652 if (codec_index < 0)
653 return codec_index;
654
655 if (link->adr_d[i].endpoints->group_id != group_id)
656 continue;
657 if (codec_info_list[codec_index].init)
658 codec_info_list[codec_index].init(link,
659 dai_links,
660 &codec_info_list[codec_index],
661 playback);
662 }
663 link++;
664 } while (link->mask && group_id);
665
666 return 0;
667}
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
684 struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
685 int *codec_num, unsigned int *group_id,
686 bool *group_generated)
687{
688 const struct snd_soc_acpi_adr_device *adr_d;
689 const struct snd_soc_acpi_link_adr *adr_next;
690 bool no_aggregation;
691 int index = 0;
692
693 no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
694 *codec_num = adr_link->num_adr;
695 adr_d = adr_link->adr_d;
696
697
698 if (!is_power_of_2(adr_link->mask))
699 return -EINVAL;
700
701 cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
702 if (!adr_d->endpoints->aggregated || no_aggregation) {
703 *cpu_dai_num = 1;
704 *group_id = 0;
705 return 0;
706 }
707
708 *group_id = adr_d->endpoints->group_id;
709
710
711 for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
712 adr_next++) {
713 const struct snd_soc_acpi_endpoint *endpoint;
714
715 endpoint = adr_next->adr_d->endpoints;
716 if (!endpoint->aggregated ||
717 endpoint->group_id != *group_id)
718 continue;
719
720
721 if (!is_power_of_2(adr_next->mask))
722 return -EINVAL;
723
724 if (index >= SDW_MAX_CPU_DAIS) {
725 dev_err(dev, " cpu_dai_id array overflows");
726 return -EINVAL;
727 }
728
729 cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
730 *codec_num += adr_next->num_adr;
731 }
732
733
734
735
736
737 group_generated[*group_id] = true;
738 *cpu_dai_num = index;
739
740 return 0;
741}
742
743static int create_sdw_dailink(struct device *dev, int *be_index,
744 struct snd_soc_dai_link *dai_links,
745 int sdw_be_num, int sdw_cpu_dai_num,
746 struct snd_soc_dai_link_component *cpus,
747 const struct snd_soc_acpi_link_adr *link,
748 int *cpu_id, bool *group_generated,
749 struct snd_soc_codec_conf *codec_conf,
750 int codec_count,
751 int *codec_conf_index,
752 bool *ignore_pch_dmic)
753{
754 const struct snd_soc_acpi_link_adr *link_next;
755 struct snd_soc_dai_link_component *codecs;
756 int cpu_dai_id[SDW_MAX_CPU_DAIS];
757 int cpu_dai_num, cpu_dai_index;
758 unsigned int group_id;
759 int codec_idx = 0;
760 int i = 0, j = 0;
761 int codec_index;
762 int codec_num;
763 int stream;
764 int ret;
765 int k;
766
767 ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
768 &group_id, group_generated);
769 if (ret)
770 return ret;
771
772 codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
773 if (!codecs)
774 return -ENOMEM;
775
776
777 for (link_next = link; link_next && link_next->num_adr &&
778 i < cpu_dai_num; link_next++) {
779 const struct snd_soc_acpi_endpoint *endpoints;
780
781 endpoints = link_next->adr_d->endpoints;
782 if (group_id && (!endpoints->aggregated ||
783 endpoints->group_id != group_id))
784 continue;
785
786
787 if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
788 continue;
789
790 ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
791 codec_conf, codec_count, codec_conf_index);
792 if (ret < 0)
793 return ret;
794
795
796 i++;
797 codec_idx += link_next->num_adr;
798 }
799
800
801 codec_index = find_codec_info_part(link->adr_d[0].adr);
802 if (codec_index < 0)
803 return codec_index;
804
805 if (codec_info_list[codec_index].ignore_pch_dmic)
806 *ignore_pch_dmic = true;
807
808 cpu_dai_index = *cpu_id;
809 for_each_pcm_streams(stream) {
810 char *name, *cpu_name;
811 int playback, capture;
812 static const char * const sdw_stream_name[] = {
813 "SDW%d-Playback",
814 "SDW%d-Capture",
815 };
816
817 if (!codec_info_list[codec_index].direction[stream])
818 continue;
819
820
821 name = devm_kasprintf(dev, GFP_KERNEL,
822 sdw_stream_name[stream], cpu_dai_id[0]);
823 if (!name)
824 return -ENOMEM;
825
826
827
828
829
830 for (k = 0; k < cpu_dai_num; k++) {
831 cpu_name = devm_kasprintf(dev, GFP_KERNEL,
832 "SDW%d Pin%d", cpu_dai_id[k],
833 j + SDW_INTEL_BIDIR_PDI_BASE);
834 if (!cpu_name)
835 return -ENOMEM;
836
837 if (cpu_dai_index >= sdw_cpu_dai_num) {
838 dev_err(dev, "invalid cpu dai index %d",
839 cpu_dai_index);
840 return -EINVAL;
841 }
842
843 cpus[cpu_dai_index++].dai_name = cpu_name;
844 }
845
846 if (*be_index >= sdw_be_num) {
847 dev_err(dev, " invalid be dai index %d", *be_index);
848 return -EINVAL;
849 }
850
851 if (*cpu_id >= sdw_cpu_dai_num) {
852 dev_err(dev, " invalid cpu dai index %d", *cpu_id);
853 return -EINVAL;
854 }
855
856 playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
857 capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
858 init_dai_link(dev, dai_links + *be_index, *be_index, name,
859 playback, capture,
860 cpus + *cpu_id, cpu_dai_num,
861 codecs, codec_num,
862 NULL, &sdw_ops);
863
864 ret = set_codec_init_func(link, dai_links + (*be_index)++,
865 playback, group_id);
866 if (ret < 0) {
867 dev_err(dev, "failed to init codec %d", codec_index);
868 return ret;
869 }
870
871 *cpu_id += cpu_dai_num;
872 j++;
873 }
874
875 return 0;
876}
877
878
879
880
881
882
883static inline int get_next_be_id(struct snd_soc_dai_link *links,
884 int be_id)
885{
886 return links[be_id - 1].id + 1;
887}
888
889#define IDISP_CODEC_MASK 0x4
890
891static int sof_card_codec_conf_alloc(struct device *dev,
892 struct snd_soc_acpi_mach_params *mach_params,
893 struct snd_soc_codec_conf **codec_conf,
894 int *codec_conf_count)
895{
896 const struct snd_soc_acpi_link_adr *adr_link;
897 struct snd_soc_codec_conf *c_conf;
898 int num_codecs = 0;
899 int i;
900
901 adr_link = mach_params->links;
902 if (!adr_link)
903 return -EINVAL;
904
905
906 for (; adr_link->num_adr; adr_link++) {
907 for (i = 0; i < adr_link->num_adr; i++) {
908 if (!adr_link->adr_d[i].name_prefix) {
909 dev_err(dev, "codec 0x%llx does not have a name prefix\n",
910 adr_link->adr_d[i].adr);
911 return -EINVAL;
912 }
913 }
914 num_codecs += adr_link->num_adr;
915 }
916
917 c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
918 if (!c_conf)
919 return -ENOMEM;
920
921 *codec_conf = c_conf;
922 *codec_conf_count = num_codecs;
923
924 return 0;
925}
926
927static int sof_card_dai_links_create(struct device *dev,
928 struct snd_soc_acpi_mach *mach,
929 struct snd_soc_card *card)
930{
931 int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
932 struct mc_private *ctx = snd_soc_card_get_drvdata(card);
933 struct snd_soc_dai_link_component *idisp_components;
934 struct snd_soc_dai_link_component *ssp_components;
935 struct snd_soc_acpi_mach_params *mach_params;
936 const struct snd_soc_acpi_link_adr *adr_link;
937 struct snd_soc_dai_link_component *cpus;
938 struct snd_soc_codec_conf *codec_conf;
939 bool ignore_pch_dmic = false;
940 int codec_conf_count;
941 int codec_conf_index = 0;
942 bool group_generated[SDW_MAX_GROUPS];
943 int ssp_codec_index, ssp_mask;
944 struct snd_soc_dai_link *links;
945 int num_links, link_id = 0;
946 char *name, *cpu_name;
947 int total_cpu_dai_num;
948 int sdw_cpu_dai_num;
949 int i, j, be_id = 0;
950 int cpu_id = 0;
951 int comp_num;
952 int ret;
953
954 mach_params = &mach->mach_params;
955
956
957 ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count);
958 if (ret < 0)
959 return ret;
960
961
962 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
963 codec_info_list[i].amp_num = 0;
964
965 if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
966 hdmi_num = SOF_TGL_HDMI_COUNT;
967 else
968 hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
969
970 ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
971
972
973
974
975
976
977 ssp_codec_index = find_codec_info_acpi(mach->id);
978 ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
979 comp_num = hdmi_num + ssp_num;
980
981 ret = get_sdw_dailink_info(mach_params->links,
982 &sdw_be_num, &sdw_cpu_dai_num);
983 if (ret < 0) {
984 dev_err(dev, "failed to get sdw link info %d", ret);
985 return ret;
986 }
987
988 if (mach_params->codec_mask & IDISP_CODEC_MASK)
989 ctx->idisp_codec = true;
990
991
992 dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
993 comp_num += dmic_num;
994
995 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
996 comp_num++;
997
998 dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
999 dmic_num, ctx->idisp_codec ? hdmi_num : 0);
1000
1001
1002 num_links = comp_num + sdw_be_num;
1003 links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
1004
1005
1006 total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
1007 cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
1008 GFP_KERNEL);
1009
1010 if (!links || !cpus)
1011 return -ENOMEM;
1012
1013
1014 if (!sdw_be_num)
1015 goto SSP;
1016
1017 adr_link = mach_params->links;
1018 if (!adr_link)
1019 return -EINVAL;
1020
1021
1022
1023
1024
1025
1026 for (i = 0; i < SDW_MAX_GROUPS; i++)
1027 group_generated[i] = false;
1028
1029
1030 for (; adr_link->num_adr; adr_link++) {
1031 const struct snd_soc_acpi_endpoint *endpoint;
1032
1033 endpoint = adr_link->adr_d->endpoints;
1034 if (endpoint->aggregated && !endpoint->group_id) {
1035 dev_err(dev, "invalid group id on link %x",
1036 adr_link->mask);
1037 continue;
1038 }
1039
1040
1041 if (endpoint->aggregated &&
1042 group_generated[endpoint->group_id])
1043 continue;
1044
1045 ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
1046 sdw_cpu_dai_num, cpus, adr_link,
1047 &cpu_id, group_generated,
1048 codec_conf, codec_conf_count,
1049 &codec_conf_index,
1050 &ignore_pch_dmic);
1051 if (ret < 0) {
1052 dev_err(dev, "failed to create dai link %d", be_id);
1053 return -ENOMEM;
1054 }
1055 }
1056
1057
1058 link_id = be_id;
1059
1060
1061 be_id = get_next_be_id(links, be_id);
1062
1063SSP:
1064
1065 if (!ssp_num)
1066 goto DMIC;
1067
1068 for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
1069 struct sof_sdw_codec_info *info;
1070 int playback, capture;
1071 char *codec_name;
1072
1073 if (!(ssp_mask & 0x1))
1074 continue;
1075
1076 name = devm_kasprintf(dev, GFP_KERNEL,
1077 "SSP%d-Codec", i);
1078 if (!name)
1079 return -ENOMEM;
1080
1081 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
1082 if (!cpu_name)
1083 return -ENOMEM;
1084
1085 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
1086 GFP_KERNEL);
1087 if (!ssp_components)
1088 return -ENOMEM;
1089
1090 info = &codec_info_list[ssp_codec_index];
1091 codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
1092 info->acpi_id, j++);
1093 if (!codec_name)
1094 return -ENOMEM;
1095
1096 ssp_components->name = codec_name;
1097 ssp_components->dai_name = info->dai_name;
1098 cpus[cpu_id].dai_name = cpu_name;
1099
1100 playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
1101 capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
1102 init_dai_link(dev, links + link_id, be_id, name,
1103 playback, capture,
1104 cpus + cpu_id, 1,
1105 ssp_components, 1,
1106 NULL, info->ops);
1107
1108 ret = info->init(NULL, links + link_id, info, 0);
1109 if (ret < 0)
1110 return ret;
1111
1112 INC_ID(be_id, cpu_id, link_id);
1113 }
1114
1115DMIC:
1116
1117 if (dmic_num > 0) {
1118 if (ignore_pch_dmic) {
1119 dev_warn(dev, "Ignoring PCH DMIC\n");
1120 goto HDMI;
1121 }
1122 cpus[cpu_id].dai_name = "DMIC01 Pin";
1123 init_dai_link(dev, links + link_id, be_id, "dmic01",
1124 0, 1,
1125 cpus + cpu_id, 1,
1126 dmic_component, 1,
1127 sof_sdw_dmic_init, NULL);
1128 INC_ID(be_id, cpu_id, link_id);
1129
1130 cpus[cpu_id].dai_name = "DMIC16k Pin";
1131 init_dai_link(dev, links + link_id, be_id, "dmic16k",
1132 0, 1,
1133 cpus + cpu_id, 1,
1134 dmic_component, 1,
1135
1136 NULL, NULL);
1137 INC_ID(be_id, cpu_id, link_id);
1138 }
1139
1140HDMI:
1141
1142 if (hdmi_num > 0) {
1143 idisp_components = devm_kcalloc(dev, hdmi_num,
1144 sizeof(*idisp_components),
1145 GFP_KERNEL);
1146 if (!idisp_components)
1147 return -ENOMEM;
1148 }
1149
1150 for (i = 0; i < hdmi_num; i++) {
1151 name = devm_kasprintf(dev, GFP_KERNEL,
1152 "iDisp%d", i + 1);
1153 if (!name)
1154 return -ENOMEM;
1155
1156 if (ctx->idisp_codec) {
1157 idisp_components[i].name = "ehdaudio0D2";
1158 idisp_components[i].dai_name = devm_kasprintf(dev,
1159 GFP_KERNEL,
1160 "intel-hdmi-hifi%d",
1161 i + 1);
1162 if (!idisp_components[i].dai_name)
1163 return -ENOMEM;
1164 } else {
1165 idisp_components[i].name = "snd-soc-dummy";
1166 idisp_components[i].dai_name = "snd-soc-dummy-dai";
1167 }
1168
1169 cpu_name = devm_kasprintf(dev, GFP_KERNEL,
1170 "iDisp%d Pin", i + 1);
1171 if (!cpu_name)
1172 return -ENOMEM;
1173
1174 cpus[cpu_id].dai_name = cpu_name;
1175 init_dai_link(dev, links + link_id, be_id, name,
1176 1, 0,
1177 cpus + cpu_id, 1,
1178 idisp_components + i, 1,
1179 sof_sdw_hdmi_init, NULL);
1180 INC_ID(be_id, cpu_id, link_id);
1181 }
1182
1183 if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
1184 int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
1185 SOF_BT_OFFLOAD_SSP_SHIFT;
1186
1187 name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
1188 if (!name)
1189 return -ENOMEM;
1190
1191 ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
1192 GFP_KERNEL);
1193 if (!ssp_components)
1194 return -ENOMEM;
1195
1196 ssp_components->name = "snd-soc-dummy";
1197 ssp_components->dai_name = "snd-soc-dummy-dai";
1198
1199 cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
1200 if (!cpu_name)
1201 return -ENOMEM;
1202
1203 cpus[cpu_id].dai_name = cpu_name;
1204 init_dai_link(dev, links + link_id, be_id, name, 1, 1,
1205 cpus + cpu_id, 1, ssp_components, 1, NULL, NULL);
1206 }
1207
1208 card->dai_link = links;
1209 card->num_links = num_links;
1210
1211 card->codec_conf = codec_conf;
1212 card->num_configs = codec_conf_count;
1213
1214 return 0;
1215}
1216
1217static int sof_sdw_card_late_probe(struct snd_soc_card *card)
1218{
1219 int i, ret;
1220
1221 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1222 if (!codec_info_list[i].late_probe)
1223 continue;
1224
1225 ret = codec_info_list[i].codec_card_late_probe(card);
1226 if (ret < 0)
1227 return ret;
1228 }
1229
1230 return sof_sdw_hdmi_card_late_probe(card);
1231}
1232
1233
1234static const char sdw_card_long_name[] = "Intel Soundwire SOF";
1235
1236static struct snd_soc_card card_sof_sdw = {
1237 .name = "soundwire",
1238 .owner = THIS_MODULE,
1239 .late_probe = sof_sdw_card_late_probe,
1240};
1241
1242static int mc_probe(struct platform_device *pdev)
1243{
1244 struct snd_soc_card *card = &card_sof_sdw;
1245 struct snd_soc_acpi_mach *mach;
1246 struct mc_private *ctx;
1247 int amp_num = 0, i;
1248 int ret;
1249
1250 dev_dbg(&pdev->dev, "Entry %s\n", __func__);
1251
1252 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1253 if (!ctx)
1254 return -ENOMEM;
1255
1256 dmi_check_system(sof_sdw_quirk_table);
1257
1258 if (quirk_override != -1) {
1259 dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1260 sof_sdw_quirk, quirk_override);
1261 sof_sdw_quirk = quirk_override;
1262 }
1263 log_quirks(&pdev->dev);
1264
1265 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
1266
1267 card->dev = &pdev->dev;
1268 snd_soc_card_set_drvdata(card, ctx);
1269
1270 mach = pdev->dev.platform_data;
1271 ret = sof_card_dai_links_create(&pdev->dev, mach,
1272 card);
1273 if (ret < 0)
1274 return ret;
1275
1276
1277
1278
1279
1280
1281 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1282 amp_num += codec_info_list[i].amp_num;
1283
1284 card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1285 "cfg-spk:%d cfg-amp:%d",
1286 (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
1287 ? 4 : 2, amp_num);
1288 if (!card->components)
1289 return -ENOMEM;
1290
1291 if (mach->mach_params.dmic_num) {
1292 card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1293 "%s mic:dmic cfg-mics:%d",
1294 card->components,
1295 mach->mach_params.dmic_num);
1296 if (!card->components)
1297 return -ENOMEM;
1298 }
1299
1300 card->long_name = sdw_card_long_name;
1301
1302
1303 ret = devm_snd_soc_register_card(&pdev->dev, card);
1304 if (ret) {
1305 dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
1306 return ret;
1307 }
1308
1309 platform_set_drvdata(pdev, card);
1310
1311 return ret;
1312}
1313
1314static int mc_remove(struct platform_device *pdev)
1315{
1316 struct snd_soc_card *card = platform_get_drvdata(pdev);
1317 struct snd_soc_dai_link *link;
1318 int ret;
1319 int i, j;
1320
1321 for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1322 if (!codec_info_list[i].exit)
1323 continue;
1324
1325
1326
1327
1328 for_each_card_prelinks(card, j, link) {
1329 if (!strcmp(link->codecs[0].dai_name,
1330 codec_info_list[i].dai_name)) {
1331 ret = codec_info_list[i].exit(&pdev->dev, link);
1332 if (ret)
1333 dev_warn(&pdev->dev,
1334 "codec exit failed %d\n",
1335 ret);
1336 break;
1337 }
1338 }
1339 }
1340
1341 return 0;
1342}
1343
1344static struct platform_driver sof_sdw_driver = {
1345 .driver = {
1346 .name = "sof_sdw",
1347 .pm = &snd_soc_pm_ops,
1348 },
1349 .probe = mc_probe,
1350 .remove = mc_remove,
1351};
1352
1353module_platform_driver(sof_sdw_driver);
1354
1355MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1356MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1357MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1358MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1359MODULE_LICENSE("GPL v2");
1360MODULE_ALIAS("platform:sof_sdw");
1361MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1362MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1363