Linux 6.7-rc7
[linux-modified.git] / sound / soc / intel / boards / sof_board_helpers.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2023 Intel Corporation. All rights reserved.
4
5 #include <sound/soc.h>
6 #include "hda_dsp_common.h"
7 #include "sof_board_helpers.h"
8
9 /*
10  * Intel HDMI DAI Link
11  */
12 static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
13 {
14         struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
15         struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);
16
17         ctx->hdmi.hdmi_comp = dai->component;
18
19         return 0;
20 }
21
22 int sof_intel_board_card_late_probe(struct snd_soc_card *card)
23 {
24         struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
25
26         if (!ctx->hdmi_num)
27                 return 0;
28
29         if (!ctx->hdmi.idisp_codec)
30                 return 0;
31
32         if (!ctx->hdmi.hdmi_comp)
33                 return -EINVAL;
34
35         return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
36 }
37 EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS);
38
39 /*
40  * DMIC DAI Link
41  */
42 static const struct snd_soc_dapm_widget dmic_widgets[] = {
43         SND_SOC_DAPM_MIC("SoC DMIC", NULL),
44 };
45
46 static const struct snd_soc_dapm_route dmic_routes[] = {
47         {"DMic", NULL, "SoC DMIC"},
48 };
49
50 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
51 {
52         struct snd_soc_card *card = rtd->card;
53         int ret;
54
55         ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
56                                         ARRAY_SIZE(dmic_widgets));
57         if (ret) {
58                 dev_err(rtd->dev, "fail to add dmic widgets, ret %d\n", ret);
59                 return ret;
60         }
61
62         ret = snd_soc_dapm_add_routes(&card->dapm, dmic_routes,
63                                       ARRAY_SIZE(dmic_routes));
64         if (ret) {
65                 dev_err(rtd->dev, "fail to add dmic routes, ret %d\n", ret);
66                 return ret;
67         }
68
69         return 0;
70 }
71
72 /*
73  * DAI Link Helpers
74  */
75 static struct snd_soc_dai_link_component dmic_component[] = {
76         {
77                 .name = "dmic-codec",
78                 .dai_name = "dmic-hifi",
79         }
80 };
81
82 static struct snd_soc_dai_link_component platform_component[] = {
83         {
84                 /* name might be overridden during probe */
85                 .name = "0000:00:1f.3"
86         }
87 };
88
89 int sof_intel_board_set_dmic_link(struct device *dev,
90                                   struct snd_soc_dai_link *link, int be_id,
91                                   enum sof_dmic_be_type be_type)
92 {
93         struct snd_soc_dai_link_component *cpus;
94
95         /* cpus */
96         cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
97                             GFP_KERNEL);
98         if (!cpus)
99                 return -ENOMEM;
100
101         switch (be_type) {
102         case SOF_DMIC_01:
103                 dev_dbg(dev, "link %d: dmic01\n", be_id);
104
105                 link->name = "dmic01";
106                 cpus->dai_name = "DMIC01 Pin";
107                 break;
108         case SOF_DMIC_16K:
109                 dev_dbg(dev, "link %d: dmic16k\n", be_id);
110
111                 link->name = "dmic16k";
112                 cpus->dai_name = "DMIC16k Pin";
113                 break;
114         default:
115                 dev_err(dev, "invalid be type %d\n", be_type);
116                 return -EINVAL;
117         }
118
119         link->cpus = cpus;
120         link->num_cpus = 1;
121
122         /* codecs */
123         link->codecs = dmic_component;
124         link->num_codecs = ARRAY_SIZE(dmic_component);
125
126         /* platforms */
127         link->platforms = platform_component;
128         link->num_platforms = ARRAY_SIZE(platform_component);
129
130         link->id = be_id;
131         if (be_type == SOF_DMIC_01)
132                 link->init = dmic_init;
133         link->ignore_suspend = 1;
134         link->no_pcm = 1;
135         link->dpcm_capture = 1;
136
137         return 0;
138 }
139 EXPORT_SYMBOL_NS(sof_intel_board_set_dmic_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
140
141 int sof_intel_board_set_intel_hdmi_link(struct device *dev,
142                                         struct snd_soc_dai_link *link, int be_id,
143                                         int hdmi_id, bool idisp_codec)
144 {
145         struct snd_soc_dai_link_component *cpus, *codecs;
146
147         dev_dbg(dev, "link %d: intel hdmi, hdmi id %d, idisp codec %d\n",
148                 be_id, hdmi_id, idisp_codec);
149
150         /* link name */
151         link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id);
152         if (!link->name)
153                 return -ENOMEM;
154
155         /* cpus */
156         cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
157                             GFP_KERNEL);
158         if (!cpus)
159                 return -ENOMEM;
160
161         cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", hdmi_id);
162         if (!cpus->dai_name)
163                 return -ENOMEM;
164
165         link->cpus = cpus;
166         link->num_cpus = 1;
167
168         /* codecs */
169         if (idisp_codec) {
170                 codecs = devm_kzalloc(dev,
171                                       sizeof(struct snd_soc_dai_link_component),
172                                       GFP_KERNEL);
173                 if (!codecs)
174                         return -ENOMEM;
175
176                 codecs->name = "ehdaudio0D2";
177                 codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL,
178                                                   "intel-hdmi-hifi%d", hdmi_id);
179                 if (!codecs->dai_name)
180                         return -ENOMEM;
181
182                 link->codecs = codecs;
183         } else {
184                 link->codecs = &snd_soc_dummy_dlc;
185         }
186         link->num_codecs = 1;
187
188         /* platforms */
189         link->platforms = platform_component;
190         link->num_platforms = ARRAY_SIZE(platform_component);
191
192         link->id = be_id;
193         link->init = (hdmi_id == 1) ? hdmi_init : NULL;
194         link->no_pcm = 1;
195         link->dpcm_playback = 1;
196
197         return 0;
198 }
199 EXPORT_SYMBOL_NS(sof_intel_board_set_intel_hdmi_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
200
201 MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
202 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
203 MODULE_LICENSE("GPL");
204 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);