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