xref: /linux/sound/soc/sof/ipc4-topology.c (revision fdfa38e95e1229ec2fb2f18540987c97f861d470)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2022 Intel Corporation
7 //
8 //
9 #include <linux/bitfield.h>
10 #include <linux/cleanup.h>
11 #include <uapi/sound/sof/tokens.h>
12 #include <sound/pcm_params.h>
13 #include <sound/sof/ext_manifest4.h>
14 #include <sound/intel-nhlt.h>
15 #include "sof-priv.h"
16 #include "sof-audio.h"
17 #include "ipc4-priv.h"
18 #include "ipc4-topology.h"
19 #include "ops.h"
20 
21 /*
22  * The ignore_cpc flag can be used to ignore the CPC value for all modules by
23  * using 0 instead.
24  * The CPC is sent to the firmware along with the SOF_IPC4_MOD_INIT_INSTANCE
25  * message and it is used for clock scaling.
26  * 0 as CPC value will instruct the firmware to use maximum frequency, thus
27  * deactivating the clock scaling.
28  */
29 static bool ignore_cpc;
30 module_param_named(ipc4_ignore_cpc, ignore_cpc, bool, 0444);
31 MODULE_PARM_DESC(ipc4_ignore_cpc,
32 		 "Ignore CPC values. This option will disable clock scaling in firmware.");
33 
34 #define SOF_IPC4_GAIN_PARAM_ID  0
35 #define SOF_IPC4_TPLG_ABI_SIZE 6
36 
37 static DEFINE_IDA(alh_group_ida);
38 static DEFINE_IDA(pipeline_ida);
39 
40 struct sof_comp_domains {
41 	const char *name;
42 	enum sof_comp_domain domain;
43 };
44 
45 static const struct sof_comp_domains sof_domains[] = {
46 	{ "LL", SOF_COMP_DOMAIN_LL, },
47 	{ "DP", SOF_COMP_DOMAIN_DP, }
48 };
49 
find_domain(const char * name)50 static enum sof_comp_domain find_domain(const char *name)
51 {
52 	int i;
53 
54 	for (i = 0; i < ARRAY_SIZE(sof_domains); i++) {
55 		if (strcmp(name, sof_domains[i].name) == 0)
56 			return sof_domains[i].domain;
57 	}
58 	/* No valid value found, fall back to manifest value */
59 	return SOF_COMP_DOMAIN_UNSET;
60 }
61 
get_token_comp_domain(void * elem,void * object,u32 offset)62 static int get_token_comp_domain(void *elem, void *object, u32 offset)
63 {
64 	u32 *val = (u32 *)((u8 *)object + offset);
65 
66 	*val = find_domain((const char *)elem);
67 	return 0;
68 }
69 
70 static const struct sof_topology_token ipc4_sched_tokens[] = {
71 	{SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
72 		offsetof(struct sof_ipc4_pipeline, lp_mode)},
73 	{SOF_TKN_SCHED_USE_CHAIN_DMA, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
74 		offsetof(struct sof_ipc4_pipeline, use_chain_dma)},
75 	{SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
76 		offsetof(struct sof_ipc4_pipeline, core_id)},
77 	{SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
78 		offsetof(struct sof_ipc4_pipeline, priority)},
79 };
80 
81 static const struct sof_topology_token pipeline_tokens[] = {
82 	{SOF_TKN_SCHED_DYNAMIC_PIPELINE, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
83 		offsetof(struct snd_sof_widget, dynamic_pipeline_widget)},
84 };
85 
86 static const struct sof_topology_token ipc4_comp_tokens[] = {
87 	{SOF_TKN_COMP_IS_PAGES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
88 		offsetof(struct sof_ipc4_base_module_cfg, is_pages)},
89 };
90 
91 static const struct sof_topology_token ipc4_in_audio_format_tokens[] = {
92 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
93 		offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)},
94 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
95 		offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)},
96 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
97 		offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)},
98 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
99 		offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)},
100 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
101 		get_token_u32, offsetof(struct sof_ipc4_pin_format,
102 		audio_fmt.interleaving_style)},
103 	{SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
104 		offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
105 	{SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
106 		offsetof(struct sof_ipc4_pin_format, pin_index)},
107 	{SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
108 		offsetof(struct sof_ipc4_pin_format, buffer_size)},
109 };
110 
111 static const struct sof_topology_token ipc4_out_audio_format_tokens[] = {
112 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
113 		offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)},
114 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
115 		offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)},
116 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
117 		offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)},
118 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
119 		offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)},
120 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
121 		get_token_u32, offsetof(struct sof_ipc4_pin_format,
122 		audio_fmt.interleaving_style)},
123 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
124 		offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)},
125 	{SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
126 		offsetof(struct sof_ipc4_pin_format, pin_index)},
127 	{SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
128 		offsetof(struct sof_ipc4_pin_format, buffer_size)},
129 };
130 
131 static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = {
132 	{SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0},
133 };
134 
135 static const struct sof_topology_token ipc4_copier_tokens[] = {
136 	{SOF_TKN_INTEL_COPIER_NODE_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0},
137 };
138 
139 static const struct sof_topology_token ipc4_audio_fmt_num_tokens[] = {
140 	{SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
141 		offsetof(struct sof_ipc4_available_audio_format, num_input_formats)},
142 	{SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
143 		offsetof(struct sof_ipc4_available_audio_format, num_output_formats)},
144 };
145 
146 static const struct sof_topology_token dai_tokens[] = {
147 	{SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type,
148 		offsetof(struct sof_ipc4_copier, dai_type)},
149 	{SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
150 		offsetof(struct sof_ipc4_copier, dai_index)},
151 };
152 
153 /* Component extended tokens */
154 static const struct sof_topology_token comp_ext_tokens[] = {
155 	{SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid,
156 		offsetof(struct snd_sof_widget, uuid)},
157 	{SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
158 		offsetof(struct snd_sof_widget, core)},
159 	{SOF_TKN_COMP_SCHED_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_domain,
160 		offsetof(struct snd_sof_widget, comp_domain)},
161 };
162 
163 static const struct sof_topology_token gain_tokens[] = {
164 	{SOF_TKN_GAIN_RAMP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
165 		get_token_u32, offsetof(struct sof_ipc4_gain_params, curve_type)},
166 	{SOF_TKN_GAIN_RAMP_DURATION,
167 		SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
168 		offsetof(struct sof_ipc4_gain_params, curve_duration_l)},
169 	{SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD,
170 		get_token_u32, offsetof(struct sof_ipc4_gain_params, init_val)},
171 };
172 
173 /* SRC */
174 static const struct sof_topology_token src_tokens[] = {
175 	{SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
176 		offsetof(struct sof_ipc4_src_data, sink_rate)},
177 };
178 
179 /* ASRC */
180 static const struct sof_topology_token asrc_tokens[] = {
181 	{SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
182 		offsetof(struct sof_ipc4_asrc_data, out_freq)},
183 	{SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
184 		offsetof(struct sof_ipc4_asrc_data, asrc_mode)},
185 };
186 
187 static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
188 	[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
189 	[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
190 	[SOF_SCHED_TOKENS] = {"Scheduler tokens", ipc4_sched_tokens,
191 		ARRAY_SIZE(ipc4_sched_tokens)},
192 	[SOF_COMP_EXT_TOKENS] = {"Comp extended tokens", comp_ext_tokens,
193 		ARRAY_SIZE(comp_ext_tokens)},
194 	[SOF_COMP_TOKENS] = {"IPC4 Component tokens",
195 		ipc4_comp_tokens, ARRAY_SIZE(ipc4_comp_tokens)},
196 	[SOF_IN_AUDIO_FORMAT_TOKENS] = {"IPC4 Input Audio format tokens",
197 		ipc4_in_audio_format_tokens, ARRAY_SIZE(ipc4_in_audio_format_tokens)},
198 	[SOF_OUT_AUDIO_FORMAT_TOKENS] = {"IPC4 Output Audio format tokens",
199 		ipc4_out_audio_format_tokens, ARRAY_SIZE(ipc4_out_audio_format_tokens)},
200 	[SOF_COPIER_DEEP_BUFFER_TOKENS] = {"IPC4 Copier deep buffer tokens",
201 		ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)},
202 	[SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens,
203 		ARRAY_SIZE(ipc4_copier_tokens)},
204 	[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
205 		ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
206 	[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
207 	[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
208 	[SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)},
209 };
210 
sof_ipc4_find_swidget_by_ids(struct snd_sof_dev * sdev,u32 module_id,int instance_id)211 struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev,
212 						    u32 module_id, int instance_id)
213 {
214 	struct snd_sof_widget *swidget;
215 
216 	list_for_each_entry(swidget, &sdev->widget_list, list) {
217 		struct sof_ipc4_fw_module *fw_module = swidget->module_info;
218 
219 		/* Only active module instances have valid instance_id */
220 		if (!swidget->use_count)
221 			continue;
222 
223 		if (fw_module && fw_module->man4_module_entry.id == module_id &&
224 		    swidget->instance_id == instance_id)
225 			return swidget;
226 	}
227 
228 	return NULL;
229 }
230 
sof_ipc4_dbg_audio_format(struct device * dev,struct sof_ipc4_pin_format * pin_fmt,int num_formats)231 static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt,
232 				      int num_formats)
233 {
234 	int i;
235 
236 	for (i = 0; i < num_formats; i++) {
237 		struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt;
238 		dev_dbg(dev,
239 			"Pin #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
240 			pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth,
241 			SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg),
242 			fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg,
243 			pin_fmt[i].buffer_size);
244 	}
245 }
246 
247 static void
sof_ipc4_dbg_module_audio_format(struct device * dev,struct snd_sof_widget * swidget,struct sof_ipc4_available_audio_format * available_fmt,int in_fmt_index,int out_fmt_index)248 sof_ipc4_dbg_module_audio_format(struct device *dev,
249 				 struct snd_sof_widget *swidget,
250 				 struct sof_ipc4_available_audio_format *available_fmt,
251 				 int in_fmt_index, int out_fmt_index)
252 {
253 	struct sof_ipc4_audio_format *in_fmt, *out_fmt;
254 	u32 out_rate, out_channels, out_valid_bits;
255 	u32 in_rate, in_channels, in_valid_bits;
256 	struct sof_ipc4_pin_format *pin_fmt;
257 
258 	if (!available_fmt->num_input_formats &&
259 	    !available_fmt->num_output_formats)
260 		return;
261 
262 	/* Only input or output is supported by the module */
263 	if (!available_fmt->num_input_formats) {
264 		if (available_fmt->num_output_formats == 1)
265 			dev_dbg(dev, "Output audio format for %s:\n",
266 				swidget->widget->name);
267 		else
268 			dev_dbg(dev,
269 				"Output audio format (format index: %d) for %s:\n",
270 				out_fmt_index, swidget->widget->name);
271 
272 		pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index];
273 		sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
274 
275 		return;
276 	} else if (!available_fmt->num_output_formats) {
277 		if (available_fmt->num_input_formats == 1)
278 			dev_dbg(dev, "Input audio format for %s:\n",
279 				swidget->widget->name);
280 		else
281 			dev_dbg(dev,
282 				"Input audio format (format index: %d) for %s:\n",
283 				out_fmt_index, swidget->widget->name);
284 
285 		pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
286 		sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
287 
288 		return;
289 	}
290 
291 	in_fmt = &available_fmt->input_pin_fmts[in_fmt_index].audio_fmt;
292 	out_fmt = &available_fmt->output_pin_fmts[out_fmt_index].audio_fmt;
293 
294 	in_rate = in_fmt->sampling_frequency;
295 	in_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
296 	in_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
297 
298 	out_rate = out_fmt->sampling_frequency;
299 	out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg);
300 	out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
301 
302 	if (!(in_valid_bits != out_valid_bits || in_rate != out_rate ||
303 	      in_channels != out_channels)) {
304 		/* There is no change in format */
305 		if (available_fmt->num_input_formats == 1 &&
306 		    available_fmt->num_output_formats == 1)
307 			dev_dbg(dev, "Audio format for %s:\n",
308 				swidget->widget->name);
309 		else
310 			dev_dbg(dev,
311 				"Audio format (in/out format index: %d/%d) for %s:\n",
312 				in_fmt_index, out_fmt_index, swidget->widget->name);
313 
314 		pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
315 		sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
316 
317 		return;
318 	}
319 
320 	/* The format is changed by the module */
321 	if (available_fmt->num_input_formats == 1)
322 		dev_dbg(dev, "Input audio format for %s:\n",
323 			swidget->widget->name);
324 	else
325 		dev_dbg(dev, "Input audio format (format index: %d) for %s:\n",
326 			in_fmt_index, swidget->widget->name);
327 
328 	pin_fmt = &available_fmt->input_pin_fmts[in_fmt_index];
329 	sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
330 
331 	if (available_fmt->num_output_formats == 1)
332 		dev_dbg(dev, "Output audio format for %s:\n",
333 			swidget->widget->name);
334 	else
335 		dev_dbg(dev, "Output audio format (format index: %d) for %s:\n",
336 			out_fmt_index, swidget->widget->name);
337 
338 	pin_fmt = &available_fmt->output_pin_fmts[out_fmt_index];
339 	sof_ipc4_dbg_audio_format(dev, pin_fmt, 1);
340 }
341 
342 static const struct sof_ipc4_audio_format *
sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget * swidget,int pin_index)343 sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index)
344 {
345 	struct sof_ipc4_base_module_cfg_ext *base_cfg_ext;
346 	struct sof_ipc4_process *process;
347 	int i;
348 
349 	if (swidget->id != snd_soc_dapm_effect) {
350 		struct sof_ipc4_base_module_cfg *base = swidget->private;
351 
352 		/* For non-process modules, base module config format is used for all input pins */
353 		return &base->audio_fmt;
354 	}
355 
356 	process = swidget->private;
357 
358 	/*
359 	 * For process modules without base config extension, base module config
360 	 * format is used for all input pins
361 	 */
362 	if (process->init_config != SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT)
363 		return &process->base_config.audio_fmt;
364 
365 	base_cfg_ext = process->base_config_ext;
366 
367 	/*
368 	 * If there are multiple input formats available for a pin, the first available format
369 	 * is chosen.
370 	 */
371 	for (i = 0; i < base_cfg_ext->num_input_pin_fmts; i++) {
372 		struct sof_ipc4_pin_format *pin_format = &base_cfg_ext->pin_formats[i];
373 
374 		if (pin_format->pin_index == pin_index)
375 			return &pin_format->audio_fmt;
376 	}
377 
378 	return NULL;
379 }
380 
381 /**
382  * sof_ipc4_get_audio_fmt - get available audio formats from swidget->tuples
383  * @scomp: pointer to pointer to SOC component
384  * @swidget: pointer to struct snd_sof_widget containing tuples
385  * @available_fmt: pointer to struct sof_ipc4_available_audio_format being filling in
386  * @module_base_cfg: Pointer to the base_config in the module init IPC payload
387  *
388  * Return: 0 if successful
389  */
sof_ipc4_get_audio_fmt(struct snd_soc_component * scomp,struct snd_sof_widget * swidget,struct sof_ipc4_available_audio_format * available_fmt,struct sof_ipc4_base_module_cfg * module_base_cfg)390 static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp,
391 				  struct snd_sof_widget *swidget,
392 				  struct sof_ipc4_available_audio_format *available_fmt,
393 				  struct sof_ipc4_base_module_cfg *module_base_cfg)
394 {
395 	struct sof_ipc4_pin_format *in_format = NULL;
396 	struct sof_ipc4_pin_format *out_format;
397 	int ret;
398 
399 	ret = sof_update_ipc_object(scomp, available_fmt,
400 				    SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples,
401 				    swidget->num_tuples, sizeof(*available_fmt), 1);
402 	if (ret) {
403 		dev_err(scomp->dev, "Failed to parse audio format token count\n");
404 		return ret;
405 	}
406 
407 	if (!available_fmt->num_input_formats && !available_fmt->num_output_formats) {
408 		dev_err(scomp->dev, "No input/output pin formats set in topology\n");
409 		return -EINVAL;
410 	}
411 
412 	dev_dbg(scomp->dev,
413 		"Number of input audio formats: %d. Number of output audio formats: %d\n",
414 		available_fmt->num_input_formats, available_fmt->num_output_formats);
415 
416 	/* set is_pages in the module's base_config */
417 	ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples,
418 				    swidget->num_tuples, sizeof(*module_base_cfg), 1);
419 	if (ret) {
420 		dev_err(scomp->dev, "parse comp tokens for %s failed, error: %d\n",
421 			swidget->widget->name, ret);
422 		return ret;
423 	}
424 
425 	dev_dbg(scomp->dev, "widget %s: is_pages: %d\n", swidget->widget->name,
426 		module_base_cfg->is_pages);
427 
428 	if (available_fmt->num_input_formats) {
429 		in_format = kcalloc(available_fmt->num_input_formats,
430 				    sizeof(*in_format), GFP_KERNEL);
431 		if (!in_format)
432 			return -ENOMEM;
433 		available_fmt->input_pin_fmts = in_format;
434 
435 		ret = sof_update_ipc_object(scomp, in_format,
436 					    SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples,
437 					    swidget->num_tuples, sizeof(*in_format),
438 					    available_fmt->num_input_formats);
439 		if (ret) {
440 			dev_err(scomp->dev, "parse input audio fmt tokens failed %d\n", ret);
441 			goto err_in;
442 		}
443 
444 		dev_dbg(scomp->dev, "Input audio formats for %s\n", swidget->widget->name);
445 		sof_ipc4_dbg_audio_format(scomp->dev, in_format,
446 					  available_fmt->num_input_formats);
447 	}
448 
449 	if (available_fmt->num_output_formats) {
450 		out_format = kcalloc(available_fmt->num_output_formats, sizeof(*out_format),
451 				     GFP_KERNEL);
452 		if (!out_format) {
453 			ret = -ENOMEM;
454 			goto err_in;
455 		}
456 
457 		ret = sof_update_ipc_object(scomp, out_format,
458 					    SOF_OUT_AUDIO_FORMAT_TOKENS, swidget->tuples,
459 					    swidget->num_tuples, sizeof(*out_format),
460 					    available_fmt->num_output_formats);
461 		if (ret) {
462 			dev_err(scomp->dev, "parse output audio fmt tokens failed\n");
463 			goto err_out;
464 		}
465 
466 		available_fmt->output_pin_fmts = out_format;
467 		dev_dbg(scomp->dev, "Output audio formats for %s\n", swidget->widget->name);
468 		sof_ipc4_dbg_audio_format(scomp->dev, out_format,
469 					  available_fmt->num_output_formats);
470 	}
471 
472 	return 0;
473 
474 err_out:
475 	kfree(out_format);
476 err_in:
477 	kfree(in_format);
478 	available_fmt->input_pin_fmts = NULL;
479 	return ret;
480 }
481 
482 /* release the memory allocated in sof_ipc4_get_audio_fmt */
sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format * available_fmt)483 static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *available_fmt)
484 
485 {
486 	kfree(available_fmt->output_pin_fmts);
487 	available_fmt->output_pin_fmts = NULL;
488 	kfree(available_fmt->input_pin_fmts);
489 	available_fmt->input_pin_fmts = NULL;
490 }
491 
sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget * swidget)492 static void sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget *swidget)
493 {
494 	kfree(swidget->private);
495 }
496 
sof_ipc4_widget_set_module_info(struct snd_sof_widget * swidget)497 static int sof_ipc4_widget_set_module_info(struct snd_sof_widget *swidget)
498 {
499 	struct snd_soc_component *scomp = swidget->scomp;
500 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
501 
502 	swidget->module_info = sof_ipc4_find_module_by_uuid(sdev, &swidget->uuid);
503 
504 	if (swidget->module_info)
505 		return 0;
506 
507 	dev_err(sdev->dev, "failed to find module info for widget %s with UUID %pUL\n",
508 		swidget->widget->name, &swidget->uuid);
509 	return -EINVAL;
510 }
511 
sof_ipc4_widget_setup_msg(struct snd_sof_widget * swidget,struct sof_ipc4_msg * msg)512 static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ipc4_msg *msg)
513 {
514 	struct sof_ipc4_fw_module *fw_module;
515 	uint32_t type;
516 	int ret;
517 
518 	ret = sof_ipc4_widget_set_module_info(swidget);
519 	if (ret)
520 		return ret;
521 
522 	fw_module = swidget->module_info;
523 
524 	msg->primary = fw_module->man4_module_entry.id;
525 	msg->primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_INIT_INSTANCE);
526 	msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
527 	msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
528 
529 	msg->extension = SOF_IPC4_MOD_EXT_CORE_ID(swidget->core);
530 
531 	switch (swidget->comp_domain) {
532 	case SOF_COMP_DOMAIN_LL:
533 		type = 0;
534 		break;
535 	case SOF_COMP_DOMAIN_DP:
536 		type = 1;
537 		break;
538 	default:
539 		type = (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP) ? 1 : 0;
540 		break;
541 	}
542 	msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type);
543 
544 	return 0;
545 }
546 
sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget * swidget)547 static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swidget)
548 {
549 	struct snd_soc_component *scomp = swidget->scomp;
550 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
551 	struct sof_ipc4_fw_module *fw_module = swidget->module_info;
552 	struct snd_sof_control *scontrol;
553 
554 	/* update module ID for all kcontrols for this widget */
555 	list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
556 		if (scontrol->comp_id == swidget->comp_id) {
557 			struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
558 			struct sof_ipc4_msg *msg = &cdata->msg;
559 
560 			msg->primary |= fw_module->man4_module_entry.id;
561 		}
562 	}
563 }
564 
565 static int
sof_ipc4_update_card_components_string(struct snd_sof_widget * swidget,struct snd_sof_pcm * spcm,int dir)566 sof_ipc4_update_card_components_string(struct snd_sof_widget *swidget,
567 				       struct snd_sof_pcm *spcm, int dir)
568 {
569 	struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
570 	struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
571 	struct snd_soc_component *scomp = spcm->scomp;
572 	struct snd_soc_card *card = scomp->card;
573 	const char *pt_marker = "iec61937-pcm";
574 
575 	/*
576 	 * Update the card's components list with iec61937-pcm and a list of PCM
577 	 * ids where ChainDMA is enabled.
578 	 * These PCMs can be used for bytestream passthrough.
579 	 */
580 	if (!pipeline->use_chain_dma)
581 		return 0;
582 
583 	if (card->components) {
584 		const char *tmp = card->components;
585 
586 		if (strstr(card->components, pt_marker))
587 			card->components = devm_kasprintf(card->dev, GFP_KERNEL,
588 							  "%s,%d",
589 							  card->components,
590 							  spcm->pcm.pcm_id);
591 		else
592 			card->components = devm_kasprintf(card->dev, GFP_KERNEL,
593 							  "%s %s:%d",
594 							  card->components,
595 							  pt_marker,
596 							  spcm->pcm.pcm_id);
597 
598 		devm_kfree(card->dev, tmp);
599 	} else {
600 		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
601 						  "%s:%d", pt_marker,
602 						  spcm->pcm.pcm_id);
603 	}
604 
605 	if (!card->components)
606 		return -ENOMEM;
607 
608 	return 0;
609 }
610 
sof_ipc4_widget_setup_pcm(struct snd_sof_widget * swidget)611 static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
612 {
613 	struct sof_ipc4_available_audio_format *available_fmt;
614 	struct snd_soc_component *scomp = swidget->scomp;
615 	struct sof_ipc4_copier *ipc4_copier;
616 	struct snd_sof_pcm *spcm;
617 	int node_type = 0;
618 	int ret, dir;
619 
620 	ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL);
621 	if (!ipc4_copier)
622 		return -ENOMEM;
623 
624 	swidget->private = ipc4_copier;
625 	available_fmt = &ipc4_copier->available_fmt;
626 
627 	dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
628 
629 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt,
630 				     &ipc4_copier->data.base_config);
631 	if (ret)
632 		goto free_copier;
633 
634 	/*
635 	 * This callback is used by host copier and module-to-module copier,
636 	 * and only host copier needs to set gtw_cfg.
637 	 */
638 	if (!WIDGET_IS_AIF(swidget->id))
639 		goto skip_gtw_cfg;
640 
641 	ret = sof_update_ipc_object(scomp, &node_type,
642 				    SOF_COPIER_TOKENS, swidget->tuples,
643 				    swidget->num_tuples, sizeof(node_type), 1);
644 
645 	if (ret) {
646 		dev_err(scomp->dev, "parse host copier node type token failed %d\n",
647 			ret);
648 		goto free_available_fmt;
649 	}
650 	dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type);
651 
652 	spcm = snd_sof_find_spcm_comp(scomp, swidget->comp_id, &dir);
653 	if (!spcm)
654 		goto skip_gtw_cfg;
655 
656 	ret = sof_ipc4_update_card_components_string(swidget, spcm, dir);
657 	if (ret)
658 		goto free_available_fmt;
659 
660 	if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
661 		struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
662 
663 		sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
664 				      SOF_COPIER_DEEP_BUFFER_TOKENS,
665 				      swidget->tuples,
666 				      swidget->num_tuples, sizeof(u32), 1);
667 		/* Set default DMA buffer size if it is not specified in topology */
668 		if (!sps->dsp_max_burst_size_in_ms) {
669 			struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
670 			struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
671 
672 			sps->dsp_max_burst_size_in_ms = pipeline->use_chain_dma ?
673 				SOF_IPC4_CHAIN_DMA_BUFFER_SIZE : SOF_IPC4_MIN_DMA_BUFFER_SIZE;
674 		}
675 	} else {
676 		/* Capture data is copied from DSP to host in 1ms bursts */
677 		spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
678 	}
679 
680 skip_gtw_cfg:
681 	ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL);
682 	if (!ipc4_copier->gtw_attr) {
683 		ret = -ENOMEM;
684 		goto free_available_fmt;
685 	}
686 
687 	ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr;
688 	ipc4_copier->data.gtw_cfg.config_length =
689 		sizeof(struct sof_ipc4_gtw_attributes) >> 2;
690 
691 	switch (swidget->id) {
692 	case snd_soc_dapm_aif_in:
693 	case snd_soc_dapm_aif_out:
694 		ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_NODE_TYPE(node_type);
695 		break;
696 	case snd_soc_dapm_buffer:
697 		ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_INVALID_NODE_ID;
698 		ipc4_copier->ipc_config_size = 0;
699 		break;
700 	default:
701 		dev_err(scomp->dev, "invalid widget type %d\n", swidget->id);
702 		ret = -EINVAL;
703 		goto free_gtw_attr;
704 	}
705 
706 	/* set up module info and message header */
707 	ret = sof_ipc4_widget_setup_msg(swidget, &ipc4_copier->msg);
708 	if (ret)
709 		goto free_gtw_attr;
710 
711 	return 0;
712 
713 free_gtw_attr:
714 	kfree(ipc4_copier->gtw_attr);
715 free_available_fmt:
716 	sof_ipc4_free_audio_fmt(available_fmt);
717 free_copier:
718 	kfree(ipc4_copier);
719 	swidget->private = NULL;
720 	return ret;
721 }
722 
sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget * swidget)723 static void sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget *swidget)
724 {
725 	struct sof_ipc4_copier *ipc4_copier = swidget->private;
726 	struct sof_ipc4_available_audio_format *available_fmt;
727 
728 	if (!ipc4_copier)
729 		return;
730 
731 	available_fmt = &ipc4_copier->available_fmt;
732 	kfree(available_fmt->output_pin_fmts);
733 	kfree(ipc4_copier->gtw_attr);
734 	kfree(ipc4_copier);
735 	swidget->private = NULL;
736 }
737 
sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget * swidget)738 static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
739 {
740 	struct sof_ipc4_available_audio_format *available_fmt;
741 	struct snd_soc_component *scomp = swidget->scomp;
742 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
743 	struct snd_sof_dai *dai = swidget->private;
744 	struct sof_ipc4_copier *ipc4_copier;
745 	struct snd_sof_widget *pipe_widget;
746 	struct sof_ipc4_pipeline *pipeline;
747 	int node_type = 0;
748 	int ret;
749 
750 	ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL);
751 	if (!ipc4_copier)
752 		return -ENOMEM;
753 
754 	available_fmt = &ipc4_copier->available_fmt;
755 
756 	dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
757 
758 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt,
759 				     &ipc4_copier->data.base_config);
760 	if (ret)
761 		goto free_copier;
762 
763 	ret = sof_update_ipc_object(scomp, &node_type,
764 				    SOF_COPIER_TOKENS, swidget->tuples,
765 				    swidget->num_tuples, sizeof(node_type), 1);
766 	if (ret) {
767 		dev_err(scomp->dev, "parse dai node type failed %d\n", ret);
768 		goto free_available_fmt;
769 	}
770 
771 	ret = sof_update_ipc_object(scomp, ipc4_copier,
772 				    SOF_DAI_TOKENS, swidget->tuples,
773 				    swidget->num_tuples, sizeof(u32), 1);
774 	if (ret) {
775 		dev_err(scomp->dev, "parse dai copier node token failed %d\n", ret);
776 		goto free_available_fmt;
777 	}
778 
779 	dev_dbg(scomp->dev, "dai %s node_type %u dai_type %u dai_index %d\n", swidget->widget->name,
780 		node_type, ipc4_copier->dai_type, ipc4_copier->dai_index);
781 
782 	dai->type = ipc4_copier->dai_type;
783 	ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_NODE_TYPE(node_type);
784 
785 	pipe_widget = swidget->spipe->pipe_widget;
786 	pipeline = pipe_widget->private;
787 
788 	if (pipeline->use_chain_dma &&
789 	    !snd_sof_is_chain_dma_supported(sdev, ipc4_copier->dai_type)) {
790 		dev_err(scomp->dev, "Bad DAI type '%d', Chain DMA is not supported\n",
791 			ipc4_copier->dai_type);
792 		ret = -ENODEV;
793 		goto free_available_fmt;
794 	}
795 
796 	switch (ipc4_copier->dai_type) {
797 	case SOF_DAI_INTEL_ALH:
798 	{
799 		struct sof_ipc4_alh_configuration_blob *blob;
800 		struct snd_soc_dapm_path *p;
801 		struct snd_sof_widget *w;
802 		int src_num = 0;
803 
804 		snd_soc_dapm_widget_for_each_source_path(swidget->widget, p)
805 			src_num++;
806 
807 		if (swidget->id == snd_soc_dapm_dai_in && src_num == 0) {
808 			/*
809 			 * The blob will not be used if the ALH copier is playback direction
810 			 * and doesn't connect to any source.
811 			 * It is fine to call kfree(ipc4_copier->copier_config) since
812 			 * ipc4_copier->copier_config is null.
813 			 */
814 			break;
815 		}
816 
817 		blob = kzalloc(sizeof(*blob), GFP_KERNEL);
818 		if (!blob) {
819 			ret = -ENOMEM;
820 			goto free_available_fmt;
821 		}
822 
823 		list_for_each_entry(w, &sdev->widget_list, list) {
824 			struct snd_sof_dai *alh_dai;
825 
826 			if (!WIDGET_IS_DAI(w->id) || !w->widget->sname ||
827 			    strcmp(w->widget->sname, swidget->widget->sname))
828 				continue;
829 
830 			alh_dai = w->private;
831 			if (alh_dai->type != SOF_DAI_INTEL_ALH)
832 				continue;
833 
834 			blob->alh_cfg.device_count++;
835 		}
836 
837 		ipc4_copier->copier_config = (uint32_t *)blob;
838 		/* set data.gtw_cfg.config_length based on device_count */
839 		ipc4_copier->data.gtw_cfg.config_length = (sizeof(blob->gw_attr) +
840 							   sizeof(blob->alh_cfg.device_count) +
841 							   sizeof(*blob->alh_cfg.mapping) *
842 							   blob->alh_cfg.device_count) >> 2;
843 		break;
844 	}
845 	case SOF_DAI_INTEL_SSP:
846 		/* set SSP DAI index as the node_id */
847 		ipc4_copier->data.gtw_cfg.node_id |=
848 			SOF_IPC4_NODE_INDEX_INTEL_SSP(ipc4_copier->dai_index);
849 		break;
850 	case SOF_DAI_INTEL_DMIC:
851 		/* set DMIC DAI index as the node_id */
852 		ipc4_copier->data.gtw_cfg.node_id |=
853 			SOF_IPC4_NODE_INDEX_INTEL_DMIC(ipc4_copier->dai_index);
854 		break;
855 	default:
856 		ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL);
857 		if (!ipc4_copier->gtw_attr) {
858 			ret = -ENOMEM;
859 			goto free_available_fmt;
860 		}
861 
862 		ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr;
863 		ipc4_copier->data.gtw_cfg.config_length =
864 			sizeof(struct sof_ipc4_gtw_attributes) >> 2;
865 		break;
866 	}
867 
868 	dai->scomp = scomp;
869 	dai->private = ipc4_copier;
870 
871 	/* set up module info and message header */
872 	ret = sof_ipc4_widget_setup_msg(swidget, &ipc4_copier->msg);
873 	if (ret)
874 		goto free_copier_config;
875 
876 	return 0;
877 
878 free_copier_config:
879 	kfree(ipc4_copier->copier_config);
880 free_available_fmt:
881 	sof_ipc4_free_audio_fmt(available_fmt);
882 free_copier:
883 	kfree(ipc4_copier);
884 	dai->private = NULL;
885 	dai->scomp = NULL;
886 	return ret;
887 }
888 
sof_ipc4_widget_free_comp_dai(struct snd_sof_widget * swidget)889 static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget)
890 {
891 	struct sof_ipc4_available_audio_format *available_fmt;
892 	struct snd_sof_dai *dai = swidget->private;
893 	struct sof_ipc4_copier *ipc4_copier;
894 
895 	if (!dai)
896 		return;
897 
898 	if (!dai->private) {
899 		kfree(dai);
900 		swidget->private = NULL;
901 		return;
902 	}
903 
904 	ipc4_copier = dai->private;
905 	available_fmt = &ipc4_copier->available_fmt;
906 
907 	kfree(available_fmt->output_pin_fmts);
908 	if (ipc4_copier->dai_type != SOF_DAI_INTEL_SSP &&
909 	    ipc4_copier->dai_type != SOF_DAI_INTEL_DMIC)
910 		kfree(ipc4_copier->copier_config);
911 	kfree(dai->private);
912 	kfree(dai);
913 	swidget->private = NULL;
914 }
915 
sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget * swidget)916 static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
917 {
918 	struct snd_soc_component *scomp = swidget->scomp;
919 	struct sof_ipc4_pipeline *pipeline;
920 	struct snd_sof_pipeline *spipe = swidget->spipe;
921 	int ret;
922 
923 	pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
924 	if (!pipeline)
925 		return -ENOMEM;
926 
927 	ret = sof_update_ipc_object(scomp, pipeline, SOF_SCHED_TOKENS, swidget->tuples,
928 				    swidget->num_tuples, sizeof(*pipeline), 1);
929 	if (ret) {
930 		dev_err(scomp->dev, "parsing scheduler tokens failed\n");
931 		goto err;
932 	}
933 
934 	swidget->core = pipeline->core_id;
935 	spipe->core_mask |= BIT(pipeline->core_id);
936 
937 	if (pipeline->use_chain_dma) {
938 		dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name);
939 		swidget->private = pipeline;
940 		return 0;
941 	}
942 
943 	/* parse one set of pipeline tokens */
944 	ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples,
945 				    swidget->num_tuples, sizeof(*swidget), 1);
946 	if (ret) {
947 		dev_err(scomp->dev, "parsing pipeline tokens failed\n");
948 		goto err;
949 	}
950 
951 	dev_dbg(scomp->dev, "pipeline '%s': id %d, pri %d, core_id %u, lp mode %d\n",
952 		swidget->widget->name, swidget->pipeline_id,
953 		pipeline->priority, pipeline->core_id, pipeline->lp_mode);
954 
955 	swidget->private = pipeline;
956 
957 	pipeline->msg.primary = SOF_IPC4_GLB_PIPE_PRIORITY(pipeline->priority);
958 	pipeline->msg.primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_CREATE_PIPELINE);
959 	pipeline->msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
960 	pipeline->msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG);
961 
962 	pipeline->msg.extension = pipeline->lp_mode;
963 	pipeline->msg.extension |= SOF_IPC4_GLB_PIPE_EXT_CORE_ID(pipeline->core_id);
964 	pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED;
965 
966 	return 0;
967 err:
968 	kfree(pipeline);
969 	return ret;
970 }
971 
sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget * swidget)972 static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
973 {
974 	struct snd_soc_component *scomp = swidget->scomp;
975 	struct sof_ipc4_gain *gain;
976 	int ret;
977 
978 	gain = kzalloc(sizeof(*gain), GFP_KERNEL);
979 	if (!gain)
980 		return -ENOMEM;
981 
982 	swidget->private = gain;
983 
984 	gain->data.params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
985 	gain->data.params.init_val = SOF_IPC4_VOL_ZERO_DB;
986 
987 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->data.base_config);
988 	if (ret)
989 		goto err;
990 
991 	ret = sof_update_ipc_object(scomp, &gain->data.params, SOF_GAIN_TOKENS,
992 				    swidget->tuples, swidget->num_tuples, sizeof(gain->data), 1);
993 	if (ret) {
994 		dev_err(scomp->dev, "Parsing gain tokens failed\n");
995 		goto err;
996 	}
997 
998 	dev_dbg(scomp->dev,
999 		"pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x\n",
1000 		swidget->widget->name, gain->data.params.curve_type,
1001 		gain->data.params.curve_duration_l, gain->data.params.init_val);
1002 
1003 	ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg);
1004 	if (ret)
1005 		goto err;
1006 
1007 	sof_ipc4_widget_update_kcontrol_module_id(swidget);
1008 
1009 	return 0;
1010 err:
1011 	sof_ipc4_free_audio_fmt(&gain->available_fmt);
1012 	kfree(gain);
1013 	swidget->private = NULL;
1014 	return ret;
1015 }
1016 
sof_ipc4_widget_free_comp_pga(struct snd_sof_widget * swidget)1017 static void sof_ipc4_widget_free_comp_pga(struct snd_sof_widget *swidget)
1018 {
1019 	struct sof_ipc4_gain *gain = swidget->private;
1020 
1021 	if (!gain)
1022 		return;
1023 
1024 	sof_ipc4_free_audio_fmt(&gain->available_fmt);
1025 	kfree(swidget->private);
1026 	swidget->private = NULL;
1027 }
1028 
sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget * swidget)1029 static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
1030 {
1031 	struct snd_soc_component *scomp = swidget->scomp;
1032 	struct sof_ipc4_mixer *mixer;
1033 	int ret;
1034 
1035 	dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
1036 
1037 	mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
1038 	if (!mixer)
1039 		return -ENOMEM;
1040 
1041 	swidget->private = mixer;
1042 
1043 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt,
1044 				     &mixer->base_config);
1045 	if (ret)
1046 		goto err;
1047 
1048 	ret = sof_ipc4_widget_setup_msg(swidget, &mixer->msg);
1049 	if (ret)
1050 		goto err;
1051 
1052 	return 0;
1053 err:
1054 	sof_ipc4_free_audio_fmt(&mixer->available_fmt);
1055 	kfree(mixer);
1056 	swidget->private = NULL;
1057 	return ret;
1058 }
1059 
sof_ipc4_widget_setup_comp_src(struct snd_sof_widget * swidget)1060 static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
1061 {
1062 	struct snd_soc_component *scomp = swidget->scomp;
1063 	struct snd_sof_pipeline *spipe = swidget->spipe;
1064 	struct sof_ipc4_src *src;
1065 	int ret;
1066 
1067 	dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
1068 
1069 	src = kzalloc(sizeof(*src), GFP_KERNEL);
1070 	if (!src)
1071 		return -ENOMEM;
1072 
1073 	swidget->private = src;
1074 
1075 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt,
1076 				     &src->data.base_config);
1077 	if (ret)
1078 		goto err;
1079 
1080 	ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples,
1081 				    swidget->num_tuples, sizeof(*src), 1);
1082 	if (ret) {
1083 		dev_err(scomp->dev, "Parsing SRC tokens failed\n");
1084 		goto err;
1085 	}
1086 
1087 	spipe->core_mask |= BIT(swidget->core);
1088 
1089 	dev_dbg(scomp->dev, "SRC sink rate %d\n", src->data.sink_rate);
1090 
1091 	ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
1092 	if (ret)
1093 		goto err;
1094 
1095 	return 0;
1096 err:
1097 	sof_ipc4_free_audio_fmt(&src->available_fmt);
1098 	kfree(src);
1099 	swidget->private = NULL;
1100 	return ret;
1101 }
1102 
sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget * swidget)1103 static int sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget *swidget)
1104 {
1105 	struct snd_soc_component *scomp = swidget->scomp;
1106 	struct snd_sof_pipeline *spipe = swidget->spipe;
1107 	struct sof_ipc4_asrc *asrc;
1108 	int ret;
1109 
1110 	dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
1111 
1112 	asrc = kzalloc(sizeof(*asrc), GFP_KERNEL);
1113 	if (!asrc)
1114 		return -ENOMEM;
1115 
1116 	swidget->private = asrc;
1117 
1118 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &asrc->available_fmt,
1119 				     &asrc->data.base_config);
1120 	if (ret)
1121 		goto err;
1122 
1123 	ret = sof_update_ipc_object(scomp, &asrc->data, SOF_ASRC_TOKENS, swidget->tuples,
1124 				    swidget->num_tuples, sizeof(*asrc), 1);
1125 	if (ret) {
1126 		dev_err(scomp->dev, "Parsing ASRC tokens failed\n");
1127 		goto err;
1128 	}
1129 
1130 	spipe->core_mask |= BIT(swidget->core);
1131 
1132 	dev_dbg(scomp->dev, "ASRC sink rate %d, mode 0x%08x\n",
1133 		asrc->data.out_freq, asrc->data.asrc_mode);
1134 
1135 	ret = sof_ipc4_widget_setup_msg(swidget, &asrc->msg);
1136 	if (ret)
1137 		goto err;
1138 
1139 	return 0;
1140 err:
1141 	sof_ipc4_free_audio_fmt(&asrc->available_fmt);
1142 	kfree(asrc);
1143 	swidget->private = NULL;
1144 	return ret;
1145 }
1146 
sof_ipc4_widget_free_comp_src(struct snd_sof_widget * swidget)1147 static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
1148 {
1149 	struct sof_ipc4_src *src = swidget->private;
1150 
1151 	if (!src)
1152 		return;
1153 
1154 	sof_ipc4_free_audio_fmt(&src->available_fmt);
1155 	kfree(swidget->private);
1156 	swidget->private = NULL;
1157 }
1158 
sof_ipc4_widget_free_comp_asrc(struct snd_sof_widget * swidget)1159 static void sof_ipc4_widget_free_comp_asrc(struct snd_sof_widget *swidget)
1160 {
1161 	struct sof_ipc4_asrc *asrc = swidget->private;
1162 
1163 	if (!asrc)
1164 		return;
1165 
1166 	sof_ipc4_free_audio_fmt(&asrc->available_fmt);
1167 	kfree(swidget->private);
1168 	swidget->private = NULL;
1169 }
1170 
sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget * swidget)1171 static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
1172 {
1173 	struct sof_ipc4_mixer *mixer = swidget->private;
1174 
1175 	if (!mixer)
1176 		return;
1177 
1178 	sof_ipc4_free_audio_fmt(&mixer->available_fmt);
1179 	kfree(swidget->private);
1180 	swidget->private = NULL;
1181 }
1182 
1183 /*
1184  * Add the process modules support. The process modules are defined as snd_soc_dapm_effect modules.
1185  */
sof_ipc4_widget_setup_comp_process(struct snd_sof_widget * swidget)1186 static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
1187 {
1188 	struct snd_soc_component *scomp = swidget->scomp;
1189 	struct sof_ipc4_fw_module *fw_module;
1190 	struct snd_sof_pipeline *spipe = swidget->spipe;
1191 	struct sof_ipc4_process *process;
1192 	void *cfg;
1193 	int ret;
1194 
1195 	process = kzalloc(sizeof(*process), GFP_KERNEL);
1196 	if (!process)
1197 		return -ENOMEM;
1198 
1199 	swidget->private = process;
1200 
1201 	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &process->available_fmt,
1202 				     &process->base_config);
1203 	if (ret)
1204 		goto err;
1205 
1206 	ret = sof_ipc4_widget_setup_msg(swidget, &process->msg);
1207 	if (ret)
1208 		goto err;
1209 
1210 	/* parse process init module payload config type from module info */
1211 	fw_module = swidget->module_info;
1212 	process->init_config = FIELD_GET(SOF_IPC4_MODULE_INIT_CONFIG_MASK,
1213 					 fw_module->man4_module_entry.type);
1214 
1215 	process->ipc_config_size = sizeof(struct sof_ipc4_base_module_cfg);
1216 
1217 	/* allocate memory for base config extension if needed */
1218 	if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) {
1219 		struct sof_ipc4_base_module_cfg_ext *base_cfg_ext;
1220 		u32 ext_size = struct_size(base_cfg_ext, pin_formats,
1221 					   size_add(swidget->num_input_pins,
1222 						    swidget->num_output_pins));
1223 
1224 		base_cfg_ext = kzalloc(ext_size, GFP_KERNEL);
1225 		if (!base_cfg_ext) {
1226 			ret = -ENOMEM;
1227 			goto free_available_fmt;
1228 		}
1229 
1230 		base_cfg_ext->num_input_pin_fmts = swidget->num_input_pins;
1231 		base_cfg_ext->num_output_pin_fmts = swidget->num_output_pins;
1232 		process->base_config_ext = base_cfg_ext;
1233 		process->base_config_ext_size = ext_size;
1234 		process->ipc_config_size += ext_size;
1235 	}
1236 
1237 	cfg = kzalloc(process->ipc_config_size, GFP_KERNEL);
1238 	if (!cfg) {
1239 		ret = -ENOMEM;
1240 		goto free_base_cfg_ext;
1241 	}
1242 
1243 	process->ipc_config_data = cfg;
1244 
1245 	sof_ipc4_widget_update_kcontrol_module_id(swidget);
1246 
1247 	/* set pipeline core mask to keep track of the core the module is scheduled to run on */
1248 	spipe->core_mask |= BIT(swidget->core);
1249 
1250 	return 0;
1251 free_base_cfg_ext:
1252 	kfree(process->base_config_ext);
1253 	process->base_config_ext = NULL;
1254 free_available_fmt:
1255 	sof_ipc4_free_audio_fmt(&process->available_fmt);
1256 err:
1257 	kfree(process);
1258 	swidget->private = NULL;
1259 	return ret;
1260 }
1261 
sof_ipc4_widget_free_comp_process(struct snd_sof_widget * swidget)1262 static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget)
1263 {
1264 	struct sof_ipc4_process *process = swidget->private;
1265 
1266 	if (!process)
1267 		return;
1268 
1269 	kfree(process->ipc_config_data);
1270 	kfree(process->base_config_ext);
1271 	sof_ipc4_free_audio_fmt(&process->available_fmt);
1272 	kfree(swidget->private);
1273 	swidget->private = NULL;
1274 }
1275 
1276 static void
sof_ipc4_update_resource_usage(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget,struct sof_ipc4_base_module_cfg * base_config)1277 sof_ipc4_update_resource_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
1278 			       struct sof_ipc4_base_module_cfg *base_config)
1279 {
1280 	struct sof_ipc4_fw_module *fw_module = swidget->module_info;
1281 	struct snd_sof_widget *pipe_widget;
1282 	struct sof_ipc4_pipeline *pipeline;
1283 	int task_mem, queue_mem;
1284 	int ibs, bss, total;
1285 
1286 	ibs = base_config->ibs;
1287 	bss = base_config->is_pages;
1288 
1289 	task_mem = SOF_IPC4_PIPELINE_OBJECT_SIZE;
1290 	task_mem += SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE + bss;
1291 
1292 	if (fw_module->man4_module_entry.type & SOF_IPC4_MODULE_LL) {
1293 		task_mem += SOF_IPC4_FW_ROUNDUP(SOF_IPC4_LL_TASK_OBJECT_SIZE);
1294 		task_mem += SOF_IPC4_FW_MAX_QUEUE_COUNT * SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE;
1295 		task_mem += SOF_IPC4_LL_TASK_LIST_ITEM_SIZE;
1296 	} else {
1297 		task_mem += SOF_IPC4_FW_ROUNDUP(SOF_IPC4_DP_TASK_OBJECT_SIZE);
1298 		task_mem += SOF_IPC4_DP_TASK_LIST_SIZE;
1299 	}
1300 
1301 	ibs = SOF_IPC4_FW_ROUNDUP(ibs);
1302 	queue_mem = SOF_IPC4_FW_MAX_QUEUE_COUNT * (SOF_IPC4_DATA_QUEUE_OBJECT_SIZE +  ibs);
1303 
1304 	total = SOF_IPC4_FW_PAGE(task_mem + queue_mem);
1305 
1306 	pipe_widget = swidget->spipe->pipe_widget;
1307 	pipeline = pipe_widget->private;
1308 	pipeline->mem_usage += total;
1309 
1310 	/* Update base_config->cpc from the module manifest */
1311 	sof_ipc4_update_cpc_from_manifest(sdev, fw_module, base_config);
1312 
1313 	if (ignore_cpc) {
1314 		dev_dbg(sdev->dev, "%s: ibs / obs: %u / %u, forcing cpc to 0 from %u\n",
1315 			swidget->widget->name, base_config->ibs, base_config->obs,
1316 			base_config->cpc);
1317 		base_config->cpc = 0;
1318 	} else {
1319 		dev_dbg(sdev->dev, "%s: ibs / obs / cpc: %u / %u / %u\n",
1320 			swidget->widget->name, base_config->ibs, base_config->obs,
1321 			base_config->cpc);
1322 	}
1323 }
1324 
sof_ipc4_widget_assign_instance_id(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget)1325 static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev,
1326 					      struct snd_sof_widget *swidget)
1327 {
1328 	struct sof_ipc4_fw_module *fw_module = swidget->module_info;
1329 	int max_instances = fw_module->man4_module_entry.instance_max_count;
1330 
1331 	swidget->instance_id = ida_alloc_max(&fw_module->m_ida, max_instances, GFP_KERNEL);
1332 	if (swidget->instance_id < 0) {
1333 		dev_err(sdev->dev, "failed to assign instance id for widget %s",
1334 			swidget->widget->name);
1335 		return swidget->instance_id;
1336 	}
1337 
1338 	return 0;
1339 }
1340 
sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg)1341 static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg)
1342 {
1343 	/* Fetch  the sample type from the fmt for 8 and 32 bit formats */
1344 	u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg);
1345 
1346 	if (__bits == 8 || __bits == 32)
1347 		return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg);
1348 
1349 	/*
1350 	 * Return LSB integer type for 20 and 24 formats as the firmware is
1351 	 * handling the LSB/MSB alignment internally, for the kernel this
1352 	 * should not be taken into account, we treat them as LSB to match with
1353 	 * the format we support on the PCM side.
1354 	 */
1355 	return SOF_IPC4_TYPE_LSB_INTEGER;
1356 }
1357 
1358 /* update hw_params based on the audio stream format */
sof_ipc4_update_hw_params(struct snd_sof_dev * sdev,struct snd_pcm_hw_params * params,struct sof_ipc4_audio_format * fmt,u32 param_to_update)1359 static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params,
1360 				     struct sof_ipc4_audio_format *fmt, u32 param_to_update)
1361 {
1362 	struct snd_interval *i;
1363 
1364 	if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) {
1365 		int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1366 		int type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg);
1367 		snd_pcm_format_t snd_fmt;
1368 		struct snd_mask *m;
1369 
1370 		switch (valid_bits) {
1371 		case 8:
1372 			switch (type) {
1373 			case SOF_IPC4_TYPE_A_LAW:
1374 				snd_fmt = SNDRV_PCM_FORMAT_A_LAW;
1375 				break;
1376 			case SOF_IPC4_TYPE_MU_LAW:
1377 				snd_fmt = SNDRV_PCM_FORMAT_MU_LAW;
1378 				break;
1379 			case SOF_IPC4_TYPE_UNSIGNED_INTEGER:
1380 				snd_fmt = SNDRV_PCM_FORMAT_U8;
1381 				break;
1382 			default:
1383 				dev_err(sdev->dev, "Unsupported PCM 8-bit IPC4 type %d\n", type);
1384 				return -EINVAL;
1385 			}
1386 			break;
1387 		case 16:
1388 			snd_fmt = SNDRV_PCM_FORMAT_S16_LE;
1389 			break;
1390 		case 24:
1391 			snd_fmt = SNDRV_PCM_FORMAT_S24_LE;
1392 			break;
1393 		case 32:
1394 			switch (type) {
1395 			case SOF_IPC4_TYPE_LSB_INTEGER:
1396 				snd_fmt = SNDRV_PCM_FORMAT_S32_LE;
1397 				break;
1398 			case SOF_IPC4_TYPE_FLOAT:
1399 				snd_fmt = SNDRV_PCM_FORMAT_FLOAT_LE;
1400 				break;
1401 			default:
1402 				dev_err(sdev->dev, "Unsupported PCM 32-bit IPC4 type %d\n", type);
1403 				return -EINVAL;
1404 			}
1405 			break;
1406 		default:
1407 			dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits);
1408 			return -EINVAL;
1409 		}
1410 
1411 		m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1412 		snd_mask_none(m);
1413 		snd_mask_set_format(m, snd_fmt);
1414 	}
1415 
1416 	if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_RATE)) {
1417 		unsigned int rate = fmt->sampling_frequency;
1418 
1419 		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
1420 		i->min = rate;
1421 		i->max = rate;
1422 	}
1423 
1424 	if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_CHANNELS)) {
1425 		unsigned int channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1426 
1427 		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
1428 		i->min = channels;
1429 		i->max = channels;
1430 	}
1431 
1432 	return 0;
1433 }
1434 
sof_ipc4_is_single_format(struct snd_sof_dev * sdev,struct sof_ipc4_pin_format * pin_fmts,u32 pin_fmts_size)1435 static bool sof_ipc4_is_single_format(struct snd_sof_dev *sdev,
1436 				      struct sof_ipc4_pin_format *pin_fmts, u32 pin_fmts_size)
1437 {
1438 	struct sof_ipc4_audio_format *fmt;
1439 	u32 rate, channels, valid_bits;
1440 	int i;
1441 
1442 	fmt = &pin_fmts[0].audio_fmt;
1443 	rate = fmt->sampling_frequency;
1444 	channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1445 	valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1446 
1447 	/* check if all output formats in topology are the same */
1448 	for (i = 1; i < pin_fmts_size; i++) {
1449 		u32 _rate, _channels, _valid_bits;
1450 
1451 		fmt = &pin_fmts[i].audio_fmt;
1452 		_rate = fmt->sampling_frequency;
1453 		_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1454 		_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1455 
1456 		if (_rate != rate || _channels != channels || _valid_bits != valid_bits)
1457 			return false;
1458 	}
1459 
1460 	return true;
1461 }
1462 
sof_ipc4_init_output_audio_fmt(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget,struct sof_ipc4_base_module_cfg * base_config,struct sof_ipc4_available_audio_format * available_fmt,u32 out_ref_rate,u32 out_ref_channels,u32 out_ref_valid_bits,u32 out_ref_type)1463 static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev,
1464 					  struct snd_sof_widget *swidget,
1465 					  struct sof_ipc4_base_module_cfg *base_config,
1466 					  struct sof_ipc4_available_audio_format *available_fmt,
1467 					  u32 out_ref_rate, u32 out_ref_channels,
1468 					  u32 out_ref_valid_bits, u32 out_ref_type)
1469 {
1470 	struct sof_ipc4_pin_format *pin_fmts = available_fmt->output_pin_fmts;
1471 	u32 pin_fmts_size = available_fmt->num_output_formats;
1472 	bool single_format;
1473 	int i = 0;
1474 
1475 	if (!pin_fmts_size) {
1476 		dev_err(sdev->dev, "no output formats for %s\n",
1477 			swidget->widget->name);
1478 		return -EINVAL;
1479 	}
1480 
1481 	single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size);
1482 
1483 	/* pick the first format if there's only one available or if all formats are the same */
1484 	if (single_format)
1485 		goto out_fmt;
1486 
1487 	/*
1488 	 * if there are multiple output formats, then choose the output format that matches
1489 	 * the reference params
1490 	 */
1491 	for (i = 0; i < pin_fmts_size; i++) {
1492 		struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt;
1493 
1494 		u32 _out_rate, _out_channels, _out_valid_bits, _out_type;
1495 
1496 		_out_rate = fmt->sampling_frequency;
1497 		_out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1498 		_out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1499 		_out_type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg);
1500 
1501 		if (_out_rate == out_ref_rate && _out_channels == out_ref_channels &&
1502 		    _out_valid_bits == out_ref_valid_bits && _out_type == out_ref_type)
1503 			goto out_fmt;
1504 	}
1505 
1506 	dev_err(sdev->dev,
1507 		"%s: Unsupported audio format: %uHz, %ubit, %u channels, type: %d\n",
1508 		__func__, out_ref_rate, out_ref_valid_bits, out_ref_channels,
1509 		out_ref_type);
1510 
1511 	return -EINVAL;
1512 
1513 out_fmt:
1514 	base_config->obs = pin_fmts[i].buffer_size;
1515 
1516 	return i;
1517 }
1518 
sof_ipc4_get_valid_bits(struct snd_sof_dev * sdev,struct snd_pcm_hw_params * params)1519 static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
1520 {
1521 	switch (params_format(params)) {
1522 	case SNDRV_PCM_FORMAT_U8:
1523 	case SNDRV_PCM_FORMAT_MU_LAW:
1524 	case SNDRV_PCM_FORMAT_A_LAW:
1525 		return 8;
1526 	case SNDRV_PCM_FORMAT_S16_LE:
1527 		return 16;
1528 	case SNDRV_PCM_FORMAT_S24_LE:
1529 		return 24;
1530 	case SNDRV_PCM_FORMAT_S32_LE:
1531 		return 32;
1532 	case SNDRV_PCM_FORMAT_FLOAT_LE:
1533 		return 32;
1534 	default:
1535 		dev_err(sdev->dev, "invalid pcm frame format %d\n", params_format(params));
1536 		return -EINVAL;
1537 	}
1538 }
1539 
sof_ipc4_get_sample_type(struct snd_sof_dev * sdev,struct snd_pcm_hw_params * params)1540 static int sof_ipc4_get_sample_type(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params)
1541 {
1542 	switch (params_format(params)) {
1543 	case SNDRV_PCM_FORMAT_A_LAW:
1544 		return SOF_IPC4_TYPE_A_LAW;
1545 	case SNDRV_PCM_FORMAT_MU_LAW:
1546 		return SOF_IPC4_TYPE_MU_LAW;
1547 	case SNDRV_PCM_FORMAT_U8:
1548 		return SOF_IPC4_TYPE_UNSIGNED_INTEGER;
1549 	case SNDRV_PCM_FORMAT_S16_LE:
1550 	case SNDRV_PCM_FORMAT_S24_LE:
1551 	case SNDRV_PCM_FORMAT_S32_LE:
1552 	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
1553 		return SOF_IPC4_TYPE_LSB_INTEGER;
1554 	case SNDRV_PCM_FORMAT_FLOAT_LE:
1555 		return SOF_IPC4_TYPE_FLOAT;
1556 	default:
1557 		dev_err(sdev->dev, "invalid pcm sample type %d\n", params_format(params));
1558 		return -EINVAL;
1559 	}
1560 }
1561 
sof_ipc4_init_input_audio_fmt(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget,struct sof_ipc4_base_module_cfg * base_config,struct snd_pcm_hw_params * params,struct sof_ipc4_available_audio_format * available_fmt)1562 static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev,
1563 					 struct snd_sof_widget *swidget,
1564 					 struct sof_ipc4_base_module_cfg *base_config,
1565 					 struct snd_pcm_hw_params *params,
1566 					 struct sof_ipc4_available_audio_format *available_fmt)
1567 {
1568 	struct sof_ipc4_pin_format *pin_fmts = available_fmt->input_pin_fmts;
1569 	u32 pin_fmts_size = available_fmt->num_input_formats;
1570 	u32 valid_bits;
1571 	u32 channels;
1572 	u32 rate;
1573 	u32 type;
1574 	bool single_format;
1575 	int sample_valid_bits;
1576 	int sample_type;
1577 	int i = 0;
1578 
1579 	if (!pin_fmts_size) {
1580 		dev_err(sdev->dev, "no input formats for %s\n", swidget->widget->name);
1581 		return -EINVAL;
1582 	}
1583 
1584 	single_format = sof_ipc4_is_single_format(sdev, pin_fmts, pin_fmts_size);
1585 	if (single_format)
1586 		goto in_fmt;
1587 
1588 	sample_valid_bits = sof_ipc4_get_valid_bits(sdev, params);
1589 	if (sample_valid_bits < 0)
1590 		return sample_valid_bits;
1591 
1592 	sample_type = sof_ipc4_get_sample_type(sdev, params);
1593 	if (sample_type < 0)
1594 		return sample_type;
1595 
1596 	/*
1597 	 * Search supported input audio formats with pin index 0 to match rate, channels and
1598 	 * sample_valid_bits from reference params
1599 	 */
1600 	for (i = 0; i < pin_fmts_size; i++) {
1601 		struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt;
1602 
1603 		if (pin_fmts[i].pin_index)
1604 			continue;
1605 
1606 		rate = fmt->sampling_frequency;
1607 		channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1608 		valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1609 		type = sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg);
1610 		if (params_rate(params) == rate && params_channels(params) == channels &&
1611 		    sample_valid_bits == valid_bits && sample_type == type)
1612 			break;
1613 	}
1614 
1615 	if (i == pin_fmts_size) {
1616 		dev_err(sdev->dev,
1617 			"%s: Unsupported audio format: %uHz, %ubit, %u channels, type: %d\n",
1618 			__func__, params_rate(params), sample_valid_bits,
1619 			params_channels(params), sample_type);
1620 		return -EINVAL;
1621 	}
1622 
1623 in_fmt:
1624 	/* copy input format */
1625 	memcpy(&base_config->audio_fmt, &pin_fmts[i].audio_fmt,
1626 	       sizeof(struct sof_ipc4_audio_format));
1627 
1628 	/* set base_cfg ibs/obs */
1629 	base_config->ibs = pin_fmts[i].buffer_size;
1630 
1631 	return i;
1632 }
1633 
sof_ipc4_unprepare_copier_module(struct snd_sof_widget * swidget)1634 static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
1635 {
1636 	struct sof_ipc4_copier *ipc4_copier = NULL;
1637 	struct snd_sof_widget *pipe_widget;
1638 	struct sof_ipc4_pipeline *pipeline;
1639 
1640 	/* reset pipeline memory usage */
1641 	pipe_widget = swidget->spipe->pipe_widget;
1642 	pipeline = pipe_widget->private;
1643 	pipeline->mem_usage = 0;
1644 
1645 	if (WIDGET_IS_AIF(swidget->id) || swidget->id == snd_soc_dapm_buffer) {
1646 		if (pipeline->use_chain_dma) {
1647 			pipeline->msg.primary = 0;
1648 			pipeline->msg.extension = 0;
1649 		}
1650 		ipc4_copier = swidget->private;
1651 	} else if (WIDGET_IS_DAI(swidget->id)) {
1652 		struct snd_sof_dai *dai = swidget->private;
1653 
1654 		ipc4_copier = dai->private;
1655 
1656 		if (pipeline->use_chain_dma) {
1657 			/*
1658 			 * Preserve the DMA Link ID and clear other bits since
1659 			 * the DMA Link ID is only configured once during
1660 			 * dai_config, other fields are expected to be 0 for
1661 			 * re-configuration
1662 			 */
1663 			pipeline->msg.primary &= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK;
1664 			pipeline->msg.extension = 0;
1665 		}
1666 
1667 		if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
1668 			struct sof_ipc4_alh_configuration_blob *blob;
1669 			unsigned int group_id;
1670 
1671 			blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
1672 			if (blob->alh_cfg.device_count > 1) {
1673 				group_id = SOF_IPC4_NODE_INDEX(ipc4_copier->data.gtw_cfg.node_id) -
1674 					   ALH_MULTI_GTW_BASE;
1675 				ida_free(&alh_group_ida, group_id);
1676 			}
1677 		}
1678 	}
1679 
1680 	if (ipc4_copier) {
1681 		kfree(ipc4_copier->ipc_config_data);
1682 		ipc4_copier->ipc_config_data = NULL;
1683 		ipc4_copier->ipc_config_size = 0;
1684 	}
1685 }
1686 
1687 #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
snd_sof_get_hw_config_params(struct snd_sof_dev * sdev,struct snd_sof_dai * dai,int * sample_rate,int * channel_count,int * bit_depth)1688 static int snd_sof_get_hw_config_params(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1689 					int *sample_rate, int *channel_count, int *bit_depth)
1690 {
1691 	struct snd_soc_tplg_hw_config *hw_config;
1692 	struct snd_sof_dai_link *slink;
1693 	bool dai_link_found = false;
1694 	bool hw_cfg_found = false;
1695 	int i;
1696 
1697 	/* get current hw_config from link */
1698 	list_for_each_entry(slink, &sdev->dai_link_list, list) {
1699 		if (!strcmp(slink->link->name, dai->name)) {
1700 			dai_link_found = true;
1701 			break;
1702 		}
1703 	}
1704 
1705 	if (!dai_link_found) {
1706 		dev_err(sdev->dev, "%s: no DAI link found for DAI %s\n", __func__, dai->name);
1707 		return -EINVAL;
1708 	}
1709 
1710 	for (i = 0; i < slink->num_hw_configs; i++) {
1711 		hw_config = &slink->hw_configs[i];
1712 		if (dai->current_config == le32_to_cpu(hw_config->id)) {
1713 			hw_cfg_found = true;
1714 			break;
1715 		}
1716 	}
1717 
1718 	if (!hw_cfg_found) {
1719 		dev_err(sdev->dev, "%s: no matching hw_config found for DAI %s\n", __func__,
1720 			dai->name);
1721 		return -EINVAL;
1722 	}
1723 
1724 	*bit_depth = le32_to_cpu(hw_config->tdm_slot_width);
1725 	*channel_count = le32_to_cpu(hw_config->tdm_slots);
1726 	*sample_rate = le32_to_cpu(hw_config->fsync_rate);
1727 
1728 	dev_dbg(sdev->dev, "sample rate: %d sample width: %d channels: %d\n",
1729 		*sample_rate, *bit_depth, *channel_count);
1730 
1731 	return 0;
1732 }
1733 
1734 static int
snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev * sdev,struct snd_sof_dai * dai,bool single_bitdepth,struct snd_pcm_hw_params * params,u32 dai_index,u32 linktype,u8 dir,u32 ** dst,u32 * len)1735 snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1736 			       bool single_bitdepth,
1737 			       struct snd_pcm_hw_params *params, u32 dai_index,
1738 			       u32 linktype, u8 dir, u32 **dst, u32 *len)
1739 {
1740 	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
1741 	struct nhlt_specific_cfg *cfg;
1742 	int sample_rate, channel_count;
1743 	bool format_change = false;
1744 	int bit_depth, ret;
1745 	u32 nhlt_type;
1746 	int dev_type = 0;
1747 
1748 	/* convert to NHLT type */
1749 	switch (linktype) {
1750 	case SOF_DAI_INTEL_DMIC:
1751 		nhlt_type = NHLT_LINK_DMIC;
1752 		channel_count = params_channels(params);
1753 		sample_rate = params_rate(params);
1754 		bit_depth = params_width(params);
1755 		/*
1756 		 * Look for 32-bit blob first instead of 16-bit if copier
1757 		 * supports multiple formats
1758 		 */
1759 		if (bit_depth == 16 && !single_bitdepth) {
1760 			dev_dbg(sdev->dev, "Looking for 32-bit blob first for DMIC\n");
1761 			format_change = true;
1762 			bit_depth = 32;
1763 		}
1764 		break;
1765 	case SOF_DAI_INTEL_SSP:
1766 		nhlt_type = NHLT_LINK_SSP;
1767 		ret = snd_sof_get_hw_config_params(sdev, dai, &sample_rate, &channel_count,
1768 						   &bit_depth);
1769 		if (ret < 0)
1770 			return ret;
1771 
1772 		/*
1773 		 * We need to know the type of the external device attached to a SSP
1774 		 * port to retrieve the blob from NHLT. However, device type is not
1775 		 * specified in topology.
1776 		 * Query the type for the port and then pass that information back
1777 		 * to the blob lookup function.
1778 		 */
1779 		dev_type = intel_nhlt_ssp_device_type(sdev->dev, ipc4_data->nhlt,
1780 						      dai_index);
1781 		if (dev_type < 0)
1782 			return dev_type;
1783 		break;
1784 	default:
1785 		return 0;
1786 	}
1787 
1788 	dev_dbg(sdev->dev, "dai index %d nhlt type %d direction %d dev type %d\n",
1789 		dai_index, nhlt_type, dir, dev_type);
1790 
1791 	/* find NHLT blob with matching params */
1792 	cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, dai_index, nhlt_type,
1793 					   bit_depth, bit_depth, channel_count, sample_rate,
1794 					   dir, dev_type);
1795 
1796 	if (!cfg) {
1797 		bool get_new_blob = false;
1798 
1799 		if (format_change) {
1800 			/*
1801 			 * The 32-bit blob was not found in NHLT table, try to
1802 			 * look for one based on the params
1803 			 */
1804 			bit_depth = params_width(params);
1805 			format_change = false;
1806 			get_new_blob = true;
1807 		} else if (linktype == SOF_DAI_INTEL_DMIC && !single_bitdepth) {
1808 			/*
1809 			 * The requested 32-bit blob (no format change for the
1810 			 * blob request) was not found in NHLT table, try to
1811 			 * look for 16-bit blob if the copier supports multiple
1812 			 * formats
1813 			 */
1814 			bit_depth = 16;
1815 			format_change = true;
1816 			get_new_blob = true;
1817 		}
1818 
1819 		if (get_new_blob) {
1820 			cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt,
1821 							   dai_index, nhlt_type,
1822 							   bit_depth, bit_depth,
1823 							   channel_count, sample_rate,
1824 							   dir, dev_type);
1825 			if (cfg)
1826 				goto out;
1827 		}
1828 
1829 		dev_err(sdev->dev,
1830 			"no matching blob for sample rate: %d sample width: %d channels: %d\n",
1831 			sample_rate, bit_depth, channel_count);
1832 		return -EINVAL;
1833 	}
1834 
1835 out:
1836 	/* config length should be in dwords */
1837 	*len = cfg->size >> 2;
1838 	*dst = (u32 *)cfg->caps;
1839 
1840 	if (format_change) {
1841 		/*
1842 		 * Update the params to reflect that different blob was loaded
1843 		 * instead of the requested bit depth (16 -> 32 or 32 -> 16).
1844 		 * This information is going to be used by the caller to find
1845 		 * matching copier format on the dai side.
1846 		 */
1847 		struct snd_mask *m;
1848 
1849 		m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1850 		snd_mask_none(m);
1851 		if (bit_depth == 16)
1852 			snd_mask_set_format(m, SNDRV_PCM_FORMAT_S16_LE);
1853 		else
1854 			snd_mask_set_format(m, SNDRV_PCM_FORMAT_S32_LE);
1855 
1856 	}
1857 
1858 	return 0;
1859 }
1860 #else
1861 static int
snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev * sdev,struct snd_sof_dai * dai,bool single_bitdepth,struct snd_pcm_hw_params * params,u32 dai_index,u32 linktype,u8 dir,u32 ** dst,u32 * len)1862 snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1863 			       bool single_bitdepth,
1864 			       struct snd_pcm_hw_params *params, u32 dai_index,
1865 			       u32 linktype, u8 dir, u32 **dst, u32 *len)
1866 {
1867 	return 0;
1868 }
1869 #endif
1870 
sof_ipc4_copier_is_single_bitdepth(struct snd_sof_dev * sdev,struct sof_ipc4_pin_format * pin_fmts,u32 pin_fmts_size)1871 bool sof_ipc4_copier_is_single_bitdepth(struct snd_sof_dev *sdev,
1872 					struct sof_ipc4_pin_format *pin_fmts,
1873 					u32 pin_fmts_size)
1874 {
1875 	struct sof_ipc4_audio_format *fmt;
1876 	u32 valid_bits;
1877 	int i;
1878 
1879 	fmt = &pin_fmts[0].audio_fmt;
1880 	valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1881 
1882 	/* check if all formats in topology are the same */
1883 	for (i = 1; i < pin_fmts_size; i++) {
1884 		u32 _valid_bits;
1885 
1886 		fmt = &pin_fmts[i].audio_fmt;
1887 		_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1888 
1889 		if (_valid_bits != valid_bits)
1890 			return false;
1891 	}
1892 
1893 	return true;
1894 }
1895 
1896 static int
sof_ipc4_adjust_params_to_dai_format(struct snd_sof_dev * sdev,struct snd_pcm_hw_params * params,struct sof_ipc4_pin_format * pin_fmts,u32 pin_fmts_size)1897 sof_ipc4_adjust_params_to_dai_format(struct snd_sof_dev *sdev,
1898 				     struct snd_pcm_hw_params *params,
1899 				     struct sof_ipc4_pin_format *pin_fmts,
1900 				     u32 pin_fmts_size)
1901 {
1902 	u32 params_mask = BIT(SNDRV_PCM_HW_PARAM_RATE) |
1903 			  BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
1904 			  BIT(SNDRV_PCM_HW_PARAM_FORMAT);
1905 	struct sof_ipc4_audio_format *fmt;
1906 	u32 rate, channels, valid_bits;
1907 	int i;
1908 
1909 	fmt = &pin_fmts[0].audio_fmt;
1910 	rate = fmt->sampling_frequency;
1911 	channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1912 	valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1913 
1914 	/* check if parameters in topology defined formats are the same */
1915 	for (i = 1; i < pin_fmts_size; i++) {
1916 		u32 val;
1917 
1918 		fmt = &pin_fmts[i].audio_fmt;
1919 
1920 		if (params_mask & BIT(SNDRV_PCM_HW_PARAM_RATE)) {
1921 			val = fmt->sampling_frequency;
1922 			if (val != rate)
1923 				params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_RATE);
1924 		}
1925 		if (params_mask & BIT(SNDRV_PCM_HW_PARAM_CHANNELS)) {
1926 			val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
1927 			if (val != channels)
1928 				params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_CHANNELS);
1929 		}
1930 		if (params_mask & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) {
1931 			val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);
1932 			if (val != valid_bits)
1933 				params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_FORMAT);
1934 		}
1935 	}
1936 
1937 	if (params_mask)
1938 		return sof_ipc4_update_hw_params(sdev, params,
1939 						 &pin_fmts[0].audio_fmt,
1940 						 params_mask);
1941 
1942 	return 0;
1943 }
1944 
1945 static int
sof_ipc4_prepare_dai_copier(struct snd_sof_dev * sdev,struct snd_sof_dai * dai,struct snd_pcm_hw_params * params,int dir)1946 sof_ipc4_prepare_dai_copier(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1947 			    struct snd_pcm_hw_params *params, int dir)
1948 {
1949 	struct sof_ipc4_available_audio_format *available_fmt;
1950 	struct snd_pcm_hw_params dai_params = *params;
1951 	struct sof_ipc4_copier_data *copier_data;
1952 	struct sof_ipc4_pin_format *pin_fmts;
1953 	struct sof_ipc4_copier *ipc4_copier;
1954 	bool single_bitdepth;
1955 	u32 num_pin_fmts;
1956 	int ret;
1957 
1958 	ipc4_copier = dai->private;
1959 	copier_data = &ipc4_copier->data;
1960 	available_fmt = &ipc4_copier->available_fmt;
1961 
1962 	/*
1963 	 * Fixup the params based on the format parameters of the DAI. If any
1964 	 * of the RATE, CHANNELS, bit depth is static among the formats then
1965 	 * narrow the params to only allow that specific parameter value.
1966 	 */
1967 	if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
1968 		pin_fmts = available_fmt->output_pin_fmts;
1969 		num_pin_fmts = available_fmt->num_output_formats;
1970 	} else {
1971 		pin_fmts = available_fmt->input_pin_fmts;
1972 		num_pin_fmts = available_fmt->num_input_formats;
1973 	}
1974 
1975 	ret = sof_ipc4_adjust_params_to_dai_format(sdev, &dai_params, pin_fmts,
1976 						   num_pin_fmts);
1977 	if (ret)
1978 		return ret;
1979 
1980 	single_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev, pin_fmts,
1981 							     num_pin_fmts);
1982 	ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, single_bitdepth,
1983 					     &dai_params,
1984 					     ipc4_copier->dai_index,
1985 					     ipc4_copier->dai_type, dir,
1986 					     &ipc4_copier->copier_config,
1987 					     &copier_data->gtw_cfg.config_length);
1988 	/* Update the params to reflect the changes made in this function */
1989 	if (!ret)
1990 		*params = dai_params;
1991 
1992 	return ret;
1993 }
1994 
1995 static int
sof_ipc4_prepare_copier_module(struct snd_sof_widget * swidget,struct snd_pcm_hw_params * fe_params,struct snd_sof_platform_stream_params * platform_params,struct snd_pcm_hw_params * pipeline_params,int dir)1996 sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
1997 			       struct snd_pcm_hw_params *fe_params,
1998 			       struct snd_sof_platform_stream_params *platform_params,
1999 			       struct snd_pcm_hw_params *pipeline_params, int dir)
2000 {
2001 	struct sof_ipc4_available_audio_format *available_fmt;
2002 	struct snd_soc_component *scomp = swidget->scomp;
2003 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2004 	struct sof_ipc4_copier_data *copier_data;
2005 	int input_fmt_index, output_fmt_index;
2006 	struct sof_ipc4_copier *ipc4_copier;
2007 	struct snd_pcm_hw_params *ref_params __free(kfree) = NULL;
2008 	struct snd_sof_dai *dai;
2009 	u32 gtw_cfg_config_length;
2010 	u32 dma_config_tlv_size = 0;
2011 	void **ipc_config_data;
2012 	int *ipc_config_size;
2013 	u32 **data;
2014 	int ipc_size, ret, out_ref_valid_bits;
2015 	u32 out_ref_rate, out_ref_channels, out_ref_type;
2016 	u32 deep_buffer_dma_ms = 0;
2017 	bool single_output_bitdepth;
2018 	int i;
2019 
2020 	switch (swidget->id) {
2021 	case snd_soc_dapm_aif_in:
2022 	case snd_soc_dapm_aif_out:
2023 	{
2024 		struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
2025 		struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
2026 		struct sof_ipc4_gtw_attributes *gtw_attr;
2027 
2028 		dev_dbg(sdev->dev,
2029 			"Host copier %s, type %d, ChainDMA: %s, stream_tag: %d\n",
2030 			swidget->widget->name, swidget->id,
2031 			str_yes_no(pipeline->use_chain_dma),
2032 			platform_params->stream_tag);
2033 
2034 		/* parse the deep buffer dma size */
2035 		ret = sof_update_ipc_object(scomp, &deep_buffer_dma_ms,
2036 					    SOF_COPIER_DEEP_BUFFER_TOKENS, swidget->tuples,
2037 					    swidget->num_tuples, sizeof(u32), 1);
2038 		if (ret) {
2039 			dev_err(scomp->dev, "Failed to parse deep buffer dma size for %s\n",
2040 				swidget->widget->name);
2041 			return ret;
2042 		}
2043 
2044 		ipc4_copier = (struct sof_ipc4_copier *)swidget->private;
2045 		gtw_attr = ipc4_copier->gtw_attr;
2046 		copier_data = &ipc4_copier->data;
2047 		available_fmt = &ipc4_copier->available_fmt;
2048 
2049 		if (pipeline->use_chain_dma) {
2050 			u32 host_dma_id;
2051 			u32 fifo_size;
2052 
2053 			host_dma_id = platform_params->stream_tag - 1;
2054 			pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id);
2055 
2056 			if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE)
2057 				pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
2058 
2059 			/* Set SCS bit for 8 and 16 bit formats */
2060 			if (params_physical_width(fe_params) <= 16)
2061 				pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK;
2062 
2063 			/*
2064 			 * Despite its name the bitfield 'fifo_size' is used to define DMA buffer
2065 			 * size. The expression calculates 2ms buffer size.
2066 			 */
2067 			fifo_size = DIV_ROUND_UP((SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS *
2068 						  params_rate(fe_params) *
2069 						  params_channels(fe_params) *
2070 						  params_physical_width(fe_params)), 8000);
2071 			pipeline->msg.extension |= SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(fifo_size);
2072 
2073 			/*
2074 			 * Chain DMA does not support stream timestamping, but it
2075 			 * can use the host side registers for delay calculation.
2076 			 */
2077 			copier_data->gtw_cfg.node_id = SOF_IPC4_CHAIN_DMA_NODE_ID;
2078 
2079 			return 0;
2080 		}
2081 
2082 		/*
2083 		 * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts
2084 		 * for capture.
2085 		 */
2086 		if (dir == SNDRV_PCM_STREAM_PLAYBACK)
2087 			ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL);
2088 		else
2089 			ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL);
2090 		if (!ref_params)
2091 			return -ENOMEM;
2092 
2093 		copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
2094 		copier_data->gtw_cfg.node_id |=
2095 			SOF_IPC4_NODE_INDEX(platform_params->stream_tag - 1);
2096 
2097 		/* set gateway attributes */
2098 		gtw_attr->lp_buffer_alloc = pipeline->lp_mode;
2099 		break;
2100 	}
2101 	case snd_soc_dapm_dai_in:
2102 	case snd_soc_dapm_dai_out:
2103 	{
2104 		struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
2105 		struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
2106 
2107 		dev_dbg(sdev->dev, "Dai copier %s, type %d, ChainDMA: %s\n",
2108 			swidget->widget->name, swidget->id,
2109 			str_yes_no(pipeline->use_chain_dma));
2110 
2111 		if (pipeline->use_chain_dma)
2112 			return 0;
2113 
2114 		dai = swidget->private;
2115 
2116 		ipc4_copier = (struct sof_ipc4_copier *)dai->private;
2117 		copier_data = &ipc4_copier->data;
2118 		available_fmt = &ipc4_copier->available_fmt;
2119 
2120 		/*
2121 		 * Use the fe_params as a base for the copier configuration.
2122 		 * The ref_params might get updated to reflect what format is
2123 		 * supported by the copier on the DAI side.
2124 		 *
2125 		 * In case of capture the ref_params returned will be used to
2126 		 * find the input configuration of the copier.
2127 		 */
2128 		ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL);
2129 		if (!ref_params)
2130 			return -ENOMEM;
2131 
2132 		ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir);
2133 		if (ret < 0)
2134 			return ret;
2135 
2136 		/*
2137 		 * For playback the pipeline_params needs to be used to find the
2138 		 * input configuration of the copier.
2139 		 */
2140 		if (dir == SNDRV_PCM_STREAM_PLAYBACK)
2141 			memcpy(ref_params, pipeline_params, sizeof(*ref_params));
2142 
2143 		break;
2144 	}
2145 	case snd_soc_dapm_buffer:
2146 	{
2147 		dev_dbg(sdev->dev, "Module copier %s, type %d\n",
2148 			swidget->widget->name, swidget->id);
2149 
2150 		ipc4_copier = (struct sof_ipc4_copier *)swidget->private;
2151 		copier_data = &ipc4_copier->data;
2152 		available_fmt = &ipc4_copier->available_fmt;
2153 
2154 		ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL);
2155 		if (!ref_params)
2156 			return -ENOMEM;
2157 
2158 		break;
2159 	}
2160 	default:
2161 		dev_err(sdev->dev, "unsupported type %d for copier %s",
2162 			swidget->id, swidget->widget->name);
2163 		return -EINVAL;
2164 	}
2165 
2166 	/* set input and output audio formats */
2167 	input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
2168 							&copier_data->base_config,
2169 							ref_params, available_fmt);
2170 	if (input_fmt_index < 0)
2171 		return input_fmt_index;
2172 
2173 	/* set the reference params for output format selection */
2174 	single_output_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev,
2175 					available_fmt->output_pin_fmts,
2176 					available_fmt->num_output_formats);
2177 	switch (swidget->id) {
2178 	case snd_soc_dapm_aif_in:
2179 	case snd_soc_dapm_dai_out:
2180 	case snd_soc_dapm_buffer:
2181 	{
2182 		struct sof_ipc4_audio_format *in_fmt;
2183 
2184 		in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
2185 		out_ref_rate = in_fmt->sampling_frequency;
2186 		out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2187 		out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
2188 
2189 		if (!single_output_bitdepth)
2190 			out_ref_valid_bits =
2191 				SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2192 		break;
2193 	}
2194 	case snd_soc_dapm_aif_out:
2195 	case snd_soc_dapm_dai_in:
2196 		out_ref_rate = params_rate(fe_params);
2197 		out_ref_channels = params_channels(fe_params);
2198 		ret = sof_ipc4_get_sample_type(sdev, fe_params);
2199 		if (ret < 0)
2200 			return ret;
2201 		out_ref_type = (u32)ret;
2202 
2203 		if (!single_output_bitdepth) {
2204 			out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
2205 			if (out_ref_valid_bits < 0)
2206 				return out_ref_valid_bits;
2207 		}
2208 		break;
2209 	default:
2210 		/*
2211 		 * Unsupported type should be caught by the former switch default
2212 		 * case, this should never happen in reality.
2213 		 */
2214 		return -EINVAL;
2215 	}
2216 
2217 	/*
2218 	 * if the output format is the same across all available output formats, choose
2219 	 * that as the reference.
2220 	 */
2221 	if (single_output_bitdepth) {
2222 		struct sof_ipc4_audio_format *out_fmt;
2223 
2224 		out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;
2225 		out_ref_valid_bits =
2226 			SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg);
2227 		out_ref_type = sof_ipc4_fmt_cfg_to_type(out_fmt->fmt_cfg);
2228 	}
2229 
2230 	output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
2231 							  &copier_data->base_config,
2232 							  available_fmt, out_ref_rate,
2233 							  out_ref_channels, out_ref_valid_bits,
2234 							  out_ref_type);
2235 	if (output_fmt_index < 0)
2236 		return output_fmt_index;
2237 
2238 	/*
2239 	 * Set the output format. Current topology defines pin 0 input and output formats in pairs.
2240 	 * This assumes that the pin 0 formats are defined before all other pins.
2241 	 * So pick the output audio format with the same index as the chosen
2242 	 * input format. This logic will need to be updated when the format definitions
2243 	 * in topology change.
2244 	 */
2245 	memcpy(&copier_data->out_format,
2246 	       &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt,
2247 	       sizeof(struct sof_ipc4_audio_format));
2248 
2249 	switch (swidget->id) {
2250 	case snd_soc_dapm_dai_in:
2251 	case snd_soc_dapm_dai_out:
2252 	{
2253 		/*
2254 		 * Only SOF_DAI_INTEL_ALH needs copier_data to set blob.
2255 		 * That's why only ALH dai's blob is set after sof_ipc4_init_input_audio_fmt
2256 		 */
2257 		if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
2258 			struct sof_ipc4_alh_configuration_blob *blob;
2259 			struct sof_ipc4_dma_config *dma_config;
2260 			struct sof_ipc4_copier_data *alh_data;
2261 			struct sof_ipc4_copier *alh_copier;
2262 			struct snd_sof_widget *w;
2263 			u32 ch_count = 0;
2264 			u32 ch_mask = 0;
2265 			u32 ch_map;
2266 			u32 step;
2267 			u32 mask;
2268 
2269 			blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
2270 
2271 			blob->gw_attr.lp_buffer_alloc = 0;
2272 
2273 			/* Get channel_mask from ch_map */
2274 			ch_map = copier_data->base_config.audio_fmt.ch_map;
2275 			for (i = 0; ch_map; i++) {
2276 				if ((ch_map & 0xf) != 0xf) {
2277 					ch_mask |= BIT(i);
2278 					ch_count++;
2279 				}
2280 				ch_map >>= 4;
2281 			}
2282 
2283 			step = ch_count / blob->alh_cfg.device_count;
2284 			mask =  GENMASK(step - 1, 0);
2285 			/*
2286 			 * Set each gtw_cfg.node_id to blob->alh_cfg.mapping[]
2287 			 * for all widgets with the same stream name
2288 			 */
2289 			i = 0;
2290 			list_for_each_entry(w, &sdev->widget_list, list) {
2291 				u32 node_type;
2292 
2293 				if (!WIDGET_IS_DAI(w->id) || !w->widget->sname ||
2294 				    strcmp(w->widget->sname, swidget->widget->sname))
2295 					continue;
2296 
2297 				dai = w->private;
2298 				if (dai->type != SOF_DAI_INTEL_ALH)
2299 					continue;
2300 				alh_copier = (struct sof_ipc4_copier *)dai->private;
2301 				alh_data = &alh_copier->data;
2302 				node_type = SOF_IPC4_GET_NODE_TYPE(alh_data->gtw_cfg.node_id);
2303 				blob->alh_cfg.mapping[i].device = SOF_IPC4_NODE_TYPE(node_type);
2304 				blob->alh_cfg.mapping[i].device |=
2305 					SOF_IPC4_NODE_INDEX(alh_copier->dai_index);
2306 
2307 				/*
2308 				 * The mapping[i] device in ALH blob should be the same as the
2309 				 * dma_config_tlv[i] mapping device if a dma_config_tlv is present.
2310 				 * The device id will be used for DMA tlv mapping purposes.
2311 				 */
2312 				if (ipc4_copier->dma_config_tlv[i].length) {
2313 					dma_config = &ipc4_copier->dma_config_tlv[i].dma_config;
2314 					blob->alh_cfg.mapping[i].device =
2315 						dma_config->dma_stream_channel_map.mapping[0].device;
2316 				}
2317 
2318 				/*
2319 				 * Set the same channel mask for playback as the audio data is
2320 				 * duplicated for all speakers. For capture, split the channels
2321 				 * among the aggregated DAIs. For example, with 4 channels on 2
2322 				 * aggregated DAIs, the channel_mask should be 0x3 and 0xc for the
2323 				 * two DAI's.
2324 				 * The channel masks used depend on the cpu_dais used in the
2325 				 * dailink at the machine driver level, which actually comes from
2326 				 * the tables in soc_acpi files depending on the _ADR and devID
2327 				 * registers for each codec.
2328 				 */
2329 				if (w->id == snd_soc_dapm_dai_in)
2330 					blob->alh_cfg.mapping[i].channel_mask = ch_mask;
2331 				else
2332 					blob->alh_cfg.mapping[i].channel_mask = mask << (step * i);
2333 
2334 				i++;
2335 			}
2336 			if (blob->alh_cfg.device_count > 1) {
2337 				int group_id;
2338 
2339 				group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1,
2340 							 GFP_KERNEL);
2341 
2342 				if (group_id < 0)
2343 					return group_id;
2344 
2345 				/* add multi-gateway base */
2346 				group_id += ALH_MULTI_GTW_BASE;
2347 				copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
2348 				copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(group_id);
2349 			}
2350 		}
2351 	}
2352 	}
2353 
2354 	/* modify the input params for the next widget */
2355 	ret = sof_ipc4_update_hw_params(sdev, pipeline_params,
2356 					&copier_data->out_format,
2357 					BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
2358 					BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
2359 					BIT(SNDRV_PCM_HW_PARAM_RATE));
2360 	if (ret)
2361 		return ret;
2362 
2363 	/*
2364 	 * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the
2365 	 * deep buffer case, set the dma_buffer_size depending on the deep_buffer_dma_ms set
2366 	 * in topology.
2367 	 */
2368 	switch (swidget->id) {
2369 	case snd_soc_dapm_dai_in:
2370 		copier_data->gtw_cfg.dma_buffer_size =
2371 			SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.ibs;
2372 		break;
2373 	case snd_soc_dapm_aif_in:
2374 		copier_data->gtw_cfg.dma_buffer_size =
2375 			max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) *
2376 				copier_data->base_config.ibs;
2377 		dev_dbg(sdev->dev, "copier %s, dma buffer%s: %u ms (%u bytes)",
2378 			swidget->widget->name,
2379 			deep_buffer_dma_ms ? " (using Deep Buffer)" : "",
2380 			max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms),
2381 			copier_data->gtw_cfg.dma_buffer_size);
2382 		break;
2383 	case snd_soc_dapm_dai_out:
2384 	case snd_soc_dapm_aif_out:
2385 		copier_data->gtw_cfg.dma_buffer_size =
2386 			SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs;
2387 		break;
2388 	default:
2389 		break;
2390 	}
2391 
2392 	data = &ipc4_copier->copier_config;
2393 	ipc_config_size = &ipc4_copier->ipc_config_size;
2394 	ipc_config_data = &ipc4_copier->ipc_config_data;
2395 
2396 	/* config_length is DWORD based */
2397 	gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4;
2398 	ipc_size = sizeof(*copier_data) + gtw_cfg_config_length;
2399 
2400 	dma_config_tlv_size = 0;
2401 	for (i = 0; i < SOF_IPC4_DMA_DEVICE_MAX_COUNT; i++) {
2402 		if (ipc4_copier->dma_config_tlv[i].type != SOF_IPC4_GTW_DMA_CONFIG_ID)
2403 			continue;
2404 		dma_config_tlv_size += ipc4_copier->dma_config_tlv[i].length;
2405 		dma_config_tlv_size +=
2406 			ipc4_copier->dma_config_tlv[i].dma_config.dma_priv_config_size;
2407 		dma_config_tlv_size += (sizeof(ipc4_copier->dma_config_tlv[i]) -
2408 			sizeof(ipc4_copier->dma_config_tlv[i].dma_config));
2409 	}
2410 
2411 	if (dma_config_tlv_size) {
2412 		ipc_size += dma_config_tlv_size;
2413 
2414 		/* we also need to increase the size at the gtw level */
2415 		copier_data->gtw_cfg.config_length += dma_config_tlv_size / 4;
2416 	}
2417 
2418 	dev_dbg(sdev->dev, "copier %s, IPC size is %d", swidget->widget->name, ipc_size);
2419 
2420 	*ipc_config_data = kzalloc(ipc_size, GFP_KERNEL);
2421 	if (!*ipc_config_data)
2422 		return -ENOMEM;
2423 
2424 	*ipc_config_size = ipc_size;
2425 
2426 	sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
2427 					 input_fmt_index, output_fmt_index);
2428 
2429 	/* update pipeline memory usage */
2430 	sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
2431 
2432 	/* copy IPC data */
2433 	memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data));
2434 	if (gtw_cfg_config_length)
2435 		memcpy(*ipc_config_data + sizeof(*copier_data),
2436 		       *data, gtw_cfg_config_length);
2437 
2438 	/* add DMA Config TLV, if configured */
2439 	if (dma_config_tlv_size)
2440 		memcpy(*ipc_config_data + sizeof(*copier_data) +
2441 		       gtw_cfg_config_length,
2442 		       &ipc4_copier->dma_config_tlv, dma_config_tlv_size);
2443 
2444 	/*
2445 	 * Restore gateway config length now that IPC payload is prepared. This avoids
2446 	 * counting the DMA CONFIG TLV multiple times
2447 	 */
2448 	copier_data->gtw_cfg.config_length = gtw_cfg_config_length / 4;
2449 
2450 	return 0;
2451 }
2452 
sof_ipc4_prepare_gain_module(struct snd_sof_widget * swidget,struct snd_pcm_hw_params * fe_params,struct snd_sof_platform_stream_params * platform_params,struct snd_pcm_hw_params * pipeline_params,int dir)2453 static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
2454 					struct snd_pcm_hw_params *fe_params,
2455 					struct snd_sof_platform_stream_params *platform_params,
2456 					struct snd_pcm_hw_params *pipeline_params, int dir)
2457 {
2458 	struct snd_soc_component *scomp = swidget->scomp;
2459 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2460 	struct sof_ipc4_gain *gain = swidget->private;
2461 	struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt;
2462 	struct sof_ipc4_audio_format *in_fmt;
2463 	u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
2464 	int input_fmt_index, output_fmt_index;
2465 
2466 	input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
2467 							&gain->data.base_config,
2468 							pipeline_params,
2469 							available_fmt);
2470 	if (input_fmt_index < 0)
2471 		return input_fmt_index;
2472 
2473 	in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
2474 	out_ref_rate = in_fmt->sampling_frequency;
2475 	out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2476 	out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2477 	out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
2478 
2479 	output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
2480 							  &gain->data.base_config,
2481 							  available_fmt,
2482 							  out_ref_rate,
2483 							  out_ref_channels,
2484 							  out_ref_valid_bits,
2485 							  out_ref_type);
2486 	if (output_fmt_index < 0)
2487 		return output_fmt_index;
2488 
2489 	sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
2490 					 input_fmt_index, output_fmt_index);
2491 
2492 	/* update pipeline memory usage */
2493 	sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config);
2494 
2495 	return 0;
2496 }
2497 
sof_ipc4_prepare_mixer_module(struct snd_sof_widget * swidget,struct snd_pcm_hw_params * fe_params,struct snd_sof_platform_stream_params * platform_params,struct snd_pcm_hw_params * pipeline_params,int dir)2498 static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
2499 					 struct snd_pcm_hw_params *fe_params,
2500 					 struct snd_sof_platform_stream_params *platform_params,
2501 					 struct snd_pcm_hw_params *pipeline_params, int dir)
2502 {
2503 	struct snd_soc_component *scomp = swidget->scomp;
2504 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2505 	struct sof_ipc4_mixer *mixer = swidget->private;
2506 	struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt;
2507 	struct sof_ipc4_audio_format *in_fmt;
2508 	u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
2509 	int input_fmt_index, output_fmt_index;
2510 
2511 	input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
2512 							&mixer->base_config,
2513 							pipeline_params,
2514 							available_fmt);
2515 	if (input_fmt_index < 0)
2516 		return input_fmt_index;
2517 
2518 	in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
2519 	out_ref_rate = in_fmt->sampling_frequency;
2520 	out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2521 	out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2522 	out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
2523 
2524 	output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
2525 							  &mixer->base_config,
2526 							  available_fmt,
2527 							  out_ref_rate,
2528 							  out_ref_channels,
2529 							  out_ref_valid_bits,
2530 							  out_ref_type);
2531 	if (output_fmt_index < 0)
2532 		return output_fmt_index;
2533 
2534 	sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
2535 					 input_fmt_index, output_fmt_index);
2536 
2537 	/* update pipeline memory usage */
2538 	sof_ipc4_update_resource_usage(sdev, swidget, &mixer->base_config);
2539 
2540 	return 0;
2541 }
2542 
sof_ipc4_prepare_src_module(struct snd_sof_widget * swidget,struct snd_pcm_hw_params * fe_params,struct snd_sof_platform_stream_params * platform_params,struct snd_pcm_hw_params * pipeline_params,int dir)2543 static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
2544 				       struct snd_pcm_hw_params *fe_params,
2545 				       struct snd_sof_platform_stream_params *platform_params,
2546 				       struct snd_pcm_hw_params *pipeline_params, int dir)
2547 {
2548 	struct snd_soc_component *scomp = swidget->scomp;
2549 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2550 	struct sof_ipc4_src *src = swidget->private;
2551 	struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt;
2552 	struct sof_ipc4_audio_format *out_audio_fmt;
2553 	struct sof_ipc4_audio_format *in_audio_fmt;
2554 	u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
2555 	int output_fmt_index, input_fmt_index;
2556 
2557 	input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
2558 							&src->data.base_config,
2559 							pipeline_params,
2560 							available_fmt);
2561 	if (input_fmt_index < 0)
2562 		return input_fmt_index;
2563 
2564 	/*
2565 	 * For playback, the SRC sink rate will be configured based on the requested output
2566 	 * format, which is restricted to only deal with DAI's with a single format for now.
2567 	 */
2568 	if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) {
2569 		dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n",
2570 			available_fmt->num_output_formats, swidget->widget->name);
2571 		return -EINVAL;
2572 	}
2573 
2574 	/*
2575 	 * SRC does not perform format conversion, so the output channels and valid bit depth must
2576 	 * be the same as that of the input.
2577 	 */
2578 	in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
2579 	out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg);
2580 	out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
2581 	out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg);
2582 
2583 	/*
2584 	 * For capture, the SRC module should convert the rate to match the rate requested by the
2585 	 * PCM hw_params. Set the reference params based on the fe_params unconditionally as it
2586 	 * will be ignored for playback anyway.
2587 	 */
2588 	out_ref_rate = params_rate(fe_params);
2589 
2590 	output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
2591 							  &src->data.base_config,
2592 							  available_fmt,
2593 							  out_ref_rate,
2594 							  out_ref_channels,
2595 							  out_ref_valid_bits,
2596 							  out_ref_type);
2597 	if (output_fmt_index < 0)
2598 		return output_fmt_index;
2599 
2600 	sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
2601 					 input_fmt_index, output_fmt_index);
2602 
2603 	/* update pipeline memory usage */
2604 	sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config);
2605 
2606 	out_audio_fmt = &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt;
2607 	src->data.sink_rate = out_audio_fmt->sampling_frequency;
2608 
2609 	/* update pipeline_params for sink widgets */
2610 	return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt,
2611 					 BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
2612 					 BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
2613 					 BIT(SNDRV_PCM_HW_PARAM_RATE));
2614 }
2615 
2616 static int
sof_ipc4_process_set_pin_formats(struct snd_sof_widget * swidget,int pin_type)2617 sof_ipc4_process_set_pin_formats(struct snd_sof_widget *swidget, int pin_type)
2618 {
2619 	struct sof_ipc4_process *process = swidget->private;
2620 	struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext;
2621 	struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt;
2622 	struct sof_ipc4_pin_format *pin_format, *format_list_to_search;
2623 	struct snd_soc_component *scomp = swidget->scomp;
2624 	int num_pins, format_list_count;
2625 	int pin_format_offset = 0;
2626 	int i, j;
2627 
2628 	/* set number of pins, offset of pin format and format list to search based on pin type */
2629 	if (pin_type == SOF_PIN_TYPE_INPUT) {
2630 		num_pins = swidget->num_input_pins;
2631 		format_list_to_search = available_fmt->input_pin_fmts;
2632 		format_list_count = available_fmt->num_input_formats;
2633 	} else {
2634 		num_pins = swidget->num_output_pins;
2635 		pin_format_offset = swidget->num_input_pins;
2636 		format_list_to_search = available_fmt->output_pin_fmts;
2637 		format_list_count = available_fmt->num_output_formats;
2638 	}
2639 
2640 	for (i = pin_format_offset; i < num_pins + pin_format_offset; i++) {
2641 		pin_format = &base_cfg_ext->pin_formats[i];
2642 
2643 		/* Pin 0 audio formats are derived from the base config input/output format */
2644 		if (i == pin_format_offset) {
2645 			if (pin_type == SOF_PIN_TYPE_INPUT) {
2646 				pin_format->buffer_size = process->base_config.ibs;
2647 				pin_format->audio_fmt = process->base_config.audio_fmt;
2648 			} else {
2649 				pin_format->buffer_size = process->base_config.obs;
2650 				pin_format->audio_fmt = process->output_format;
2651 			}
2652 			continue;
2653 		}
2654 
2655 		/*
2656 		 * For all other pins, find the pin formats from those set in topology. If there
2657 		 * is more than one format specified for a pin, this will pick the first available
2658 		 * one.
2659 		 */
2660 		for (j = 0; j < format_list_count; j++) {
2661 			struct sof_ipc4_pin_format *pin_format_item = &format_list_to_search[j];
2662 
2663 			if (pin_format_item->pin_index == i - pin_format_offset) {
2664 				*pin_format = *pin_format_item;
2665 				break;
2666 			}
2667 		}
2668 
2669 		if (j == format_list_count) {
2670 			dev_err(scomp->dev, "%s pin %d format not found for %s\n",
2671 				(pin_type == SOF_PIN_TYPE_INPUT) ? "input" : "output",
2672 				i - pin_format_offset, swidget->widget->name);
2673 			return -EINVAL;
2674 		}
2675 	}
2676 
2677 	return 0;
2678 }
2679 
sof_ipc4_process_add_base_cfg_extn(struct snd_sof_widget * swidget)2680 static int sof_ipc4_process_add_base_cfg_extn(struct snd_sof_widget *swidget)
2681 {
2682 	int ret, i;
2683 
2684 	/* copy input and output pin formats */
2685 	for (i = 0; i <= SOF_PIN_TYPE_OUTPUT; i++) {
2686 		ret = sof_ipc4_process_set_pin_formats(swidget, i);
2687 		if (ret < 0)
2688 			return ret;
2689 	}
2690 
2691 	return 0;
2692 }
2693 
sof_ipc4_prepare_process_module(struct snd_sof_widget * swidget,struct snd_pcm_hw_params * fe_params,struct snd_sof_platform_stream_params * platform_params,struct snd_pcm_hw_params * pipeline_params,int dir)2694 static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
2695 					   struct snd_pcm_hw_params *fe_params,
2696 					   struct snd_sof_platform_stream_params *platform_params,
2697 					   struct snd_pcm_hw_params *pipeline_params, int dir)
2698 {
2699 	struct snd_soc_component *scomp = swidget->scomp;
2700 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2701 	struct sof_ipc4_process *process = swidget->private;
2702 	struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt;
2703 	void *cfg = process->ipc_config_data;
2704 	int output_fmt_index = 0;
2705 	int input_fmt_index = 0;
2706 	int ret;
2707 
2708 	input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
2709 							&process->base_config,
2710 							pipeline_params,
2711 							available_fmt);
2712 	if (input_fmt_index < 0)
2713 		return input_fmt_index;
2714 
2715 	/* Configure output audio format only if the module supports output */
2716 	if (available_fmt->num_output_formats) {
2717 		struct sof_ipc4_audio_format *in_fmt;
2718 		struct sof_ipc4_pin_format *pin_fmt;
2719 		u32 out_ref_rate, out_ref_channels;
2720 		int out_ref_valid_bits, out_ref_type;
2721 
2722 		in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
2723 
2724 		out_ref_rate = in_fmt->sampling_frequency;
2725 		out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
2726 		out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
2727 		out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
2728 
2729 		output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
2730 								  &process->base_config,
2731 								  available_fmt,
2732 								  out_ref_rate,
2733 								  out_ref_channels,
2734 								  out_ref_valid_bits,
2735 								  out_ref_type);
2736 		if (output_fmt_index < 0)
2737 			return output_fmt_index;
2738 
2739 		pin_fmt = &available_fmt->output_pin_fmts[output_fmt_index];
2740 
2741 		/* copy Pin output format for Pin 0 only */
2742 		if (pin_fmt->pin_index == 0) {
2743 			memcpy(&process->output_format, &pin_fmt->audio_fmt,
2744 			       sizeof(struct sof_ipc4_audio_format));
2745 
2746 			/* modify the pipeline params with the output format */
2747 			ret = sof_ipc4_update_hw_params(sdev, pipeline_params,
2748 							&process->output_format,
2749 							BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
2750 							BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
2751 							BIT(SNDRV_PCM_HW_PARAM_RATE));
2752 			if (ret)
2753 				return ret;
2754 		}
2755 	}
2756 
2757 	sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
2758 					 input_fmt_index, output_fmt_index);
2759 
2760 	/* update pipeline memory usage */
2761 	sof_ipc4_update_resource_usage(sdev, swidget, &process->base_config);
2762 
2763 	/* ipc_config_data is composed of the base_config followed by an optional extension */
2764 	memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg));
2765 	cfg += sizeof(struct sof_ipc4_base_module_cfg);
2766 
2767 	if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) {
2768 		struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext;
2769 
2770 		ret = sof_ipc4_process_add_base_cfg_extn(swidget);
2771 		if (ret < 0)
2772 			return ret;
2773 
2774 		memcpy(cfg, base_cfg_ext, process->base_config_ext_size);
2775 	}
2776 
2777 	return 0;
2778 }
2779 
sof_ipc4_control_load_volume(struct snd_sof_dev * sdev,struct snd_sof_control * scontrol)2780 static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
2781 {
2782 	struct sof_ipc4_control_data *control_data;
2783 	struct sof_ipc4_msg *msg;
2784 	int i;
2785 
2786 	scontrol->size = struct_size(control_data, chanv, scontrol->num_channels);
2787 
2788 	/* scontrol->ipc_control_data will be freed in sof_control_unload */
2789 	scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
2790 	if (!scontrol->ipc_control_data)
2791 		return -ENOMEM;
2792 
2793 	control_data = scontrol->ipc_control_data;
2794 	control_data->index = scontrol->index;
2795 
2796 	msg = &control_data->msg;
2797 	msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET);
2798 	msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
2799 	msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
2800 
2801 	/* volume controls with range 0-1 (off/on) are switch controls */
2802 	if (scontrol->max == 1)
2803 		msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_SWITCH_CONTROL_PARAM_ID);
2804 	else
2805 		msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_GAIN_PARAM_ID);
2806 
2807 	for (i = 0; i < scontrol->num_channels; i++) {
2808 		control_data->chanv[i].channel = i;
2809 		/*
2810 		 * Default, initial values:
2811 		 * - 0dB for volume controls
2812 		 * - off (0) for switch controls - value already zero after
2813 		 *				   memory allocation
2814 		 */
2815 		if (scontrol->max > 1)
2816 			control_data->chanv[i].value = SOF_IPC4_VOL_ZERO_DB;
2817 	}
2818 
2819 	return 0;
2820 }
2821 
sof_ipc4_control_load_enum(struct snd_sof_dev * sdev,struct snd_sof_control * scontrol)2822 static int sof_ipc4_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
2823 {
2824 	struct sof_ipc4_control_data *control_data;
2825 	struct sof_ipc4_msg *msg;
2826 	int i;
2827 
2828 	scontrol->size = struct_size(control_data, chanv, scontrol->num_channels);
2829 
2830 	/* scontrol->ipc_control_data will be freed in sof_control_unload */
2831 	scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
2832 	if (!scontrol->ipc_control_data)
2833 		return -ENOMEM;
2834 
2835 	control_data = scontrol->ipc_control_data;
2836 	control_data->index = scontrol->index;
2837 
2838 	msg = &control_data->msg;
2839 	msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET);
2840 	msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
2841 	msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
2842 
2843 	msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_ENUM_CONTROL_PARAM_ID);
2844 
2845 	/* Default, initial value for enums: first enum entry is selected (0) */
2846 	for (i = 0; i < scontrol->num_channels; i++)
2847 		control_data->chanv[i].channel = i;
2848 
2849 	return 0;
2850 }
2851 
sof_ipc4_control_load_bytes(struct snd_sof_dev * sdev,struct snd_sof_control * scontrol)2852 static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
2853 {
2854 	struct sof_ipc4_control_data *control_data;
2855 	struct sof_ipc4_msg *msg;
2856 	int ret;
2857 
2858 	if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) {
2859 		dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n",
2860 			scontrol->name, scontrol->max_size);
2861 		return -EINVAL;
2862 	}
2863 
2864 	if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) {
2865 		dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n",
2866 			scontrol->name, scontrol->priv_size,
2867 			scontrol->max_size - sizeof(*control_data));
2868 		return -EINVAL;
2869 	}
2870 
2871 	scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size;
2872 
2873 	scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
2874 	if (!scontrol->ipc_control_data)
2875 		return -ENOMEM;
2876 
2877 	control_data = scontrol->ipc_control_data;
2878 	control_data->index = scontrol->index;
2879 	if (scontrol->priv_size > 0) {
2880 		memcpy(control_data->data, scontrol->priv, scontrol->priv_size);
2881 		kfree(scontrol->priv);
2882 		scontrol->priv = NULL;
2883 
2884 		if (control_data->data->magic != SOF_IPC4_ABI_MAGIC) {
2885 			dev_err(sdev->dev, "Wrong ABI magic (%#x) for control: %s\n",
2886 				control_data->data->magic, scontrol->name);
2887 			ret = -EINVAL;
2888 			goto err;
2889 		}
2890 
2891 		/* TODO: check the ABI version */
2892 
2893 		if (control_data->data->size + sizeof(struct sof_abi_hdr) !=
2894 		    scontrol->priv_size) {
2895 			dev_err(sdev->dev, "Control %s conflict in bytes %zu vs. priv size %zu.\n",
2896 				scontrol->name,
2897 				control_data->data->size + sizeof(struct sof_abi_hdr),
2898 				scontrol->priv_size);
2899 			ret = -EINVAL;
2900 			goto err;
2901 		}
2902 	}
2903 
2904 	msg = &control_data->msg;
2905 	msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET);
2906 	msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
2907 	msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
2908 
2909 	return 0;
2910 
2911 err:
2912 	kfree(scontrol->ipc_control_data);
2913 	scontrol->ipc_control_data = NULL;
2914 	return ret;
2915 }
2916 
sof_ipc4_control_setup(struct snd_sof_dev * sdev,struct snd_sof_control * scontrol)2917 static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
2918 {
2919 	switch (scontrol->info_type) {
2920 	case SND_SOC_TPLG_CTL_VOLSW:
2921 	case SND_SOC_TPLG_CTL_VOLSW_SX:
2922 	case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
2923 		return sof_ipc4_control_load_volume(sdev, scontrol);
2924 	case SND_SOC_TPLG_CTL_BYTES:
2925 		return sof_ipc4_control_load_bytes(sdev, scontrol);
2926 	case SND_SOC_TPLG_CTL_ENUM:
2927 	case SND_SOC_TPLG_CTL_ENUM_VALUE:
2928 		return sof_ipc4_control_load_enum(sdev, scontrol);
2929 	default:
2930 		break;
2931 	}
2932 
2933 	return 0;
2934 }
2935 
sof_ipc4_widget_setup(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget)2936 static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
2937 {
2938 	struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
2939 	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
2940 	struct sof_ipc4_pipeline *pipeline;
2941 	struct sof_ipc4_msg *msg;
2942 	void *ipc_data = NULL;
2943 	u32 ipc_size = 0;
2944 	int ret;
2945 
2946 	switch (swidget->id) {
2947 	case snd_soc_dapm_scheduler:
2948 		pipeline = swidget->private;
2949 
2950 		if (pipeline->use_chain_dma) {
2951 			dev_warn(sdev->dev, "use_chain_dma set for scheduler %s",
2952 				 swidget->widget->name);
2953 			return 0;
2954 		}
2955 
2956 		dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id,
2957 			pipeline->mem_usage);
2958 
2959 		msg = &pipeline->msg;
2960 		msg->primary |= pipeline->mem_usage;
2961 
2962 		swidget->instance_id = ida_alloc_max(&pipeline_ida, ipc4_data->max_num_pipelines,
2963 						     GFP_KERNEL);
2964 		if (swidget->instance_id < 0) {
2965 			dev_err(sdev->dev, "failed to assign pipeline id for %s: %d\n",
2966 				swidget->widget->name, swidget->instance_id);
2967 			return swidget->instance_id;
2968 		}
2969 		msg->primary &= ~SOF_IPC4_GLB_PIPE_INSTANCE_MASK;
2970 		msg->primary |= SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id);
2971 		break;
2972 	case snd_soc_dapm_aif_in:
2973 	case snd_soc_dapm_aif_out:
2974 	case snd_soc_dapm_buffer:
2975 	{
2976 		struct sof_ipc4_copier *ipc4_copier = swidget->private;
2977 
2978 		pipeline = pipe_widget->private;
2979 		if (pipeline->use_chain_dma)
2980 			return 0;
2981 
2982 		ipc_size = ipc4_copier->ipc_config_size;
2983 		ipc_data = ipc4_copier->ipc_config_data;
2984 
2985 		msg = &ipc4_copier->msg;
2986 		break;
2987 	}
2988 	case snd_soc_dapm_dai_in:
2989 	case snd_soc_dapm_dai_out:
2990 	{
2991 		struct snd_sof_dai *dai = swidget->private;
2992 		struct sof_ipc4_copier *ipc4_copier = dai->private;
2993 
2994 		pipeline = pipe_widget->private;
2995 		if (pipeline->use_chain_dma)
2996 			return 0;
2997 
2998 		ipc_size = ipc4_copier->ipc_config_size;
2999 		ipc_data = ipc4_copier->ipc_config_data;
3000 
3001 		msg = &ipc4_copier->msg;
3002 		break;
3003 	}
3004 	case snd_soc_dapm_pga:
3005 	{
3006 		struct sof_ipc4_gain *gain = swidget->private;
3007 
3008 		ipc_size = sizeof(gain->data);
3009 		ipc_data = &gain->data;
3010 
3011 		msg = &gain->msg;
3012 		break;
3013 	}
3014 	case snd_soc_dapm_mixer:
3015 	{
3016 		struct sof_ipc4_mixer *mixer = swidget->private;
3017 
3018 		ipc_size = sizeof(mixer->base_config);
3019 		ipc_data = &mixer->base_config;
3020 
3021 		msg = &mixer->msg;
3022 		break;
3023 	}
3024 	case snd_soc_dapm_src:
3025 	{
3026 		struct sof_ipc4_src *src = swidget->private;
3027 
3028 		ipc_size = sizeof(src->data);
3029 		ipc_data = &src->data;
3030 
3031 		msg = &src->msg;
3032 		break;
3033 	}
3034 	case snd_soc_dapm_asrc:
3035 	{
3036 		struct sof_ipc4_asrc *asrc = swidget->private;
3037 
3038 		ipc_size = sizeof(asrc->data);
3039 		ipc_data = &asrc->data;
3040 
3041 		msg = &asrc->msg;
3042 		break;
3043 	}
3044 	case snd_soc_dapm_effect:
3045 	{
3046 		struct sof_ipc4_process *process = swidget->private;
3047 
3048 		if (!process->ipc_config_size) {
3049 			dev_err(sdev->dev, "module %s has no config data!\n",
3050 				swidget->widget->name);
3051 			return -EINVAL;
3052 		}
3053 
3054 		ipc_size = process->ipc_config_size;
3055 		ipc_data = process->ipc_config_data;
3056 
3057 		msg = &process->msg;
3058 		break;
3059 	}
3060 	default:
3061 		dev_err(sdev->dev, "widget type %d not supported", swidget->id);
3062 		return -EINVAL;
3063 	}
3064 
3065 	if (swidget->id != snd_soc_dapm_scheduler) {
3066 		int module_id = msg->primary & SOF_IPC4_MOD_ID_MASK;
3067 
3068 		ret = sof_ipc4_widget_assign_instance_id(sdev, swidget);
3069 		if (ret < 0) {
3070 			dev_err(sdev->dev, "failed to assign instance id for %s\n",
3071 				swidget->widget->name);
3072 			return ret;
3073 		}
3074 
3075 		msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK;
3076 		msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id);
3077 
3078 		msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
3079 		msg->extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(ipc_size >> 2);
3080 
3081 		msg->extension &= ~SOF_IPC4_MOD_EXT_PPL_ID_MASK;
3082 		msg->extension |= SOF_IPC4_MOD_EXT_PPL_ID(pipe_widget->instance_id);
3083 
3084 		dev_dbg(sdev->dev, "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n",
3085 			swidget->widget->name, swidget->pipeline_id, module_id,
3086 			swidget->instance_id, swidget->core);
3087 	} else {
3088 		dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n",
3089 			swidget->widget->name, swidget->pipeline_id,
3090 			swidget->instance_id, swidget->core);
3091 	}
3092 
3093 	msg->data_size = ipc_size;
3094 	msg->data_ptr = ipc_data;
3095 
3096 	ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size);
3097 	if (ret < 0) {
3098 		dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name);
3099 
3100 		if (swidget->id != snd_soc_dapm_scheduler) {
3101 			struct sof_ipc4_fw_module *fw_module = swidget->module_info;
3102 
3103 			ida_free(&fw_module->m_ida, swidget->instance_id);
3104 		} else {
3105 			ida_free(&pipeline_ida, swidget->instance_id);
3106 		}
3107 	}
3108 
3109 	return ret;
3110 }
3111 
sof_ipc4_widget_free(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget)3112 static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
3113 {
3114 	struct sof_ipc4_fw_module *fw_module = swidget->module_info;
3115 	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
3116 	int ret = 0;
3117 
3118 	mutex_lock(&ipc4_data->pipeline_state_mutex);
3119 
3120 	/* freeing a pipeline frees all the widgets associated with it */
3121 	if (swidget->id == snd_soc_dapm_scheduler) {
3122 		struct sof_ipc4_pipeline *pipeline = swidget->private;
3123 		struct sof_ipc4_msg msg = {{ 0 }};
3124 		u32 header;
3125 
3126 		if (pipeline->use_chain_dma) {
3127 			dev_warn(sdev->dev, "use_chain_dma set for scheduler %s",
3128 				 swidget->widget->name);
3129 			mutex_unlock(&ipc4_data->pipeline_state_mutex);
3130 			return 0;
3131 		}
3132 
3133 		header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id);
3134 		header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE);
3135 		header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
3136 		header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG);
3137 
3138 		msg.primary = header;
3139 
3140 		ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
3141 		if (ret < 0)
3142 			dev_err(sdev->dev, "failed to free pipeline widget %s\n",
3143 				swidget->widget->name);
3144 
3145 		pipeline->mem_usage = 0;
3146 		pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED;
3147 		ida_free(&pipeline_ida, swidget->instance_id);
3148 		swidget->instance_id = -EINVAL;
3149 	} else {
3150 		struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
3151 		struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
3152 
3153 		if (!pipeline->use_chain_dma)
3154 			ida_free(&fw_module->m_ida, swidget->instance_id);
3155 	}
3156 
3157 	mutex_unlock(&ipc4_data->pipeline_state_mutex);
3158 
3159 	return ret;
3160 }
3161 
sof_ipc4_get_queue_id(struct snd_sof_widget * src_widget,struct snd_sof_widget * sink_widget,bool pin_type)3162 static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget,
3163 				 struct snd_sof_widget *sink_widget, bool pin_type)
3164 {
3165 	struct snd_sof_widget *current_swidget;
3166 	struct snd_soc_component *scomp;
3167 	struct ida *queue_ida;
3168 	const char *buddy_name;
3169 	char **pin_binding;
3170 	u32 num_pins;
3171 	int i;
3172 
3173 	if (pin_type == SOF_PIN_TYPE_OUTPUT) {
3174 		current_swidget = src_widget;
3175 		pin_binding = src_widget->output_pin_binding;
3176 		queue_ida = &src_widget->output_queue_ida;
3177 		num_pins = src_widget->num_output_pins;
3178 		buddy_name = sink_widget->widget->name;
3179 	} else {
3180 		current_swidget = sink_widget;
3181 		pin_binding = sink_widget->input_pin_binding;
3182 		queue_ida = &sink_widget->input_queue_ida;
3183 		num_pins = sink_widget->num_input_pins;
3184 		buddy_name = src_widget->widget->name;
3185 	}
3186 
3187 	scomp = current_swidget->scomp;
3188 
3189 	if (num_pins < 1) {
3190 		dev_err(scomp->dev, "invalid %s num_pins: %d for queue allocation for %s\n",
3191 			(pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"),
3192 			num_pins, current_swidget->widget->name);
3193 		return -EINVAL;
3194 	}
3195 
3196 	/* If there is only one input/output pin, queue id must be 0 */
3197 	if (num_pins == 1)
3198 		return 0;
3199 
3200 	/* Allocate queue ID from pin binding array if it is defined in topology. */
3201 	if (pin_binding) {
3202 		for (i = 0; i < num_pins; i++) {
3203 			if (!strcmp(pin_binding[i], buddy_name))
3204 				return i;
3205 		}
3206 		/*
3207 		 * Fail if no queue ID found from pin binding array, so that we don't
3208 		 * mixed use pin binding array and ida for queue ID allocation.
3209 		 */
3210 		dev_err(scomp->dev, "no %s queue id found from pin binding array for %s\n",
3211 			(pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"),
3212 			current_swidget->widget->name);
3213 		return -EINVAL;
3214 	}
3215 
3216 	/* If no pin binding array specified in topology, use ida to allocate one */
3217 	return ida_alloc_max(queue_ida, num_pins, GFP_KERNEL);
3218 }
3219 
sof_ipc4_put_queue_id(struct snd_sof_widget * swidget,int queue_id,bool pin_type)3220 static void sof_ipc4_put_queue_id(struct snd_sof_widget *swidget, int queue_id,
3221 				  bool pin_type)
3222 {
3223 	struct ida *queue_ida;
3224 	char **pin_binding;
3225 	int num_pins;
3226 
3227 	if (pin_type == SOF_PIN_TYPE_OUTPUT) {
3228 		pin_binding = swidget->output_pin_binding;
3229 		queue_ida = &swidget->output_queue_ida;
3230 		num_pins = swidget->num_output_pins;
3231 	} else {
3232 		pin_binding = swidget->input_pin_binding;
3233 		queue_ida = &swidget->input_queue_ida;
3234 		num_pins = swidget->num_input_pins;
3235 	}
3236 
3237 	/* Nothing to free if queue ID is not allocated with ida. */
3238 	if (num_pins == 1 || pin_binding)
3239 		return;
3240 
3241 	ida_free(queue_ida, queue_id);
3242 }
3243 
sof_ipc4_set_copier_sink_format(struct snd_sof_dev * sdev,struct snd_sof_widget * src_widget,struct snd_sof_widget * sink_widget,struct snd_sof_route * sroute)3244 static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev,
3245 					   struct snd_sof_widget *src_widget,
3246 					   struct snd_sof_widget *sink_widget,
3247 					   struct snd_sof_route *sroute)
3248 {
3249 	struct sof_ipc4_copier_config_set_sink_format format;
3250 	const struct sof_ipc_ops *iops = sdev->ipc->ops;
3251 	struct sof_ipc4_base_module_cfg *src_config;
3252 	const struct sof_ipc4_audio_format *pin_fmt;
3253 	struct sof_ipc4_fw_module *fw_module;
3254 	struct sof_ipc4_msg msg = {{ 0 }};
3255 
3256 	if (WIDGET_IS_DAI(src_widget->id)) {
3257 		struct snd_sof_dai *dai = src_widget->private;
3258 
3259 		src_config = dai->private;
3260 	} else {
3261 		src_config = src_widget->private;
3262 	}
3263 
3264 	fw_module = src_widget->module_info;
3265 
3266 	format.sink_id = sroute->src_queue_id;
3267 	memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt));
3268 
3269 	pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sroute->dst_queue_id);
3270 	if (!pin_fmt) {
3271 		dev_err(sdev->dev,
3272 			"Failed to get input audio format of %s:%d for output of %s:%d\n",
3273 			sink_widget->widget->name, sroute->dst_queue_id,
3274 			src_widget->widget->name, sroute->src_queue_id);
3275 		return -EINVAL;
3276 	}
3277 
3278 	memcpy(&format.sink_fmt, pin_fmt, sizeof(format.sink_fmt));
3279 
3280 	msg.data_size = sizeof(format);
3281 	msg.data_ptr = &format;
3282 
3283 	msg.primary = fw_module->man4_module_entry.id;
3284 	msg.primary |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id);
3285 	msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
3286 	msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
3287 
3288 	msg.extension =
3289 		SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT);
3290 
3291 	return iops->set_get_data(sdev, &msg, msg.data_size, true);
3292 }
3293 
sof_ipc4_route_setup(struct snd_sof_dev * sdev,struct snd_sof_route * sroute)3294 static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
3295 {
3296 	struct snd_sof_widget *src_widget = sroute->src_widget;
3297 	struct snd_sof_widget *sink_widget = sroute->sink_widget;
3298 	struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget;
3299 	struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget;
3300 	struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info;
3301 	struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info;
3302 	struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private;
3303 	struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private;
3304 	struct sof_ipc4_msg msg = {{ 0 }};
3305 	u32 header, extension;
3306 	int ret;
3307 
3308 	/* no route set up if chain DMA is used */
3309 	if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) {
3310 		if (!src_pipeline->use_chain_dma || !sink_pipeline->use_chain_dma) {
3311 			dev_err(sdev->dev,
3312 				"use_chain_dma must be set for both src %s and sink %s pipelines\n",
3313 				src_widget->widget->name, sink_widget->widget->name);
3314 			return -EINVAL;
3315 		}
3316 		return 0;
3317 	}
3318 
3319 	if (!src_fw_module || !sink_fw_module) {
3320 		dev_err(sdev->dev,
3321 			"cannot bind %s -> %s, no firmware module for: %s%s\n",
3322 			src_widget->widget->name, sink_widget->widget->name,
3323 			src_fw_module ? "" : " source",
3324 			sink_fw_module ? "" : " sink");
3325 
3326 		return -ENODEV;
3327 	}
3328 
3329 	sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget,
3330 						     SOF_PIN_TYPE_OUTPUT);
3331 	if (sroute->src_queue_id < 0) {
3332 		dev_err(sdev->dev,
3333 			"failed to get src_queue_id ID from source widget %s\n",
3334 			src_widget->widget->name);
3335 		return sroute->src_queue_id;
3336 	}
3337 
3338 	sroute->dst_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget,
3339 						     SOF_PIN_TYPE_INPUT);
3340 	if (sroute->dst_queue_id < 0) {
3341 		dev_err(sdev->dev,
3342 			"failed to get dst_queue_id ID from sink widget %s\n",
3343 			sink_widget->widget->name);
3344 		sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id,
3345 				      SOF_PIN_TYPE_OUTPUT);
3346 		return sroute->dst_queue_id;
3347 	}
3348 
3349 	/* Pin 0 format is already set during copier module init */
3350 	if (sroute->src_queue_id > 0 && WIDGET_IS_COPIER(src_widget->id)) {
3351 		ret = sof_ipc4_set_copier_sink_format(sdev, src_widget,
3352 						      sink_widget, sroute);
3353 		if (ret < 0) {
3354 			dev_err(sdev->dev,
3355 				"failed to set sink format for source %s:%d\n",
3356 				src_widget->widget->name, sroute->src_queue_id);
3357 			goto out;
3358 		}
3359 	}
3360 
3361 	dev_dbg(sdev->dev, "bind %s:%d -> %s:%d\n",
3362 		src_widget->widget->name, sroute->src_queue_id,
3363 		sink_widget->widget->name, sroute->dst_queue_id);
3364 
3365 	header = src_fw_module->man4_module_entry.id;
3366 	header |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id);
3367 	header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_BIND);
3368 	header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
3369 	header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
3370 
3371 	extension = sink_fw_module->man4_module_entry.id;
3372 	extension |= SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(sink_widget->instance_id);
3373 	extension |= SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(sroute->dst_queue_id);
3374 	extension |= SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(sroute->src_queue_id);
3375 
3376 	msg.primary = header;
3377 	msg.extension = extension;
3378 
3379 	ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
3380 	if (ret < 0) {
3381 		dev_err(sdev->dev, "failed to bind modules %s:%d -> %s:%d\n",
3382 			src_widget->widget->name, sroute->src_queue_id,
3383 			sink_widget->widget->name, sroute->dst_queue_id);
3384 		goto out;
3385 	}
3386 
3387 	return ret;
3388 
3389 out:
3390 	sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT);
3391 	sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT);
3392 	return ret;
3393 }
3394 
sof_ipc4_route_free(struct snd_sof_dev * sdev,struct snd_sof_route * sroute)3395 static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *sroute)
3396 {
3397 	struct snd_sof_widget *src_widget = sroute->src_widget;
3398 	struct snd_sof_widget *sink_widget = sroute->sink_widget;
3399 	struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info;
3400 	struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info;
3401 	struct sof_ipc4_msg msg = {{ 0 }};
3402 	struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget;
3403 	struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget;
3404 	struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private;
3405 	struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private;
3406 	u32 header, extension;
3407 	int ret = 0;
3408 
3409 	/* no route is set up if chain DMA is used */
3410 	if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma)
3411 		return 0;
3412 
3413 	dev_dbg(sdev->dev, "unbind modules %s:%d -> %s:%d\n",
3414 		src_widget->widget->name, sroute->src_queue_id,
3415 		sink_widget->widget->name, sroute->dst_queue_id);
3416 
3417 	/*
3418 	 * routes belonging to the same pipeline will be disconnected by the FW when the pipeline
3419 	 * is freed. So avoid sending this IPC which will be ignored by the FW anyway.
3420 	 */
3421 	if (src_widget->spipe->pipe_widget == sink_widget->spipe->pipe_widget)
3422 		goto out;
3423 
3424 	header = src_fw_module->man4_module_entry.id;
3425 	header |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id);
3426 	header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_UNBIND);
3427 	header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
3428 	header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
3429 
3430 	extension = sink_fw_module->man4_module_entry.id;
3431 	extension |= SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(sink_widget->instance_id);
3432 	extension |= SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(sroute->dst_queue_id);
3433 	extension |= SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(sroute->src_queue_id);
3434 
3435 	msg.primary = header;
3436 	msg.extension = extension;
3437 
3438 	ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
3439 	if (ret < 0)
3440 		dev_err(sdev->dev, "failed to unbind modules %s:%d -> %s:%d\n",
3441 			src_widget->widget->name, sroute->src_queue_id,
3442 			sink_widget->widget->name, sroute->dst_queue_id);
3443 out:
3444 	sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT);
3445 	sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT);
3446 
3447 	return ret;
3448 }
3449 
sof_ipc4_dai_config(struct snd_sof_dev * sdev,struct snd_sof_widget * swidget,unsigned int flags,struct snd_sof_dai_config_data * data)3450 static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
3451 			       unsigned int flags, struct snd_sof_dai_config_data *data)
3452 {
3453 	struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
3454 	struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
3455 	struct snd_sof_dai *dai = swidget->private;
3456 	struct sof_ipc4_gtw_attributes *gtw_attr;
3457 	struct sof_ipc4_copier_data *copier_data;
3458 	struct sof_ipc4_copier *ipc4_copier;
3459 
3460 	if (!dai || !dai->private) {
3461 		dev_err(sdev->dev, "Invalid DAI or DAI private data for %s\n",
3462 			swidget->widget->name);
3463 		return -EINVAL;
3464 	}
3465 
3466 	ipc4_copier = (struct sof_ipc4_copier *)dai->private;
3467 	copier_data = &ipc4_copier->data;
3468 
3469 	if (!data)
3470 		return 0;
3471 
3472 	if (pipeline->use_chain_dma) {
3473 		/*
3474 		 * Only configure the DMA Link ID for ChainDMA when this op is
3475 		 * invoked with SOF_DAI_CONFIG_FLAGS_HW_PARAMS
3476 		 */
3477 		if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
3478 			pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK;
3479 			pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data);
3480 		}
3481 		return 0;
3482 	}
3483 
3484 	switch (ipc4_copier->dai_type) {
3485 	case SOF_DAI_INTEL_HDA:
3486 		gtw_attr = ipc4_copier->gtw_attr;
3487 		gtw_attr->lp_buffer_alloc = pipeline->lp_mode;
3488 		if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
3489 			copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
3490 			copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
3491 		}
3492 		break;
3493 	case SOF_DAI_INTEL_ALH:
3494 		/*
3495 		 * Do not clear the node ID when this op is invoked with
3496 		 * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during
3497 		 * unprepare. The node_id for multi-gateway DAI's will be overwritten with the
3498 		 * group_id during copier's ipc_prepare op.
3499 		 */
3500 		if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
3501 			struct sof_ipc4_alh_configuration_blob *blob;
3502 
3503 			blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
3504 			ipc4_copier->dai_index = data->dai_node_id;
3505 
3506 			/*
3507 			 * no need to set the node_id for aggregated DAI's. These will be assigned
3508 			 * a group_id during widget ipc_prepare
3509 			 */
3510 			if (blob->alh_cfg.device_count == 1) {
3511 				copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
3512 				copier_data->gtw_cfg.node_id |=
3513 					SOF_IPC4_NODE_INDEX(data->dai_node_id);
3514 			}
3515 		}
3516 
3517 		break;
3518 	case SOF_DAI_INTEL_DMIC:
3519 	case SOF_DAI_INTEL_SSP:
3520 		/* nothing to do for SSP/DMIC */
3521 		break;
3522 	default:
3523 		dev_err(sdev->dev, "%s: unsupported dai type %d\n", __func__,
3524 			ipc4_copier->dai_type);
3525 		return -EINVAL;
3526 	}
3527 
3528 	return 0;
3529 }
3530 
sof_ipc4_parse_manifest(struct snd_soc_component * scomp,int index,struct snd_soc_tplg_manifest * man)3531 static int sof_ipc4_parse_manifest(struct snd_soc_component *scomp, int index,
3532 				   struct snd_soc_tplg_manifest *man)
3533 {
3534 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
3535 	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
3536 	struct sof_manifest_tlv *manifest_tlv;
3537 	struct sof_manifest *manifest;
3538 	u32 size = le32_to_cpu(man->priv.size);
3539 	u8 *man_ptr = man->priv.data;
3540 	u32 len_check;
3541 	int i;
3542 
3543 	if (!size || size < SOF_IPC4_TPLG_ABI_SIZE) {
3544 		dev_err(scomp->dev, "%s: Invalid topology ABI size: %u\n",
3545 			__func__, size);
3546 		return -EINVAL;
3547 	}
3548 
3549 	manifest = (struct sof_manifest *)man_ptr;
3550 
3551 	dev_info(scomp->dev,
3552 		 "Topology: ABI %d:%d:%d Kernel ABI %u:%u:%u\n",
3553 		  le16_to_cpu(manifest->abi_major), le16_to_cpu(manifest->abi_minor),
3554 		  le16_to_cpu(manifest->abi_patch),
3555 		  SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH);
3556 
3557 	/* TODO: Add ABI compatibility check */
3558 
3559 	/* no more data after the ABI version */
3560 	if (size <= SOF_IPC4_TPLG_ABI_SIZE)
3561 		return 0;
3562 
3563 	manifest_tlv = manifest->items;
3564 	len_check = sizeof(struct sof_manifest);
3565 	for (i = 0; i < le16_to_cpu(manifest->count); i++) {
3566 		len_check += sizeof(struct sof_manifest_tlv) + le32_to_cpu(manifest_tlv->size);
3567 		if (len_check > size)
3568 			return -EINVAL;
3569 
3570 		switch (le32_to_cpu(manifest_tlv->type)) {
3571 		case SOF_MANIFEST_DATA_TYPE_NHLT:
3572 			/* no NHLT in BIOS, so use the one from topology manifest */
3573 			if (ipc4_data->nhlt)
3574 				break;
3575 			ipc4_data->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data,
3576 						       le32_to_cpu(manifest_tlv->size), GFP_KERNEL);
3577 			if (!ipc4_data->nhlt)
3578 				return -ENOMEM;
3579 			break;
3580 		default:
3581 			dev_warn(scomp->dev, "Skipping unknown manifest data type %d\n",
3582 				 manifest_tlv->type);
3583 			break;
3584 		}
3585 		man_ptr += sizeof(struct sof_manifest_tlv) + le32_to_cpu(manifest_tlv->size);
3586 		manifest_tlv = (struct sof_manifest_tlv *)man_ptr;
3587 	}
3588 
3589 	return 0;
3590 }
3591 
sof_ipc4_dai_get_param(struct snd_sof_dev * sdev,struct snd_sof_dai * dai,int param_type)3592 static int sof_ipc4_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type)
3593 {
3594 	struct sof_ipc4_copier *ipc4_copier = dai->private;
3595 	struct snd_soc_tplg_hw_config *hw_config;
3596 	struct snd_sof_dai_link *slink;
3597 	bool dai_link_found = false;
3598 	bool hw_cfg_found = false;
3599 	int i;
3600 
3601 	if (!ipc4_copier)
3602 		return 0;
3603 
3604 	list_for_each_entry(slink, &sdev->dai_link_list, list) {
3605 		if (!strcmp(slink->link->name, dai->name)) {
3606 			dai_link_found = true;
3607 			break;
3608 		}
3609 	}
3610 
3611 	if (!dai_link_found) {
3612 		dev_err(sdev->dev, "no DAI link found for DAI %s\n", dai->name);
3613 		return -EINVAL;
3614 	}
3615 
3616 	for (i = 0; i < slink->num_hw_configs; i++) {
3617 		hw_config = &slink->hw_configs[i];
3618 		if (dai->current_config == le32_to_cpu(hw_config->id)) {
3619 			hw_cfg_found = true;
3620 			break;
3621 		}
3622 	}
3623 
3624 	if (!hw_cfg_found) {
3625 		dev_err(sdev->dev, "no matching hw_config found for DAI %s\n", dai->name);
3626 		return -EINVAL;
3627 	}
3628 
3629 	switch (ipc4_copier->dai_type) {
3630 	case SOF_DAI_INTEL_SSP:
3631 		switch (param_type) {
3632 		case SOF_DAI_PARAM_INTEL_SSP_MCLK:
3633 			return le32_to_cpu(hw_config->mclk_rate);
3634 		case SOF_DAI_PARAM_INTEL_SSP_BCLK:
3635 			return le32_to_cpu(hw_config->bclk_rate);
3636 		case SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS:
3637 			return le32_to_cpu(hw_config->tdm_slots);
3638 		default:
3639 			dev_err(sdev->dev, "invalid SSP param %d\n", param_type);
3640 			break;
3641 		}
3642 		break;
3643 	default:
3644 		dev_err(sdev->dev, "DAI type %d not supported yet!\n", ipc4_copier->dai_type);
3645 		break;
3646 	}
3647 
3648 	return -EINVAL;
3649 }
3650 
sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev * sdev,bool verify)3651 static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
3652 {
3653 	/*
3654 	 * This function is called during system suspend, we need to make sure
3655 	 * that all streams have been freed up.
3656 	 * Freeing might have been skipped when xrun happened just at the start
3657 	 * of the suspend and it sent a SNDRV_PCM_TRIGGER_STOP to the active
3658 	 * stream. This will call sof_pcm_stream_free() with
3659 	 * free_widget_list = false which will leave the kernel and firmware out
3660 	 * of sync during suspend/resume.
3661 	 *
3662 	 * This will also make sure that paused streams handled correctly.
3663 	 */
3664 
3665 	return sof_pcm_free_all_streams(sdev);
3666 }
3667 
sof_ipc4_link_setup(struct snd_sof_dev * sdev,struct snd_soc_dai_link * link)3668 static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link)
3669 {
3670 	if (link->no_pcm)
3671 		return 0;
3672 
3673 	/*
3674 	 * set default trigger order for all links. Exceptions to
3675 	 * the rule will be handled in sof_pcm_dai_link_fixup()
3676 	 * For playback, the sequence is the following: start BE,
3677 	 * start FE, stop FE, stop BE; for Capture the sequence is
3678 	 * inverted start FE, start BE, stop BE, stop FE
3679 	 */
3680 	link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = SND_SOC_DPCM_TRIGGER_POST;
3681 	link->trigger[SNDRV_PCM_STREAM_CAPTURE] = SND_SOC_DPCM_TRIGGER_PRE;
3682 
3683 	return 0;
3684 }
3685 
3686 /* Tokens needed for different copier variants (aif, dai and buffer) */
3687 static enum sof_tokens copier_token_list[] = {
3688 	SOF_COMP_TOKENS,
3689 	SOF_COPIER_TOKENS,
3690 	SOF_AUDIO_FMT_NUM_TOKENS,
3691 	SOF_IN_AUDIO_FORMAT_TOKENS,
3692 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3693 	SOF_COMP_EXT_TOKENS,
3694 
3695 	SOF_COPIER_DEEP_BUFFER_TOKENS,	/* for AIF copier */
3696 	SOF_DAI_TOKENS,			/* for DAI copier */
3697 };
3698 
3699 static enum sof_tokens pipeline_token_list[] = {
3700 	SOF_SCHED_TOKENS,
3701 	SOF_PIPELINE_TOKENS,
3702 };
3703 
3704 static enum sof_tokens pga_token_list[] = {
3705 	SOF_COMP_TOKENS,
3706 	SOF_GAIN_TOKENS,
3707 	SOF_AUDIO_FMT_NUM_TOKENS,
3708 	SOF_IN_AUDIO_FORMAT_TOKENS,
3709 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3710 	SOF_COMP_EXT_TOKENS,
3711 };
3712 
3713 static enum sof_tokens mixer_token_list[] = {
3714 	SOF_COMP_TOKENS,
3715 	SOF_AUDIO_FMT_NUM_TOKENS,
3716 	SOF_IN_AUDIO_FORMAT_TOKENS,
3717 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3718 	SOF_COMP_EXT_TOKENS,
3719 };
3720 
3721 static enum sof_tokens src_token_list[] = {
3722 	SOF_COMP_TOKENS,
3723 	SOF_SRC_TOKENS,
3724 	SOF_AUDIO_FMT_NUM_TOKENS,
3725 	SOF_IN_AUDIO_FORMAT_TOKENS,
3726 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3727 	SOF_COMP_EXT_TOKENS,
3728 };
3729 
3730 static enum sof_tokens asrc_token_list[] = {
3731 	SOF_COMP_TOKENS,
3732 	SOF_ASRC_TOKENS,
3733 	SOF_AUDIO_FMT_NUM_TOKENS,
3734 	SOF_IN_AUDIO_FORMAT_TOKENS,
3735 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3736 	SOF_COMP_EXT_TOKENS,
3737 };
3738 
3739 static enum sof_tokens process_token_list[] = {
3740 	SOF_COMP_TOKENS,
3741 	SOF_AUDIO_FMT_NUM_TOKENS,
3742 	SOF_IN_AUDIO_FORMAT_TOKENS,
3743 	SOF_OUT_AUDIO_FORMAT_TOKENS,
3744 	SOF_COMP_EXT_TOKENS,
3745 };
3746 
3747 static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
3748 	[snd_soc_dapm_aif_in] =  {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
3749 				  copier_token_list, ARRAY_SIZE(copier_token_list),
3750 				  NULL, sof_ipc4_prepare_copier_module,
3751 				  sof_ipc4_unprepare_copier_module},
3752 	[snd_soc_dapm_aif_out] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
3753 				  copier_token_list, ARRAY_SIZE(copier_token_list),
3754 				  NULL, sof_ipc4_prepare_copier_module,
3755 				  sof_ipc4_unprepare_copier_module},
3756 	[snd_soc_dapm_dai_in] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai,
3757 				 copier_token_list, ARRAY_SIZE(copier_token_list), NULL,
3758 				 sof_ipc4_prepare_copier_module,
3759 				 sof_ipc4_unprepare_copier_module},
3760 	[snd_soc_dapm_dai_out] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai,
3761 				  copier_token_list, ARRAY_SIZE(copier_token_list), NULL,
3762 				  sof_ipc4_prepare_copier_module,
3763 				  sof_ipc4_unprepare_copier_module},
3764 	[snd_soc_dapm_buffer] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
3765 				 copier_token_list, ARRAY_SIZE(copier_token_list),
3766 				 NULL, sof_ipc4_prepare_copier_module,
3767 				 sof_ipc4_unprepare_copier_module},
3768 	[snd_soc_dapm_scheduler] = {sof_ipc4_widget_setup_comp_pipeline,
3769 				    sof_ipc4_widget_free_comp_pipeline,
3770 				    pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL,
3771 				    NULL, NULL},
3772 	[snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga,
3773 			      pga_token_list, ARRAY_SIZE(pga_token_list), NULL,
3774 			      sof_ipc4_prepare_gain_module,
3775 			      NULL},
3776 	[snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer,
3777 				mixer_token_list, ARRAY_SIZE(mixer_token_list),
3778 				NULL, sof_ipc4_prepare_mixer_module,
3779 				NULL},
3780 	[snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
3781 				src_token_list, ARRAY_SIZE(src_token_list),
3782 				NULL, sof_ipc4_prepare_src_module,
3783 				NULL},
3784 	[snd_soc_dapm_asrc] = {sof_ipc4_widget_setup_comp_asrc, sof_ipc4_widget_free_comp_asrc,
3785 				asrc_token_list, ARRAY_SIZE(asrc_token_list),
3786 				NULL, sof_ipc4_prepare_src_module, /* Common prepare with SRC */
3787 				NULL},
3788 	[snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process,
3789 				sof_ipc4_widget_free_comp_process,
3790 				process_token_list, ARRAY_SIZE(process_token_list),
3791 				NULL, sof_ipc4_prepare_process_module,
3792 				NULL},
3793 };
3794 
3795 const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
3796 	.widget = tplg_ipc4_widget_ops,
3797 	.token_list = ipc4_token_list,
3798 	.control_setup = sof_ipc4_control_setup,
3799 	.control = &tplg_ipc4_control_ops,
3800 	.widget_setup = sof_ipc4_widget_setup,
3801 	.widget_free = sof_ipc4_widget_free,
3802 	.route_setup = sof_ipc4_route_setup,
3803 	.route_free = sof_ipc4_route_free,
3804 	.dai_config = sof_ipc4_dai_config,
3805 	.parse_manifest = sof_ipc4_parse_manifest,
3806 	.dai_get_param = sof_ipc4_dai_get_param,
3807 	.tear_down_all_pipelines = sof_ipc4_tear_down_all_pipelines,
3808 	.link_setup = sof_ipc4_link_setup,
3809 };
3810