Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/boards/sof_board_helpers.c
51061 views
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
*/
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
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
51
static int dmic_init(struct snd_soc_pcm_runtime *rtd)
52
{
53
struct snd_soc_card *card = rtd->card;
54
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
55
int ret;
56
57
ret = snd_soc_dapm_new_controls(dapm, dmic_widgets,
58
ARRAY_SIZE(dmic_widgets));
59
if (ret) {
60
dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret);
61
return ret;
62
}
63
64
ret = snd_soc_dapm_add_routes(dapm, dmic_routes,
65
ARRAY_SIZE(dmic_routes));
66
if (ret) {
67
dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret);
68
return ret;
69
}
70
71
return 0;
72
}
73
74
/*
75
* HDA External Codec DAI Link
76
*/
77
static const struct snd_soc_dapm_widget hda_widgets[] = {
78
SND_SOC_DAPM_MIC("Analog In", NULL),
79
SND_SOC_DAPM_MIC("Digital In", NULL),
80
SND_SOC_DAPM_MIC("Alt Analog In", NULL),
81
82
SND_SOC_DAPM_HP("Analog Out", NULL),
83
SND_SOC_DAPM_SPK("Digital Out", NULL),
84
SND_SOC_DAPM_HP("Alt Analog Out", NULL),
85
};
86
87
static const struct snd_soc_dapm_route hda_routes[] = {
88
{ "Codec Input Pin1", NULL, "Analog In" },
89
{ "Codec Input Pin2", NULL, "Digital In" },
90
{ "Codec Input Pin3", NULL, "Alt Analog In" },
91
92
{ "Analog Out", NULL, "Codec Output Pin1" },
93
{ "Digital Out", NULL, "Codec Output Pin2" },
94
{ "Alt Analog Out", NULL, "Codec Output Pin3" },
95
96
/* CODEC BE connections */
97
{ "codec0_in", NULL, "Analog CPU Capture" },
98
{ "Analog CPU Capture", NULL, "Analog Codec Capture" },
99
{ "codec1_in", NULL, "Digital CPU Capture" },
100
{ "Digital CPU Capture", NULL, "Digital Codec Capture" },
101
{ "codec2_in", NULL, "Alt Analog CPU Capture" },
102
{ "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" },
103
104
{ "Analog Codec Playback", NULL, "Analog CPU Playback" },
105
{ "Analog CPU Playback", NULL, "codec0_out" },
106
{ "Digital Codec Playback", NULL, "Digital CPU Playback" },
107
{ "Digital CPU Playback", NULL, "codec1_out" },
108
{ "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" },
109
{ "Alt Analog CPU Playback", NULL, "codec2_out" },
110
};
111
112
static int hda_init(struct snd_soc_pcm_runtime *rtd)
113
{
114
struct snd_soc_card *card = rtd->card;
115
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
116
int ret;
117
118
ret = snd_soc_dapm_new_controls(dapm, hda_widgets,
119
ARRAY_SIZE(hda_widgets));
120
if (ret) {
121
dev_err(rtd->dev, "fail to add hda widgets, ret %d\n", ret);
122
return ret;
123
}
124
125
ret = snd_soc_dapm_add_routes(dapm, hda_routes,
126
ARRAY_SIZE(hda_routes));
127
if (ret)
128
dev_err(rtd->dev, "fail to add hda routes, ret %d\n", ret);
129
130
return ret;
131
}
132
133
/*
134
* DAI Link Helpers
135
*/
136
137
enum sof_dmic_be_type {
138
SOF_DMIC_01,
139
SOF_DMIC_16K,
140
};
141
142
enum sof_hda_be_type {
143
SOF_HDA_ANALOG,
144
SOF_HDA_DIGITAL,
145
};
146
147
/* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
148
#define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \
149
SOF_LINK_DMIC01, \
150
SOF_LINK_DMIC16K, \
151
SOF_LINK_IDISP_HDMI, \
152
SOF_LINK_AMP, \
153
SOF_LINK_BT_OFFLOAD, \
154
SOF_LINK_HDMI_IN)
155
156
static struct snd_soc_dai_link_component dmic_component[] = {
157
{
158
.name = "dmic-codec",
159
.dai_name = "dmic-hifi",
160
}
161
};
162
163
SND_SOC_DAILINK_DEF(hda_analog_cpus,
164
DAILINK_COMP_ARRAY(COMP_CPU("Analog CPU DAI")));
165
SND_SOC_DAILINK_DEF(hda_analog_codecs,
166
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Analog Codec DAI")));
167
168
SND_SOC_DAILINK_DEF(hda_digital_cpus,
169
DAILINK_COMP_ARRAY(COMP_CPU("Digital CPU DAI")));
170
SND_SOC_DAILINK_DEF(hda_digital_codecs,
171
DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D0", "Digital Codec DAI")));
172
173
static struct snd_soc_dai_link_component platform_component[] = {
174
{
175
/* name might be overridden during probe */
176
.name = "0000:00:1f.3"
177
}
178
};
179
180
static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link,
181
int be_id, enum snd_soc_acpi_intel_codec codec_type,
182
int ssp_codec)
183
{
184
struct snd_soc_dai_link_component *cpus;
185
186
dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id,
187
snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec);
188
189
/* link name */
190
link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
191
if (!link->name)
192
return -ENOMEM;
193
194
/* cpus */
195
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
196
GFP_KERNEL);
197
if (!cpus)
198
return -ENOMEM;
199
200
if (soc_intel_is_byt() || soc_intel_is_cht()) {
201
/* backward-compatibility for BYT/CHT boards */
202
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port",
203
ssp_codec);
204
} else {
205
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin",
206
ssp_codec);
207
}
208
if (!cpus->dai_name)
209
return -ENOMEM;
210
211
link->cpus = cpus;
212
link->num_cpus = 1;
213
214
/* codecs - caller to handle */
215
216
/* platforms */
217
link->platforms = platform_component;
218
link->num_platforms = ARRAY_SIZE(platform_component);
219
220
link->id = be_id;
221
link->no_pcm = 1;
222
223
return 0;
224
}
225
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->capture_only = 1;
272
273
return 0;
274
}
275
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->playback_only = 1;
330
331
return 0;
332
}
333
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
/* feedback stream or firmware-generated echo reference */
365
link->platforms = platform_component;
366
link->num_platforms = ARRAY_SIZE(platform_component);
367
368
link->id = be_id;
369
link->no_pcm = 1;
370
371
return 0;
372
}
373
374
static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link,
375
int be_id, int ssp_bt)
376
{
377
struct snd_soc_dai_link_component *cpus;
378
379
dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt);
380
381
/* link name */
382
link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt);
383
if (!link->name)
384
return -ENOMEM;
385
386
/* cpus */
387
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
388
GFP_KERNEL);
389
if (!cpus)
390
return -ENOMEM;
391
392
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt);
393
if (!cpus->dai_name)
394
return -ENOMEM;
395
396
link->cpus = cpus;
397
link->num_cpus = 1;
398
399
/* codecs */
400
link->codecs = &snd_soc_dummy_dlc;
401
link->num_codecs = 1;
402
403
/* platforms */
404
link->platforms = platform_component;
405
link->num_platforms = ARRAY_SIZE(platform_component);
406
407
link->id = be_id;
408
link->no_pcm = 1;
409
410
return 0;
411
}
412
413
static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link,
414
int be_id, int ssp_hdmi)
415
{
416
struct snd_soc_dai_link_component *cpus;
417
418
dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi);
419
420
/* link name */
421
link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi);
422
if (!link->name)
423
return -ENOMEM;
424
425
/* cpus */
426
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
427
GFP_KERNEL);
428
if (!cpus)
429
return -ENOMEM;
430
431
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi);
432
if (!cpus->dai_name)
433
return -ENOMEM;
434
435
link->cpus = cpus;
436
link->num_cpus = 1;
437
438
/* codecs */
439
link->codecs = &snd_soc_dummy_dlc;
440
link->num_codecs = 1;
441
442
/* platforms */
443
link->platforms = platform_component;
444
link->num_platforms = ARRAY_SIZE(platform_component);
445
446
link->id = be_id;
447
link->no_pcm = 1;
448
link->capture_only = 1;
449
450
return 0;
451
}
452
453
static int set_hda_codec_link(struct device *dev, struct snd_soc_dai_link *link,
454
int be_id, enum sof_hda_be_type be_type)
455
{
456
switch (be_type) {
457
case SOF_HDA_ANALOG:
458
dev_dbg(dev, "link %d: hda analog\n", be_id);
459
460
link->name = "Analog Playback and Capture";
461
462
/* cpus */
463
link->cpus = hda_analog_cpus;
464
link->num_cpus = ARRAY_SIZE(hda_analog_cpus);
465
466
/* codecs */
467
link->codecs = hda_analog_codecs;
468
link->num_codecs = ARRAY_SIZE(hda_analog_codecs);
469
break;
470
case SOF_HDA_DIGITAL:
471
dev_dbg(dev, "link %d: hda digital\n", be_id);
472
473
link->name = "Digital Playback and Capture";
474
475
/* cpus */
476
link->cpus = hda_digital_cpus;
477
link->num_cpus = ARRAY_SIZE(hda_digital_cpus);
478
479
/* codecs */
480
link->codecs = hda_digital_codecs;
481
link->num_codecs = ARRAY_SIZE(hda_digital_codecs);
482
break;
483
default:
484
dev_err(dev, "invalid be type %d\n", be_type);
485
return -EINVAL;
486
}
487
488
/* platforms */
489
link->platforms = platform_component;
490
link->num_platforms = ARRAY_SIZE(platform_component);
491
492
link->id = be_id;
493
if (be_type == SOF_HDA_ANALOG)
494
link->init = hda_init;
495
link->no_pcm = 1;
496
497
return 0;
498
}
499
500
static int calculate_num_links(struct sof_card_private *ctx)
501
{
502
int num_links = 0;
503
504
/* headphone codec */
505
if (ctx->codec_type != CODEC_NONE)
506
num_links++;
507
508
/* dmic01 and dmic16k */
509
if (ctx->dmic_be_num > 0)
510
num_links++;
511
512
if (ctx->dmic_be_num > 1)
513
num_links++;
514
515
/* idisp HDMI */
516
num_links += ctx->hdmi_num;
517
518
/* speaker amp */
519
if (ctx->amp_type != CODEC_NONE)
520
num_links++;
521
522
/* BT audio offload */
523
if (ctx->bt_offload_present)
524
num_links++;
525
526
/* HDMI-In */
527
num_links += hweight32(ctx->ssp_mask_hdmi_in);
528
529
/* HDA external codec */
530
if (ctx->hda_codec_present)
531
num_links += 2;
532
533
return num_links;
534
}
535
536
int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
537
struct sof_card_private *ctx)
538
{
539
struct snd_soc_dai_link *links;
540
int num_links;
541
int i;
542
int idx = 0;
543
int ret;
544
int ssp_hdmi_in = 0;
545
unsigned long link_order, link;
546
unsigned long link_ids, be_id;
547
548
num_links = calculate_num_links(ctx);
549
550
links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link),
551
GFP_KERNEL);
552
if (!links)
553
return -ENOMEM;
554
555
if (ctx->link_order_overwrite)
556
link_order = ctx->link_order_overwrite;
557
else
558
link_order = DEFAULT_LINK_ORDER;
559
560
if (ctx->link_id_overwrite)
561
link_ids = ctx->link_id_overwrite;
562
else
563
link_ids = 0;
564
565
dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n",
566
link_order, link_ids);
567
568
while (link_order) {
569
link = link_order & SOF_LINK_ORDER_MASK;
570
link_order >>= SOF_LINK_ORDER_SHIFT;
571
572
if (ctx->link_id_overwrite) {
573
be_id = link_ids & SOF_LINK_IDS_MASK;
574
link_ids >>= SOF_LINK_IDS_SHIFT;
575
} else {
576
/* use array index as link id */
577
be_id = idx;
578
}
579
580
switch (link) {
581
case SOF_LINK_CODEC:
582
/* headphone codec */
583
if (ctx->codec_type == CODEC_NONE)
584
continue;
585
586
ret = set_ssp_codec_link(dev, &links[idx], be_id,
587
ctx->codec_type, ctx->ssp_codec);
588
if (ret) {
589
dev_err(dev, "fail to set codec link, ret %d\n",
590
ret);
591
return ret;
592
}
593
594
ctx->codec_link = &links[idx];
595
idx++;
596
break;
597
case SOF_LINK_DMIC01:
598
/* dmic01 */
599
if (ctx->dmic_be_num == 0)
600
continue;
601
602
/* at least we have dmic01 */
603
ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01);
604
if (ret) {
605
dev_err(dev, "fail to set dmic01 link, ret %d\n",
606
ret);
607
return ret;
608
}
609
610
idx++;
611
break;
612
case SOF_LINK_DMIC16K:
613
/* dmic16k */
614
if (ctx->dmic_be_num <= 1)
615
continue;
616
617
/* set up 2 BE links at most */
618
ret = set_dmic_link(dev, &links[idx], be_id,
619
SOF_DMIC_16K);
620
if (ret) {
621
dev_err(dev, "fail to set dmic16k link, ret %d\n",
622
ret);
623
return ret;
624
}
625
626
idx++;
627
break;
628
case SOF_LINK_IDISP_HDMI:
629
/* idisp HDMI */
630
for (i = 1; i <= ctx->hdmi_num; i++) {
631
ret = set_idisp_hdmi_link(dev, &links[idx],
632
be_id, i,
633
ctx->hdmi.idisp_codec);
634
if (ret) {
635
dev_err(dev, "fail to set hdmi link, ret %d\n",
636
ret);
637
return ret;
638
}
639
640
idx++;
641
be_id++;
642
}
643
break;
644
case SOF_LINK_AMP:
645
/* speaker amp */
646
if (ctx->amp_type == CODEC_NONE)
647
continue;
648
649
ret = set_ssp_amp_link(dev, &links[idx], be_id,
650
ctx->amp_type, ctx->ssp_amp);
651
if (ret) {
652
dev_err(dev, "fail to set amp link, ret %d\n",
653
ret);
654
return ret;
655
}
656
657
ctx->amp_link = &links[idx];
658
idx++;
659
break;
660
case SOF_LINK_BT_OFFLOAD:
661
/* BT audio offload */
662
if (!ctx->bt_offload_present)
663
continue;
664
665
ret = set_bt_offload_link(dev, &links[idx], be_id,
666
ctx->ssp_bt);
667
if (ret) {
668
dev_err(dev, "fail to set bt link, ret %d\n",
669
ret);
670
return ret;
671
}
672
673
idx++;
674
break;
675
case SOF_LINK_HDMI_IN:
676
/* HDMI-In */
677
for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
678
ret = set_hdmi_in_link(dev, &links[idx], be_id,
679
ssp_hdmi_in);
680
if (ret) {
681
dev_err(dev, "fail to set hdmi-in link, ret %d\n",
682
ret);
683
return ret;
684
}
685
686
idx++;
687
be_id++;
688
}
689
break;
690
case SOF_LINK_HDA:
691
/* HDA external codec */
692
if (!ctx->hda_codec_present)
693
continue;
694
695
ret = set_hda_codec_link(dev, &links[idx], be_id,
696
SOF_HDA_ANALOG);
697
if (ret) {
698
dev_err(dev, "fail to set hda analog link, ret %d\n",
699
ret);
700
return ret;
701
}
702
703
idx++;
704
be_id++;
705
706
ret = set_hda_codec_link(dev, &links[idx], be_id,
707
SOF_HDA_DIGITAL);
708
if (ret) {
709
dev_err(dev, "fail to set hda digital link, ret %d\n",
710
ret);
711
return ret;
712
}
713
714
idx++;
715
break;
716
case SOF_LINK_NONE:
717
/* caught here if it's not used as terminator in macro */
718
fallthrough;
719
default:
720
dev_err(dev, "invalid link type %ld\n", link);
721
return -EINVAL;
722
}
723
}
724
725
if (idx != num_links) {
726
dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx,
727
num_links);
728
return -EINVAL;
729
}
730
731
card->dai_link = links;
732
card->num_links = num_links;
733
734
return 0;
735
}
736
EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, "SND_SOC_INTEL_SOF_BOARD_HELPERS");
737
738
struct sof_card_private *
739
sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
740
{
741
struct sof_card_private *ctx;
742
743
dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk);
744
745
ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL);
746
if (!ctx)
747
return NULL;
748
749
ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev);
750
ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev);
751
752
ctx->dmic_be_num = 2;
753
ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >>
754
SOF_NUM_IDISP_HDMI_SHIFT;
755
/* default number of HDMI DAI's */
756
if (!ctx->hdmi_num)
757
ctx->hdmi_num = 3;
758
759
/* port number/mask of peripherals attached to ssp interface */
760
if (ctx->codec_type != CODEC_NONE)
761
ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >>
762
SOF_SSP_PORT_CODEC_SHIFT;
763
764
if (ctx->amp_type != CODEC_NONE)
765
ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >>
766
SOF_SSP_PORT_AMP_SHIFT;
767
768
if (board_quirk & SOF_BT_OFFLOAD_PRESENT) {
769
ctx->bt_offload_present = true;
770
ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >>
771
SOF_SSP_PORT_BT_OFFLOAD_SHIFT;
772
}
773
774
ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >>
775
SOF_SSP_MASK_HDMI_CAPTURE_SHIFT;
776
777
return ctx;
778
}
779
EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, "SND_SOC_INTEL_SOF_BOARD_HELPERS");
780
781
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
782
MODULE_AUTHOR("Brent Lu <[email protected]>");
783
MODULE_LICENSE("GPL");
784
MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
785
MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");
786
787