1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2023 Intel Corporation
4
5 #include <sound/soc.h>
6 #include "../common/soc-intel-quirks.h"
7 #include "hda_dsp_common.h"
8 #include "sof_board_helpers.h"
9
10 /*
11 * Intel HDMI DAI Link
12 */
hdmi_init(struct snd_soc_pcm_runtime * rtd)13 static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
14 {
15 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
16 struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
17
18 ctx->hdmi.hdmi_comp = dai->component;
19
20 return 0;
21 }
22
sof_intel_board_card_late_probe(struct snd_soc_card * card)23 int sof_intel_board_card_late_probe(struct snd_soc_card *card)
24 {
25 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
26
27 if (!ctx->hdmi_num)
28 return 0;
29
30 if (!ctx->hdmi.idisp_codec)
31 return 0;
32
33 if (!ctx->hdmi.hdmi_comp)
34 return -EINVAL;
35
36 return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
37 }
38 EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS);
39
40 /*
41 * DMIC DAI Link
42 */
43 static const struct snd_soc_dapm_widget dmic_widgets[] = {
44 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
45 };
46
47 static const struct snd_soc_dapm_route dmic_routes[] = {
48 {"DMic", NULL, "SoC DMIC"},
49 };
50
dmic_init(struct snd_soc_pcm_runtime * rtd)51 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
52 {
53 struct snd_soc_card *card = rtd->card;
54 int ret;
55
56 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
57 ARRAY_SIZE(dmic_widgets));
58 if (ret) {
59 dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret);
60 return ret;
61 }
62
63 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_routes,
64 ARRAY_SIZE(dmic_routes));
65 if (ret) {
66 dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret);
67 return ret;
68 }
69
70 return 0;
71 }
72
73 /*
74 * HDA External Codec DAI Link
75 */
76 static const struct snd_soc_dapm_widget hda_widgets[] = {
77 SND_SOC_DAPM_MIC("Analog In", NULL),
78 SND_SOC_DAPM_MIC("Digital In", NULL),
79 SND_SOC_DAPM_MIC("Alt Analog In", NULL),
80
81 SND_SOC_DAPM_HP("Analog Out", NULL),
82 SND_SOC_DAPM_SPK("Digital Out", NULL),
83 SND_SOC_DAPM_HP("Alt Analog Out", NULL),
84 };
85
86 static const struct snd_soc_dapm_route hda_routes[] = {
87 { "Codec Input Pin1", NULL, "Analog In" },
88 { "Codec Input Pin2", NULL, "Digital In" },
89 { "Codec Input Pin3", NULL, "Alt Analog In" },
90
91 { "Analog Out", NULL, "Codec Output Pin1" },
92 { "Digital Out", NULL, "Codec Output Pin2" },
93 { "Alt Analog Out", NULL, "Codec Output Pin3" },
94
95 /* CODEC BE connections */
96 { "codec0_in", NULL, "Analog CPU Capture" },
97 { "Analog CPU Capture", NULL, "Analog Codec Capture" },
98 { "codec1_in", NULL, "Digital CPU Capture" },
99 { "Digital CPU Capture", NULL, "Digital Codec Capture" },
100 { "codec2_in", NULL, "Alt Analog CPU Capture" },
101 { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" },
102
103 { "Analog Codec Playback", NULL, "Analog CPU Playback" },
104 { "Analog CPU Playback", NULL, "codec0_out" },
105 { "Digital Codec Playback", NULL, "Digital CPU Playback" },
106 { "Digital CPU Playback", NULL, "codec1_out" },
107 { "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" },
108 { "Alt Analog CPU Playback", NULL, "codec2_out" },
109 };
110
hda_init(struct snd_soc_pcm_runtime * rtd)111 static int hda_init(struct snd_soc_pcm_runtime *rtd)
112 {
113 struct snd_soc_card *card = rtd->card;
114 int ret;
115
116 ret = snd_soc_dapm_new_controls(&card->dapm, hda_widgets,
117 ARRAY_SIZE(hda_widgets));
118 if (ret) {
119 dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret);
120 return ret;
121 }
122
123 ret = snd_soc_dapm_add_routes(&card->dapm, hda_routes,
124 ARRAY_SIZE(hda_routes));
125 if (ret)
126 dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret);
127
128 return ret;
129 }
130
131 /*
132 * DAI Link Helpers
133 */
134
135 enum sof_dmic_be_type {
136 SOF_DMIC_01,
137 SOF_DMIC_16K,
138 };
139
140 enum sof_hda_be_type {
141 SOF_HDA_ANALOG,
142 SOF_HDA_DIGITAL,
143 };
144
145 /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
146 #define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \
147 SOF_LINK_DMIC01, \
148 SOF_LINK_DMIC16K, \
149 SOF_LINK_IDISP_HDMI, \
150 SOF_LINK_AMP, \
151 SOF_LINK_BT_OFFLOAD, \
152 SOF_LINK_HDMI_IN)
153
154 static struct snd_soc_dai_link_component dmic_component[] = {
155 {
156 .name = "dmic-codec",
157 .dai_name = "dmic-hifi",
158 }
159 };
160
161 SND_SOC_DAILINK_DEF(hda_analog_cpus,
162 DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI")));
163 SND_SOC_DAILINK_DEF(hda_analog_codecs,
164 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI")));
165
166 SND_SOC_DAILINK_DEF(hda_digital_cpus,
167 DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI")));
168 SND_SOC_DAILINK_DEF(hda_digital_codecs,
169 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI")));
170
171 static struct snd_soc_dai_link_component platform_component[] = {
172 {
173 /* name might be overridden during probe */
174 .name = "0000:00:1f.3"
175 }
176 };
177
set_ssp_codec_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,enum snd_soc_acpi_intel_codec codec_type,int ssp_codec)178 static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link,
179 int be_id, enum snd_soc_acpi_intel_codec codec_type,
180 int ssp_codec)
181 {
182 struct snd_soc_dai_link_component *cpus;
183
184 dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id,
185 snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec);
186
187 /* link name */
188 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
189 if (!link->name)
190 return -ENOMEM;
191
192 /* cpus */
193 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
194 GFP_KERNEL);
195 if (!cpus)
196 return -ENOMEM;
197
198 if (soc_intel_is_byt() || soc_intel_is_cht()) {
199 /* backward-compatibility for BYT/CHT boards */
200 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port",
201 ssp_codec);
202 } else {
203 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin",
204 ssp_codec);
205 }
206 if (!cpus->dai_name)
207 return -ENOMEM;
208
209 link->cpus = cpus;
210 link->num_cpus = 1;
211
212 /* codecs - caller to handle */
213
214 /* platforms */
215 link->platforms = platform_component;
216 link->num_platforms = ARRAY_SIZE(platform_component);
217
218 link->id = be_id;
219 link->no_pcm = 1;
220 link->dpcm_capture = 1;
221 link->dpcm_playback = 1;
222
223 return 0;
224 }
225
set_dmic_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,enum sof_dmic_be_type be_type)226 static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link,
227 int be_id, enum sof_dmic_be_type be_type)
228 {
229 struct snd_soc_dai_link_component *cpus;
230
231 /* cpus */
232 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
233 GFP_KERNEL);
234 if (!cpus)
235 return -ENOMEM;
236
237 switch (be_type) {
238 case SOF_DMIC_01:
239 dev_dbg(dev, "link %d: dmic01\n", be_id);
240
241 link->name = "dmic01";
242 cpus->dai_name = "DMIC01 Pin";
243 break;
244 case SOF_DMIC_16K:
245 dev_dbg(dev, "link %d: dmic16k\n", be_id);
246
247 link->name = "dmic16k";
248 cpus->dai_name = "DMIC16k Pin";
249 break;
250 default:
251 dev_err(dev, "invalid be type %d\n", be_type);
252 return -EINVAL;
253 }
254
255 link->cpus = cpus;
256 link->num_cpus = 1;
257
258 /* codecs */
259 link->codecs = dmic_component;
260 link->num_codecs = ARRAY_SIZE(dmic_component);
261
262 /* platforms */
263 link->platforms = platform_component;
264 link->num_platforms = ARRAY_SIZE(platform_component);
265
266 link->id = be_id;
267 if (be_type == SOF_DMIC_01)
268 link->init = dmic_init;
269 link->ignore_suspend = 1;
270 link->no_pcm = 1;
271 link->dpcm_capture = 1;
272
273 return 0;
274 }
275
set_idisp_hdmi_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,int hdmi_id,bool idisp_codec)276 static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link,
277 int be_id, int hdmi_id, bool idisp_codec)
278 {
279 struct snd_soc_dai_link_component *cpus, *codecs;
280
281 dev_dbg(dev, "link %d: idisp hdmi %d, idisp codec %d\n", be_id, hdmi_id,
282 idisp_codec);
283
284 /* link name */
285 link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id);
286 if (!link->name)
287 return -ENOMEM;
288
289 /* cpus */
290 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
291 GFP_KERNEL);
292 if (!cpus)
293 return -ENOMEM;
294
295 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id);
296 if (!cpus->dai_name)
297 return -ENOMEM;
298
299 link->cpus = cpus;
300 link->num_cpus = 1;
301
302 /* codecs */
303 if (idisp_codec) {
304 codecs = devm_kzalloc(dev,
305 sizeof(struct snd_soc_dai_link_component),
306 GFP_KERNEL);
307 if (!codecs)
308 return -ENOMEM;
309
310 codecs->name = "ehdaudio0D2";
311 codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL,
312 "intel-hdmi-hifi%d", hdmi_id);
313 if (!codecs->dai_name)
314 return -ENOMEM;
315
316 link->codecs = codecs;
317 } else {
318 link->codecs = &snd_soc_dummy_dlc;
319 }
320 link->num_codecs = 1;
321
322 /* platforms */
323 link->platforms = platform_component;
324 link->num_platforms = ARRAY_SIZE(platform_component);
325
326 link->id = be_id;
327 link->init = (hdmi_id == 1) ? hdmi_init : NULL;
328 link->no_pcm = 1;
329 link->dpcm_playback = 1;
330
331 return 0;
332 }
333
set_ssp_amp_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,enum snd_soc_acpi_intel_codec amp_type,int ssp_amp)334 static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link,
335 int be_id, enum snd_soc_acpi_intel_codec amp_type,
336 int ssp_amp)
337 {
338 struct snd_soc_dai_link_component *cpus;
339
340 dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id,
341 snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp);
342
343 /* link name */
344 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp);
345 if (!link->name)
346 return -ENOMEM;
347
348 /* cpus */
349 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
350 GFP_KERNEL);
351 if (!cpus)
352 return -ENOMEM;
353
354 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_amp);
355 if (!cpus->dai_name)
356 return -ENOMEM;
357
358 link->cpus = cpus;
359 link->num_cpus = 1;
360
361 /* codecs - caller to handle */
362
363 /* platforms */
364 link->platforms = platform_component;
365 link->num_platforms = ARRAY_SIZE(platform_component);
366
367 link->id = be_id;
368 link->no_pcm = 1;
369 link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */
370 link->dpcm_playback = 1;
371
372 return 0;
373 }
374
set_bt_offload_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,int ssp_bt)375 static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link,
376 int be_id, int ssp_bt)
377 {
378 struct snd_soc_dai_link_component *cpus;
379
380 dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt);
381
382 /* link name */
383 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt);
384 if (!link->name)
385 return -ENOMEM;
386
387 /* cpus */
388 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
389 GFP_KERNEL);
390 if (!cpus)
391 return -ENOMEM;
392
393 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt);
394 if (!cpus->dai_name)
395 return -ENOMEM;
396
397 link->cpus = cpus;
398 link->num_cpus = 1;
399
400 /* codecs */
401 link->codecs = &snd_soc_dummy_dlc;
402 link->num_codecs = 1;
403
404 /* platforms */
405 link->platforms = platform_component;
406 link->num_platforms = ARRAY_SIZE(platform_component);
407
408 link->id = be_id;
409 link->no_pcm = 1;
410 link->dpcm_capture = 1;
411 link->dpcm_playback = 1;
412
413 return 0;
414 }
415
set_hdmi_in_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,int ssp_hdmi)416 static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
417 int be_id, int ssp_hdmi)
418 {
419 struct snd_soc_dai_link_component *cpus;
420
421 dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi);
422
423 /* link name */
424 link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi);
425 if (!link->name)
426 return -ENOMEM;
427
428 /* cpus */
429 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
430 GFP_KERNEL);
431 if (!cpus)
432 return -ENOMEM;
433
434 cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi);
435 if (!cpus->dai_name)
436 return -ENOMEM;
437
438 link->cpus = cpus;
439 link->num_cpus = 1;
440
441 /* codecs */
442 link->codecs = &snd_soc_dummy_dlc;
443 link->num_codecs = 1;
444
445 /* platforms */
446 link->platforms = platform_component;
447 link->num_platforms = ARRAY_SIZE(platform_component);
448
449 link->id = be_id;
450 link->no_pcm = 1;
451 link->dpcm_capture = 1;
452
453 return 0;
454 }
455
set_hda_codec_link(struct device * dev,struct snd_soc_dai_link * link,int be_id,enum sof_hda_be_type be_type)456 static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link,
457 int be_id, enum sof_hda_be_type be_type)
458 {
459 switch (be_type) {
460 case SOF_HDA_ANALOG:
461 dev_dbg(dev, "link %d: hda analog\n", be_id);
462
463 link->name = "Analog Playback and Capture";
464
465 /* cpus */
466 link->cpus = hda_analog_cpus;
467 link->num_cpus = ARRAY_SIZE(hda_analog_cpus);
468
469 /* codecs */
470 link->codecs = hda_analog_codecs;
471 link->num_codecs = ARRAY_SIZE(hda_analog_codecs);
472 break;
473 case SOF_HDA_DIGITAL:
474 dev_dbg(dev, "link %d: hda digital\n", be_id);
475
476 link->name = "Digital Playback and Capture";
477
478 /* cpus */
479 link->cpus = hda_digital_cpus;
480 link->num_cpus = ARRAY_SIZE(hda_digital_cpus);
481
482 /* codecs */
483 link->codecs = hda_digital_codecs;
484 link->num_codecs = ARRAY_SIZE(hda_digital_codecs);
485 break;
486 default:
487 dev_err(dev, "invalid be type %d\n", be_type);
488 return -EINVAL;
489 }
490
491 /* platforms */
492 link->platforms = platform_component;
493 link->num_platforms = ARRAY_SIZE(platform_component);
494
495 link->id = be_id;
496 if (be_type == SOF_HDA_ANALOG)
497 link->init = hda_init;
498 link->no_pcm = 1;
499 link->dpcm_capture = 1;
500 link->dpcm_playback = 1;
501
502 return 0;
503 }
504
calculate_num_links(struct sof_card_private * ctx)505 static int calculate_num_links(struct sof_card_private *ctx)
506 {
507 int num_links = 0;
508
509 /* headphone codec */
510 if (ctx->codec_type != CODEC_NONE)
511 num_links++;
512
513 /* dmic01 and dmic16k */
514 if (ctx->dmic_be_num > 0)
515 num_links++;
516
517 if (ctx->dmic_be_num > 1)
518 num_links++;
519
520 /* idisp HDMI */
521 num_links += ctx->hdmi_num;
522
523 /* speaker amp */
524 if (ctx->amp_type != CODEC_NONE)
525 num_links++;
526
527 /* BT audio offload */
528 if (ctx->bt_offload_present)
529 num_links++;
530
531 /* HDMI-In */
532 num_links += hweight32(ctx->ssp_mask_hdmi_in);
533
534 /* HDA external codec */
535 if (ctx->hda_codec_present)
536 num_links += 2;
537
538 return num_links;
539 }
540
sof_intel_board_set_dai_link(struct device * dev,struct snd_soc_card * card,struct sof_card_private * ctx)541 int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
542 struct sof_card_private *ctx)
543 {
544 struct snd_soc_dai_link *links;
545 int num_links;
546 int i;
547 int idx = 0;
548 int ret;
549 int ssp_hdmi_in = 0;
550 unsigned long link_order, link;
551 unsigned long link_ids, be_id;
552
553 num_links = calculate_num_links(ctx);
554
555 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link),
556 GFP_KERNEL);
557 if (!links)
558 return -ENOMEM;
559
560 if (ctx->link_order_overwrite)
561 link_order = ctx->link_order_overwrite;
562 else
563 link_order = DEFAULT_LINK_ORDER;
564
565 if (ctx->link_id_overwrite)
566 link_ids = ctx->link_id_overwrite;
567 else
568 link_ids = 0;
569
570 dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n",
571 link_order, link_ids);
572
573 while (link_order) {
574 link = link_order & SOF_LINK_ORDER_MASK;
575 link_order >>= SOF_LINK_ORDER_SHIFT;
576
577 if (ctx->link_id_overwrite) {
578 be_id = link_ids & SOF_LINK_IDS_MASK;
579 link_ids >>= SOF_LINK_IDS_SHIFT;
580 } else {
581 /* use array index as link id */
582 be_id = idx;
583 }
584
585 switch (link) {
586 case SOF_LINK_CODEC:
587 /* headphone codec */
588 if (ctx->codec_type == CODEC_NONE)
589 continue;
590
591 ret = set_ssp_codec_link(dev, &links[idx], be_id,
592 ctx->codec_type, ctx->ssp_codec);
593 if (ret) {
594 dev_err(dev, "fail to set codec link, ret %d\n",
595 ret);
596 return ret;
597 }
598
599 ctx->codec_link = &links[idx];
600 idx++;
601 break;
602 case SOF_LINK_DMIC01:
603 /* dmic01 */
604 if (ctx->dmic_be_num == 0)
605 continue;
606
607 /* at least we have dmic01 */
608 ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01);
609 if (ret) {
610 dev_err(dev, "fail to set dmic01 link, ret %d\n",
611 ret);
612 return ret;
613 }
614
615 idx++;
616 break;
617 case SOF_LINK_DMIC16K:
618 /* dmic16k */
619 if (ctx->dmic_be_num <= 1)
620 continue;
621
622 /* set up 2 BE links at most */
623 ret = set_dmic_link(dev, &links[idx], be_id,
624 SOF_DMIC_16K);
625 if (ret) {
626 dev_err(dev, "fail to set dmic16k link, ret %d\n",
627 ret);
628 return ret;
629 }
630
631 idx++;
632 break;
633 case SOF_LINK_IDISP_HDMI:
634 /* idisp HDMI */
635 for (i = 1; i <= ctx->hdmi_num; i++) {
636 ret = set_idisp_hdmi_link(dev, &links[idx],
637 be_id, i,
638 ctx->hdmi.idisp_codec);
639 if (ret) {
640 dev_err(dev, "fail to set hdmi link, ret %d\n",
641 ret);
642 return ret;
643 }
644
645 idx++;
646 be_id++;
647 }
648 break;
649 case SOF_LINK_AMP:
650 /* speaker amp */
651 if (ctx->amp_type == CODEC_NONE)
652 continue;
653
654 ret = set_ssp_amp_link(dev, &links[idx], be_id,
655 ctx->amp_type, ctx->ssp_amp);
656 if (ret) {
657 dev_err(dev, "fail to set amp link, ret %d\n",
658 ret);
659 return ret;
660 }
661
662 ctx->amp_link = &links[idx];
663 idx++;
664 break;
665 case SOF_LINK_BT_OFFLOAD:
666 /* BT audio offload */
667 if (!ctx->bt_offload_present)
668 continue;
669
670 ret = set_bt_offload_link(dev, &links[idx], be_id,
671 ctx->ssp_bt);
672 if (ret) {
673 dev_err(dev, "fail to set bt link, ret %d\n",
674 ret);
675 return ret;
676 }
677
678 idx++;
679 break;
680 case SOF_LINK_HDMI_IN:
681 /* HDMI-In */
682 for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
683 ret = set_hdmi_in_link(dev, &links[idx], be_id,
684 ssp_hdmi_in);
685 if (ret) {
686 dev_err(dev, "fail to set hdmi-in link, ret %d\n",
687 ret);
688 return ret;
689 }
690
691 idx++;
692 be_id++;
693 }
694 break;
695 case SOF_LINK_HDA:
696 /* HDA external codec */
697 if (!ctx->hda_codec_present)
698 continue;
699
700 ret = set_hda_codec_link(dev, &links[idx], be_id,
701 SOF_HDA_ANALOG);
702 if (ret) {
703 dev_err(dev, "fail to set hda analog link, ret %d\n",
704 ret);
705 return ret;
706 }
707
708 idx++;
709 be_id++;
710
711 ret = set_hda_codec_link(dev, &links[idx], be_id,
712 SOF_HDA_DIGITAL);
713 if (ret) {
714 dev_err(dev, "fail to set hda digital link, ret %d\n",
715 ret);
716 return ret;
717 }
718
719 idx++;
720 break;
721 case SOF_LINK_NONE:
722 /* caught here if it's not used as terminator in macro */
723 fallthrough;
724 default:
725 dev_err(dev, "invalid link type %ld\n", link);
726 return -EINVAL;
727 }
728 }
729
730 if (idx != num_links) {
731 dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx,
732 num_links);
733 return -EINVAL;
734 }
735
736 card->dai_link = links;
737 card->num_links = num_links;
738
739 return 0;
740 }
741 EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
742
743 struct sof_card_private *
sof_intel_board_get_ctx(struct device * dev,unsigned long board_quirk)744 sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
745 {
746 struct sof_card_private *ctx;
747
748 dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk);
749
750 ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL);
751 if (!ctx)
752 return NULL;
753
754 ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev);
755 ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev);
756
757 ctx->dmic_be_num = 2;
758 ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >>
759 SOF_NUM_IDISP_HDMI_SHIFT;
760 /* default number of HDMI DAI's */
761 if (!ctx->hdmi_num)
762 ctx->hdmi_num = 3;
763
764 /* port number/mask of peripherals attached to ssp interface */
765 if (ctx->codec_type != CODEC_NONE)
766 ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >>
767 SOF_SSP_PORT_CODEC_SHIFT;
768
769 if (ctx->amp_type != CODEC_NONE)
770 ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >>
771 SOF_SSP_PORT_AMP_SHIFT;
772
773 if (board_quirk & SOF_BT_OFFLOAD_PRESENT) {
774 ctx->bt_offload_present = true;
775 ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >>
776 SOF_SSP_PORT_BT_OFFLOAD_SHIFT;
777 }
778
779 ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >>
780 SOF_SSP_MASK_HDMI_CAPTURE_SHIFT;
781
782 return ctx;
783 }
784 EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS);
785
786 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
787 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
788 MODULE_LICENSE("GPL");
789 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
790 MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);
791