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