xref: /linux/sound/soc/intel/boards/sof_board_helpers.c (revision 335bbdf01d25517ae832ac1807fd8323c1f4f3b9)
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);
205