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