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