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