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