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