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