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 /* Prefer 32-bit blob if copier supports multiple formats */ 1757 if (bit_depth <= 16 && !single_bitdepth) { 1758 dev_dbg(sdev->dev, "Looking for 32-bit blob first for DMIC\n"); 1759 format_change = true; 1760 bit_depth = 32; 1761 } 1762 break; 1763 case SOF_DAI_INTEL_SSP: 1764 nhlt_type = NHLT_LINK_SSP; 1765 ret = snd_sof_get_hw_config_params(sdev, dai, &sample_rate, &channel_count, 1766 &bit_depth); 1767 if (ret < 0) 1768 return ret; 1769 1770 /* 1771 * We need to know the type of the external device attached to a SSP 1772 * port to retrieve the blob from NHLT. However, device type is not 1773 * specified in topology. 1774 * Query the type for the port and then pass that information back 1775 * to the blob lookup function. 1776 */ 1777 dev_type = intel_nhlt_ssp_device_type(sdev->dev, ipc4_data->nhlt, 1778 dai_index); 1779 if (dev_type < 0) 1780 return dev_type; 1781 break; 1782 default: 1783 return 0; 1784 } 1785 1786 dev_dbg(sdev->dev, "dai index %d nhlt type %d direction %d dev type %d\n", 1787 dai_index, nhlt_type, dir, dev_type); 1788 1789 /* find NHLT blob with matching params */ 1790 cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, dai_index, nhlt_type, 1791 bit_depth, bit_depth, channel_count, sample_rate, 1792 dir, dev_type); 1793 1794 if (!cfg) { 1795 bool get_new_blob = false; 1796 1797 if (format_change) { 1798 /* 1799 * The 32-bit blob was not found in NHLT table, try to 1800 * look for 16-bit for DMIC or based on the params for 1801 * SSP 1802 */ 1803 if (linktype == SOF_DAI_INTEL_DMIC) { 1804 bit_depth = 16; 1805 if (params_width(params) == 16) 1806 format_change = false; 1807 } else { 1808 bit_depth = params_width(params); 1809 format_change = false; 1810 } 1811 1812 get_new_blob = true; 1813 } else if (linktype == SOF_DAI_INTEL_DMIC && !single_bitdepth) { 1814 /* 1815 * The requested 32-bit blob (no format change for the 1816 * blob request) was not found in NHLT table, try to 1817 * look for 16-bit blob if the copier supports multiple 1818 * formats 1819 */ 1820 bit_depth = 16; 1821 format_change = true; 1822 get_new_blob = true; 1823 } 1824 1825 if (get_new_blob) { 1826 cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, 1827 dai_index, nhlt_type, 1828 bit_depth, bit_depth, 1829 channel_count, sample_rate, 1830 dir, dev_type); 1831 if (cfg) 1832 goto out; 1833 } 1834 1835 dev_err(sdev->dev, 1836 "no matching blob for sample rate: %d sample width: %d channels: %d\n", 1837 sample_rate, bit_depth, channel_count); 1838 return -EINVAL; 1839 } 1840 1841 out: 1842 /* config length should be in dwords */ 1843 *len = cfg->size >> 2; 1844 *dst = (u32 *)cfg->caps; 1845 1846 if (format_change || params_format(params) == SNDRV_PCM_FORMAT_FLOAT_LE) { 1847 /* 1848 * Update the params to reflect that different blob was loaded 1849 * instead of the requested bit depth (16 -> 32 or 32 -> 16). 1850 * This information is going to be used by the caller to find 1851 * matching copier format on the dai side. 1852 */ 1853 struct snd_mask *m; 1854 1855 m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1856 snd_mask_none(m); 1857 if (bit_depth == 16) 1858 snd_mask_set_format(m, SNDRV_PCM_FORMAT_S16_LE); 1859 else 1860 snd_mask_set_format(m, SNDRV_PCM_FORMAT_S32_LE); 1861 1862 } 1863 1864 return 0; 1865 } 1866 #else 1867 static int 1868 snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, 1869 bool single_bitdepth, 1870 struct snd_pcm_hw_params *params, u32 dai_index, 1871 u32 linktype, u8 dir, u32 **dst, u32 *len) 1872 { 1873 return 0; 1874 } 1875 #endif 1876 1877 bool sof_ipc4_copier_is_single_bitdepth(struct snd_sof_dev *sdev, 1878 struct sof_ipc4_pin_format *pin_fmts, 1879 u32 pin_fmts_size) 1880 { 1881 struct sof_ipc4_audio_format *fmt; 1882 u32 valid_bits; 1883 int i; 1884 1885 fmt = &pin_fmts[0].audio_fmt; 1886 valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1887 1888 /* check if all formats in topology are the same */ 1889 for (i = 1; i < pin_fmts_size; i++) { 1890 u32 _valid_bits; 1891 1892 fmt = &pin_fmts[i].audio_fmt; 1893 _valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1894 1895 if (_valid_bits != valid_bits) 1896 return false; 1897 } 1898 1899 return true; 1900 } 1901 1902 static int 1903 sof_ipc4_adjust_params_to_dai_format(struct snd_sof_dev *sdev, 1904 struct snd_pcm_hw_params *params, 1905 struct sof_ipc4_pin_format *pin_fmts, 1906 u32 pin_fmts_size) 1907 { 1908 u32 params_mask = BIT(SNDRV_PCM_HW_PARAM_RATE) | 1909 BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | 1910 BIT(SNDRV_PCM_HW_PARAM_FORMAT); 1911 struct sof_ipc4_audio_format *fmt; 1912 u32 rate, channels, valid_bits; 1913 int i; 1914 1915 fmt = &pin_fmts[0].audio_fmt; 1916 rate = fmt->sampling_frequency; 1917 channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); 1918 valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1919 1920 /* check if parameters in topology defined formats are the same */ 1921 for (i = 1; i < pin_fmts_size; i++) { 1922 u32 val; 1923 1924 fmt = &pin_fmts[i].audio_fmt; 1925 1926 if (params_mask & BIT(SNDRV_PCM_HW_PARAM_RATE)) { 1927 val = fmt->sampling_frequency; 1928 if (val != rate) 1929 params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_RATE); 1930 } 1931 if (params_mask & BIT(SNDRV_PCM_HW_PARAM_CHANNELS)) { 1932 val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); 1933 if (val != channels) 1934 params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_CHANNELS); 1935 } 1936 if (params_mask & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) { 1937 val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1938 if (val != valid_bits) 1939 params_mask &= ~BIT(SNDRV_PCM_HW_PARAM_FORMAT); 1940 } 1941 } 1942 1943 if (params_mask) 1944 return sof_ipc4_update_hw_params(sdev, params, 1945 &pin_fmts[0].audio_fmt, 1946 params_mask); 1947 1948 return 0; 1949 } 1950 1951 static int 1952 sof_ipc4_prepare_dai_copier(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, 1953 struct snd_pcm_hw_params *params, int dir) 1954 { 1955 struct sof_ipc4_available_audio_format *available_fmt; 1956 struct snd_pcm_hw_params dai_params = *params; 1957 struct sof_ipc4_copier_data *copier_data; 1958 struct sof_ipc4_pin_format *pin_fmts; 1959 struct sof_ipc4_copier *ipc4_copier; 1960 bool single_bitdepth; 1961 u32 num_pin_fmts; 1962 int ret; 1963 1964 ipc4_copier = dai->private; 1965 copier_data = &ipc4_copier->data; 1966 available_fmt = &ipc4_copier->available_fmt; 1967 1968 /* 1969 * Fixup the params based on the format parameters of the DAI. If any 1970 * of the RATE, CHANNELS, bit depth is static among the formats then 1971 * narrow the params to only allow that specific parameter value. 1972 */ 1973 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 1974 pin_fmts = available_fmt->output_pin_fmts; 1975 num_pin_fmts = available_fmt->num_output_formats; 1976 } else { 1977 pin_fmts = available_fmt->input_pin_fmts; 1978 num_pin_fmts = available_fmt->num_input_formats; 1979 } 1980 1981 ret = sof_ipc4_adjust_params_to_dai_format(sdev, &dai_params, pin_fmts, 1982 num_pin_fmts); 1983 if (ret) 1984 return ret; 1985 1986 single_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev, pin_fmts, 1987 num_pin_fmts); 1988 ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, single_bitdepth, 1989 &dai_params, 1990 ipc4_copier->dai_index, 1991 ipc4_copier->dai_type, dir, 1992 &ipc4_copier->copier_config, 1993 &copier_data->gtw_cfg.config_length); 1994 /* Update the params to reflect the changes made in this function */ 1995 if (!ret) 1996 *params = dai_params; 1997 1998 return ret; 1999 } 2000 2001 static int 2002 sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, 2003 struct snd_pcm_hw_params *fe_params, 2004 struct snd_sof_platform_stream_params *platform_params, 2005 struct snd_pcm_hw_params *pipeline_params, int dir) 2006 { 2007 struct sof_ipc4_available_audio_format *available_fmt; 2008 struct snd_soc_component *scomp = swidget->scomp; 2009 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2010 struct sof_ipc4_copier_data *copier_data; 2011 int input_fmt_index, output_fmt_index; 2012 struct sof_ipc4_copier *ipc4_copier; 2013 struct snd_pcm_hw_params *ref_params __free(kfree) = NULL; 2014 struct snd_sof_dai *dai; 2015 u32 gtw_cfg_config_length; 2016 u32 dma_config_tlv_size = 0; 2017 void **ipc_config_data; 2018 int *ipc_config_size; 2019 u32 **data; 2020 int ipc_size, ret, out_ref_valid_bits; 2021 u32 out_ref_rate, out_ref_channels, out_ref_type; 2022 u32 deep_buffer_dma_ms = 0; 2023 bool single_output_bitdepth; 2024 int i; 2025 2026 switch (swidget->id) { 2027 case snd_soc_dapm_aif_in: 2028 case snd_soc_dapm_aif_out: 2029 { 2030 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 2031 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 2032 struct sof_ipc4_gtw_attributes *gtw_attr; 2033 2034 dev_dbg(sdev->dev, 2035 "Host copier %s, type %d, ChainDMA: %s, stream_tag: %d\n", 2036 swidget->widget->name, swidget->id, 2037 str_yes_no(pipeline->use_chain_dma), 2038 platform_params->stream_tag); 2039 2040 /* parse the deep buffer dma size */ 2041 ret = sof_update_ipc_object(scomp, &deep_buffer_dma_ms, 2042 SOF_COPIER_DEEP_BUFFER_TOKENS, swidget->tuples, 2043 swidget->num_tuples, sizeof(u32), 1); 2044 if (ret) { 2045 dev_err(scomp->dev, "Failed to parse deep buffer dma size for %s\n", 2046 swidget->widget->name); 2047 return ret; 2048 } 2049 2050 ipc4_copier = (struct sof_ipc4_copier *)swidget->private; 2051 gtw_attr = ipc4_copier->gtw_attr; 2052 copier_data = &ipc4_copier->data; 2053 available_fmt = &ipc4_copier->available_fmt; 2054 2055 if (pipeline->use_chain_dma) { 2056 u32 host_dma_id; 2057 u32 fifo_size; 2058 2059 host_dma_id = platform_params->stream_tag - 1; 2060 pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id); 2061 2062 if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE) 2063 pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; 2064 2065 /* Set SCS bit for 8 and 16 bit formats */ 2066 if (params_physical_width(fe_params) <= 16) 2067 pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; 2068 2069 /* 2070 * Despite its name the bitfield 'fifo_size' is used to define DMA buffer 2071 * size. The expression calculates 2ms buffer size. 2072 */ 2073 fifo_size = DIV_ROUND_UP((SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * 2074 params_rate(fe_params) * 2075 params_channels(fe_params) * 2076 params_physical_width(fe_params)), 8000); 2077 pipeline->msg.extension |= SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(fifo_size); 2078 2079 /* 2080 * Chain DMA does not support stream timestamping, but it 2081 * can use the host side registers for delay calculation. 2082 */ 2083 copier_data->gtw_cfg.node_id = SOF_IPC4_CHAIN_DMA_NODE_ID; 2084 2085 return 0; 2086 } 2087 2088 /* 2089 * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts 2090 * for capture. 2091 */ 2092 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 2093 ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); 2094 else 2095 ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); 2096 if (!ref_params) 2097 return -ENOMEM; 2098 2099 copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 2100 copier_data->gtw_cfg.node_id |= 2101 SOF_IPC4_NODE_INDEX(platform_params->stream_tag - 1); 2102 2103 /* set gateway attributes */ 2104 gtw_attr->lp_buffer_alloc = pipeline->lp_mode; 2105 break; 2106 } 2107 case snd_soc_dapm_dai_in: 2108 case snd_soc_dapm_dai_out: 2109 { 2110 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 2111 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 2112 2113 dev_dbg(sdev->dev, "Dai copier %s, type %d, ChainDMA: %s\n", 2114 swidget->widget->name, swidget->id, 2115 str_yes_no(pipeline->use_chain_dma)); 2116 2117 if (pipeline->use_chain_dma) 2118 return 0; 2119 2120 dai = swidget->private; 2121 2122 ipc4_copier = (struct sof_ipc4_copier *)dai->private; 2123 copier_data = &ipc4_copier->data; 2124 available_fmt = &ipc4_copier->available_fmt; 2125 2126 /* 2127 * Use the fe_params as a base for the copier configuration. 2128 * The ref_params might get updated to reflect what format is 2129 * supported by the copier on the DAI side. 2130 * 2131 * In case of capture the ref_params returned will be used to 2132 * find the input configuration of the copier. 2133 */ 2134 ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); 2135 if (!ref_params) 2136 return -ENOMEM; 2137 2138 ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); 2139 if (ret < 0) 2140 return ret; 2141 2142 /* 2143 * For playback the pipeline_params needs to be used to find the 2144 * input configuration of the copier. 2145 */ 2146 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 2147 memcpy(ref_params, pipeline_params, sizeof(*ref_params)); 2148 2149 break; 2150 } 2151 case snd_soc_dapm_buffer: 2152 { 2153 dev_dbg(sdev->dev, "Module copier %s, type %d\n", 2154 swidget->widget->name, swidget->id); 2155 2156 ipc4_copier = (struct sof_ipc4_copier *)swidget->private; 2157 copier_data = &ipc4_copier->data; 2158 available_fmt = &ipc4_copier->available_fmt; 2159 2160 ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); 2161 if (!ref_params) 2162 return -ENOMEM; 2163 2164 break; 2165 } 2166 default: 2167 dev_err(sdev->dev, "unsupported type %d for copier %s", 2168 swidget->id, swidget->widget->name); 2169 return -EINVAL; 2170 } 2171 2172 /* set input and output audio formats */ 2173 input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, 2174 &copier_data->base_config, 2175 ref_params, available_fmt); 2176 if (input_fmt_index < 0) 2177 return input_fmt_index; 2178 2179 /* set the reference params for output format selection */ 2180 single_output_bitdepth = sof_ipc4_copier_is_single_bitdepth(sdev, 2181 available_fmt->output_pin_fmts, 2182 available_fmt->num_output_formats); 2183 switch (swidget->id) { 2184 case snd_soc_dapm_aif_in: 2185 case snd_soc_dapm_dai_out: 2186 case snd_soc_dapm_buffer: 2187 { 2188 struct sof_ipc4_audio_format *in_fmt; 2189 2190 in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; 2191 out_ref_rate = in_fmt->sampling_frequency; 2192 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 2193 out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); 2194 2195 if (!single_output_bitdepth) 2196 out_ref_valid_bits = 2197 SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 2198 break; 2199 } 2200 case snd_soc_dapm_aif_out: 2201 case snd_soc_dapm_dai_in: 2202 out_ref_rate = params_rate(fe_params); 2203 out_ref_channels = params_channels(fe_params); 2204 ret = sof_ipc4_get_sample_type(sdev, fe_params); 2205 if (ret < 0) 2206 return ret; 2207 out_ref_type = (u32)ret; 2208 2209 if (!single_output_bitdepth) { 2210 out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); 2211 if (out_ref_valid_bits < 0) 2212 return out_ref_valid_bits; 2213 } 2214 break; 2215 default: 2216 /* 2217 * Unsupported type should be caught by the former switch default 2218 * case, this should never happen in reality. 2219 */ 2220 return -EINVAL; 2221 } 2222 2223 /* 2224 * if the output format is the same across all available output formats, choose 2225 * that as the reference. 2226 */ 2227 if (single_output_bitdepth) { 2228 struct sof_ipc4_audio_format *out_fmt; 2229 2230 out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; 2231 out_ref_valid_bits = 2232 SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); 2233 out_ref_type = sof_ipc4_fmt_cfg_to_type(out_fmt->fmt_cfg); 2234 } 2235 2236 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, 2237 &copier_data->base_config, 2238 available_fmt, out_ref_rate, 2239 out_ref_channels, out_ref_valid_bits, 2240 out_ref_type); 2241 if (output_fmt_index < 0) 2242 return output_fmt_index; 2243 2244 /* 2245 * Set the output format. Current topology defines pin 0 input and output formats in pairs. 2246 * This assumes that the pin 0 formats are defined before all other pins. 2247 * So pick the output audio format with the same index as the chosen 2248 * input format. This logic will need to be updated when the format definitions 2249 * in topology change. 2250 */ 2251 memcpy(&copier_data->out_format, 2252 &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt, 2253 sizeof(struct sof_ipc4_audio_format)); 2254 2255 switch (swidget->id) { 2256 case snd_soc_dapm_dai_in: 2257 case snd_soc_dapm_dai_out: 2258 { 2259 /* 2260 * Only SOF_DAI_INTEL_ALH needs copier_data to set blob. 2261 * That's why only ALH dai's blob is set after sof_ipc4_init_input_audio_fmt 2262 */ 2263 if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { 2264 struct sof_ipc4_alh_configuration_blob *blob; 2265 struct sof_ipc4_dma_config *dma_config; 2266 struct sof_ipc4_copier_data *alh_data; 2267 struct sof_ipc4_copier *alh_copier; 2268 struct snd_sof_widget *w; 2269 u32 ch_count = 0; 2270 u32 ch_mask = 0; 2271 u32 ch_map; 2272 u32 step; 2273 u32 mask; 2274 2275 blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; 2276 2277 blob->gw_attr.lp_buffer_alloc = 0; 2278 2279 /* Get channel_mask from ch_map */ 2280 ch_map = copier_data->base_config.audio_fmt.ch_map; 2281 for (i = 0; ch_map; i++) { 2282 if ((ch_map & 0xf) != 0xf) { 2283 ch_mask |= BIT(i); 2284 ch_count++; 2285 } 2286 ch_map >>= 4; 2287 } 2288 2289 if (swidget->id == snd_soc_dapm_dai_in && ch_count == out_ref_channels) { 2290 /* 2291 * For playback DAI widgets where the channel number is equal to 2292 * the output reference channels, set the step = 0 to ensure all 2293 * the ch_mask is applied to all alh mappings. 2294 */ 2295 mask = ch_mask; 2296 step = 0; 2297 } else { 2298 step = ch_count / blob->alh_cfg.device_count; 2299 mask = GENMASK(step - 1, 0); 2300 } 2301 2302 /* 2303 * Set each gtw_cfg.node_id to blob->alh_cfg.mapping[] 2304 * for all widgets with the same stream name 2305 */ 2306 i = 0; 2307 list_for_each_entry(w, &sdev->widget_list, list) { 2308 u32 node_type; 2309 2310 if (!WIDGET_IS_DAI(w->id) || !w->widget->sname || 2311 strcmp(w->widget->sname, swidget->widget->sname)) 2312 continue; 2313 2314 dai = w->private; 2315 if (dai->type != SOF_DAI_INTEL_ALH) 2316 continue; 2317 alh_copier = (struct sof_ipc4_copier *)dai->private; 2318 alh_data = &alh_copier->data; 2319 node_type = SOF_IPC4_GET_NODE_TYPE(alh_data->gtw_cfg.node_id); 2320 blob->alh_cfg.mapping[i].device = SOF_IPC4_NODE_TYPE(node_type); 2321 blob->alh_cfg.mapping[i].device |= 2322 SOF_IPC4_NODE_INDEX(alh_copier->dai_index); 2323 2324 /* 2325 * The mapping[i] device in ALH blob should be the same as the 2326 * dma_config_tlv[i] mapping device if a dma_config_tlv is present. 2327 * The device id will be used for DMA tlv mapping purposes. 2328 */ 2329 if (ipc4_copier->dma_config_tlv[i].length) { 2330 dma_config = &ipc4_copier->dma_config_tlv[i].dma_config; 2331 blob->alh_cfg.mapping[i].device = 2332 dma_config->dma_stream_channel_map.mapping[0].device; 2333 } 2334 2335 /* 2336 * Set the same channel mask if the widget channel count is the same 2337 * as the FE channels for playback as the audio data is duplicated 2338 * for all speakers in this case. Otherwise, split the channels 2339 * among the aggregated DAIs. For example, with 4 channels on 2 2340 * aggregated DAIs, the channel_mask should be 0x3 and 0xc for the 2341 * two DAI's. 2342 * The channel masks used depend on the cpu_dais used in the 2343 * dailink at the machine driver level, which actually comes from 2344 * the tables in soc_acpi files depending on the _ADR and devID 2345 * registers for each codec. 2346 */ 2347 blob->alh_cfg.mapping[i].channel_mask = mask << (step * i); 2348 2349 i++; 2350 } 2351 if (blob->alh_cfg.device_count > 1) { 2352 int group_id; 2353 2354 group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1, 2355 GFP_KERNEL); 2356 2357 if (group_id < 0) 2358 return group_id; 2359 2360 /* add multi-gateway base */ 2361 group_id += ALH_MULTI_GTW_BASE; 2362 copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 2363 copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(group_id); 2364 } 2365 } 2366 } 2367 } 2368 2369 /* modify the input params for the next widget */ 2370 ret = sof_ipc4_update_hw_params(sdev, pipeline_params, 2371 &copier_data->out_format, 2372 BIT(SNDRV_PCM_HW_PARAM_FORMAT) | 2373 BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | 2374 BIT(SNDRV_PCM_HW_PARAM_RATE)); 2375 if (ret) 2376 return ret; 2377 2378 /* 2379 * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the 2380 * deep buffer case, set the dma_buffer_size depending on the deep_buffer_dma_ms set 2381 * in topology. 2382 */ 2383 switch (swidget->id) { 2384 case snd_soc_dapm_dai_in: 2385 copier_data->gtw_cfg.dma_buffer_size = 2386 SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.ibs; 2387 break; 2388 case snd_soc_dapm_aif_in: 2389 copier_data->gtw_cfg.dma_buffer_size = 2390 max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) * 2391 copier_data->base_config.ibs; 2392 dev_dbg(sdev->dev, "copier %s, dma buffer%s: %u ms (%u bytes)", 2393 swidget->widget->name, 2394 deep_buffer_dma_ms ? " (using Deep Buffer)" : "", 2395 max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms), 2396 copier_data->gtw_cfg.dma_buffer_size); 2397 break; 2398 case snd_soc_dapm_dai_out: 2399 case snd_soc_dapm_aif_out: 2400 copier_data->gtw_cfg.dma_buffer_size = 2401 SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs; 2402 break; 2403 default: 2404 break; 2405 } 2406 2407 data = &ipc4_copier->copier_config; 2408 ipc_config_size = &ipc4_copier->ipc_config_size; 2409 ipc_config_data = &ipc4_copier->ipc_config_data; 2410 2411 /* config_length is DWORD based */ 2412 gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4; 2413 ipc_size = sizeof(*copier_data) + gtw_cfg_config_length; 2414 2415 dma_config_tlv_size = 0; 2416 for (i = 0; i < SOF_IPC4_DMA_DEVICE_MAX_COUNT; i++) { 2417 if (ipc4_copier->dma_config_tlv[i].type != SOF_IPC4_GTW_DMA_CONFIG_ID) 2418 continue; 2419 dma_config_tlv_size += ipc4_copier->dma_config_tlv[i].length; 2420 dma_config_tlv_size += 2421 ipc4_copier->dma_config_tlv[i].dma_config.dma_priv_config_size; 2422 dma_config_tlv_size += (sizeof(ipc4_copier->dma_config_tlv[i]) - 2423 sizeof(ipc4_copier->dma_config_tlv[i].dma_config)); 2424 } 2425 2426 if (dma_config_tlv_size) { 2427 ipc_size += dma_config_tlv_size; 2428 2429 /* we also need to increase the size at the gtw level */ 2430 copier_data->gtw_cfg.config_length += dma_config_tlv_size / 4; 2431 } 2432 2433 dev_dbg(sdev->dev, "copier %s, IPC size is %d", swidget->widget->name, ipc_size); 2434 2435 *ipc_config_data = kzalloc(ipc_size, GFP_KERNEL); 2436 if (!*ipc_config_data) 2437 return -ENOMEM; 2438 2439 *ipc_config_size = ipc_size; 2440 2441 sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, 2442 input_fmt_index, output_fmt_index); 2443 2444 /* update pipeline memory usage */ 2445 sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config); 2446 2447 /* copy IPC data */ 2448 memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data)); 2449 if (gtw_cfg_config_length) 2450 memcpy(*ipc_config_data + sizeof(*copier_data), 2451 *data, gtw_cfg_config_length); 2452 2453 /* add DMA Config TLV, if configured */ 2454 if (dma_config_tlv_size) 2455 memcpy(*ipc_config_data + sizeof(*copier_data) + 2456 gtw_cfg_config_length, 2457 &ipc4_copier->dma_config_tlv, dma_config_tlv_size); 2458 2459 /* 2460 * Restore gateway config length now that IPC payload is prepared. This avoids 2461 * counting the DMA CONFIG TLV multiple times 2462 */ 2463 copier_data->gtw_cfg.config_length = gtw_cfg_config_length / 4; 2464 2465 return 0; 2466 } 2467 2468 static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, 2469 struct snd_pcm_hw_params *fe_params, 2470 struct snd_sof_platform_stream_params *platform_params, 2471 struct snd_pcm_hw_params *pipeline_params, int dir) 2472 { 2473 struct snd_soc_component *scomp = swidget->scomp; 2474 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2475 struct sof_ipc4_gain *gain = swidget->private; 2476 struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; 2477 struct sof_ipc4_audio_format *in_fmt; 2478 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; 2479 int input_fmt_index, output_fmt_index; 2480 2481 input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, 2482 &gain->data.base_config, 2483 pipeline_params, 2484 available_fmt); 2485 if (input_fmt_index < 0) 2486 return input_fmt_index; 2487 2488 in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; 2489 out_ref_rate = in_fmt->sampling_frequency; 2490 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 2491 out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 2492 out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); 2493 2494 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, 2495 &gain->data.base_config, 2496 available_fmt, 2497 out_ref_rate, 2498 out_ref_channels, 2499 out_ref_valid_bits, 2500 out_ref_type); 2501 if (output_fmt_index < 0) 2502 return output_fmt_index; 2503 2504 sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, 2505 input_fmt_index, output_fmt_index); 2506 2507 /* update pipeline memory usage */ 2508 sof_ipc4_update_resource_usage(sdev, swidget, &gain->data.base_config); 2509 2510 return 0; 2511 } 2512 2513 static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, 2514 struct snd_pcm_hw_params *fe_params, 2515 struct snd_sof_platform_stream_params *platform_params, 2516 struct snd_pcm_hw_params *pipeline_params, int dir) 2517 { 2518 struct snd_soc_component *scomp = swidget->scomp; 2519 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2520 struct sof_ipc4_mixer *mixer = swidget->private; 2521 struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; 2522 struct sof_ipc4_audio_format *in_fmt; 2523 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; 2524 int input_fmt_index, output_fmt_index; 2525 2526 input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, 2527 &mixer->base_config, 2528 pipeline_params, 2529 available_fmt); 2530 if (input_fmt_index < 0) 2531 return input_fmt_index; 2532 2533 in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; 2534 out_ref_rate = in_fmt->sampling_frequency; 2535 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 2536 out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 2537 out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); 2538 2539 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, 2540 &mixer->base_config, 2541 available_fmt, 2542 out_ref_rate, 2543 out_ref_channels, 2544 out_ref_valid_bits, 2545 out_ref_type); 2546 if (output_fmt_index < 0) 2547 return output_fmt_index; 2548 2549 sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, 2550 input_fmt_index, output_fmt_index); 2551 2552 /* update pipeline memory usage */ 2553 sof_ipc4_update_resource_usage(sdev, swidget, &mixer->base_config); 2554 2555 return 0; 2556 } 2557 2558 static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, 2559 struct snd_pcm_hw_params *fe_params, 2560 struct snd_sof_platform_stream_params *platform_params, 2561 struct snd_pcm_hw_params *pipeline_params, int dir) 2562 { 2563 struct snd_soc_component *scomp = swidget->scomp; 2564 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2565 struct sof_ipc4_src *src = swidget->private; 2566 struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; 2567 struct sof_ipc4_audio_format *out_audio_fmt; 2568 struct sof_ipc4_audio_format *in_audio_fmt; 2569 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type; 2570 int output_fmt_index, input_fmt_index; 2571 2572 input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, 2573 &src->data.base_config, 2574 pipeline_params, 2575 available_fmt); 2576 if (input_fmt_index < 0) 2577 return input_fmt_index; 2578 2579 /* 2580 * For playback, the SRC sink rate will be configured based on the requested output 2581 * format, which is restricted to only deal with DAI's with a single format for now. 2582 */ 2583 if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) { 2584 dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n", 2585 available_fmt->num_output_formats, swidget->widget->name); 2586 return -EINVAL; 2587 } 2588 2589 /* 2590 * SRC does not perform format conversion, so the output channels and valid bit depth must 2591 * be the same as that of the input. 2592 */ 2593 in_audio_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; 2594 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg); 2595 out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); 2596 out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg); 2597 2598 /* 2599 * For capture, the SRC module should convert the rate to match the rate requested by the 2600 * PCM hw_params. Set the reference params based on the fe_params unconditionally as it 2601 * will be ignored for playback anyway. 2602 */ 2603 out_ref_rate = params_rate(fe_params); 2604 2605 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, 2606 &src->data.base_config, 2607 available_fmt, 2608 out_ref_rate, 2609 out_ref_channels, 2610 out_ref_valid_bits, 2611 out_ref_type); 2612 if (output_fmt_index < 0) 2613 return output_fmt_index; 2614 2615 sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, 2616 input_fmt_index, output_fmt_index); 2617 2618 /* update pipeline memory usage */ 2619 sof_ipc4_update_resource_usage(sdev, swidget, &src->data.base_config); 2620 2621 out_audio_fmt = &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt; 2622 src->data.sink_rate = out_audio_fmt->sampling_frequency; 2623 2624 /* update pipeline_params for sink widgets */ 2625 return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt, 2626 BIT(SNDRV_PCM_HW_PARAM_FORMAT) | 2627 BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | 2628 BIT(SNDRV_PCM_HW_PARAM_RATE)); 2629 } 2630 2631 static int 2632 sof_ipc4_process_set_pin_formats(struct snd_sof_widget *swidget, int pin_type) 2633 { 2634 struct sof_ipc4_process *process = swidget->private; 2635 struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; 2636 struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; 2637 struct sof_ipc4_pin_format *pin_format, *format_list_to_search; 2638 struct snd_soc_component *scomp = swidget->scomp; 2639 int num_pins, format_list_count; 2640 int pin_format_offset = 0; 2641 int i, j; 2642 2643 /* set number of pins, offset of pin format and format list to search based on pin type */ 2644 if (pin_type == SOF_PIN_TYPE_INPUT) { 2645 num_pins = swidget->num_input_pins; 2646 format_list_to_search = available_fmt->input_pin_fmts; 2647 format_list_count = available_fmt->num_input_formats; 2648 } else { 2649 num_pins = swidget->num_output_pins; 2650 pin_format_offset = swidget->num_input_pins; 2651 format_list_to_search = available_fmt->output_pin_fmts; 2652 format_list_count = available_fmt->num_output_formats; 2653 } 2654 2655 for (i = pin_format_offset; i < num_pins + pin_format_offset; i++) { 2656 pin_format = &base_cfg_ext->pin_formats[i]; 2657 2658 /* Pin 0 audio formats are derived from the base config input/output format */ 2659 if (i == pin_format_offset) { 2660 if (pin_type == SOF_PIN_TYPE_INPUT) { 2661 pin_format->buffer_size = process->base_config.ibs; 2662 pin_format->audio_fmt = process->base_config.audio_fmt; 2663 } else { 2664 pin_format->buffer_size = process->base_config.obs; 2665 pin_format->audio_fmt = process->output_format; 2666 } 2667 continue; 2668 } 2669 2670 /* 2671 * For all other pins, find the pin formats from those set in topology. If there 2672 * is more than one format specified for a pin, this will pick the first available 2673 * one. 2674 */ 2675 for (j = 0; j < format_list_count; j++) { 2676 struct sof_ipc4_pin_format *pin_format_item = &format_list_to_search[j]; 2677 2678 if (pin_format_item->pin_index == i - pin_format_offset) { 2679 *pin_format = *pin_format_item; 2680 break; 2681 } 2682 } 2683 2684 if (j == format_list_count) { 2685 dev_err(scomp->dev, "%s pin %d format not found for %s\n", 2686 (pin_type == SOF_PIN_TYPE_INPUT) ? "input" : "output", 2687 i - pin_format_offset, swidget->widget->name); 2688 return -EINVAL; 2689 } 2690 } 2691 2692 return 0; 2693 } 2694 2695 static int sof_ipc4_process_add_base_cfg_extn(struct snd_sof_widget *swidget) 2696 { 2697 int ret, i; 2698 2699 /* copy input and output pin formats */ 2700 for (i = 0; i <= SOF_PIN_TYPE_OUTPUT; i++) { 2701 ret = sof_ipc4_process_set_pin_formats(swidget, i); 2702 if (ret < 0) 2703 return ret; 2704 } 2705 2706 return 0; 2707 } 2708 2709 static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, 2710 struct snd_pcm_hw_params *fe_params, 2711 struct snd_sof_platform_stream_params *platform_params, 2712 struct snd_pcm_hw_params *pipeline_params, int dir) 2713 { 2714 struct snd_soc_component *scomp = swidget->scomp; 2715 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 2716 struct sof_ipc4_process *process = swidget->private; 2717 struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; 2718 void *cfg = process->ipc_config_data; 2719 int output_fmt_index = 0; 2720 int input_fmt_index = 0; 2721 int ret; 2722 2723 input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, 2724 &process->base_config, 2725 pipeline_params, 2726 available_fmt); 2727 if (input_fmt_index < 0) 2728 return input_fmt_index; 2729 2730 /* Configure output audio format only if the module supports output */ 2731 if (available_fmt->num_output_formats) { 2732 struct sof_ipc4_audio_format *in_fmt; 2733 struct sof_ipc4_pin_format *pin_fmt; 2734 u32 out_ref_rate, out_ref_channels; 2735 int out_ref_valid_bits, out_ref_type; 2736 2737 in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt; 2738 2739 out_ref_rate = in_fmt->sampling_frequency; 2740 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 2741 out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 2742 out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg); 2743 2744 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, 2745 &process->base_config, 2746 available_fmt, 2747 out_ref_rate, 2748 out_ref_channels, 2749 out_ref_valid_bits, 2750 out_ref_type); 2751 if (output_fmt_index < 0) 2752 return output_fmt_index; 2753 2754 pin_fmt = &available_fmt->output_pin_fmts[output_fmt_index]; 2755 2756 /* copy Pin output format for Pin 0 only */ 2757 if (pin_fmt->pin_index == 0) { 2758 memcpy(&process->output_format, &pin_fmt->audio_fmt, 2759 sizeof(struct sof_ipc4_audio_format)); 2760 2761 /* modify the pipeline params with the output format */ 2762 ret = sof_ipc4_update_hw_params(sdev, pipeline_params, 2763 &process->output_format, 2764 BIT(SNDRV_PCM_HW_PARAM_FORMAT) | 2765 BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | 2766 BIT(SNDRV_PCM_HW_PARAM_RATE)); 2767 if (ret) 2768 return ret; 2769 } 2770 } 2771 2772 sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt, 2773 input_fmt_index, output_fmt_index); 2774 2775 /* update pipeline memory usage */ 2776 sof_ipc4_update_resource_usage(sdev, swidget, &process->base_config); 2777 2778 /* ipc_config_data is composed of the base_config followed by an optional extension */ 2779 memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg)); 2780 cfg += sizeof(struct sof_ipc4_base_module_cfg); 2781 2782 if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) { 2783 struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; 2784 2785 ret = sof_ipc4_process_add_base_cfg_extn(swidget); 2786 if (ret < 0) 2787 return ret; 2788 2789 memcpy(cfg, base_cfg_ext, process->base_config_ext_size); 2790 } 2791 2792 return 0; 2793 } 2794 2795 static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 2796 { 2797 struct sof_ipc4_control_data *control_data; 2798 struct sof_ipc4_msg *msg; 2799 int i; 2800 2801 scontrol->size = struct_size(control_data, chanv, scontrol->num_channels); 2802 2803 /* scontrol->ipc_control_data will be freed in sof_control_unload */ 2804 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 2805 if (!scontrol->ipc_control_data) 2806 return -ENOMEM; 2807 2808 control_data = scontrol->ipc_control_data; 2809 control_data->index = scontrol->index; 2810 2811 msg = &control_data->msg; 2812 msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); 2813 msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 2814 msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 2815 2816 /* volume controls with range 0-1 (off/on) are switch controls */ 2817 if (scontrol->max == 1) 2818 msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_SWITCH_CONTROL_PARAM_ID); 2819 else 2820 msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_GAIN_PARAM_ID); 2821 2822 for (i = 0; i < scontrol->num_channels; i++) { 2823 control_data->chanv[i].channel = i; 2824 /* 2825 * Default, initial values: 2826 * - 0dB for volume controls 2827 * - off (0) for switch controls - value already zero after 2828 * memory allocation 2829 */ 2830 if (scontrol->max > 1) 2831 control_data->chanv[i].value = SOF_IPC4_VOL_ZERO_DB; 2832 } 2833 2834 return 0; 2835 } 2836 2837 static int sof_ipc4_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 2838 { 2839 struct sof_ipc4_control_data *control_data; 2840 struct sof_ipc4_msg *msg; 2841 int i; 2842 2843 scontrol->size = struct_size(control_data, chanv, scontrol->num_channels); 2844 2845 /* scontrol->ipc_control_data will be freed in sof_control_unload */ 2846 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 2847 if (!scontrol->ipc_control_data) 2848 return -ENOMEM; 2849 2850 control_data = scontrol->ipc_control_data; 2851 control_data->index = scontrol->index; 2852 2853 msg = &control_data->msg; 2854 msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); 2855 msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 2856 msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 2857 2858 msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_ENUM_CONTROL_PARAM_ID); 2859 2860 /* Default, initial value for enums: first enum entry is selected (0) */ 2861 for (i = 0; i < scontrol->num_channels; i++) 2862 control_data->chanv[i].channel = i; 2863 2864 return 0; 2865 } 2866 2867 static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 2868 { 2869 struct sof_ipc4_control_data *control_data; 2870 struct sof_ipc4_msg *msg; 2871 int ret; 2872 2873 if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) { 2874 dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", 2875 scontrol->name, scontrol->max_size); 2876 return -EINVAL; 2877 } 2878 2879 if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { 2880 dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", 2881 scontrol->name, scontrol->priv_size, 2882 scontrol->max_size - sizeof(*control_data)); 2883 return -EINVAL; 2884 } 2885 2886 scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size; 2887 2888 scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); 2889 if (!scontrol->ipc_control_data) 2890 return -ENOMEM; 2891 2892 control_data = scontrol->ipc_control_data; 2893 control_data->index = scontrol->index; 2894 if (scontrol->priv_size > 0) { 2895 memcpy(control_data->data, scontrol->priv, scontrol->priv_size); 2896 kfree(scontrol->priv); 2897 scontrol->priv = NULL; 2898 2899 if (control_data->data->magic != SOF_IPC4_ABI_MAGIC) { 2900 dev_err(sdev->dev, "Wrong ABI magic (%#x) for control: %s\n", 2901 control_data->data->magic, scontrol->name); 2902 ret = -EINVAL; 2903 goto err; 2904 } 2905 2906 /* TODO: check the ABI version */ 2907 2908 if (control_data->data->size + sizeof(struct sof_abi_hdr) != 2909 scontrol->priv_size) { 2910 dev_err(sdev->dev, "Control %s conflict in bytes %zu vs. priv size %zu.\n", 2911 scontrol->name, 2912 control_data->data->size + sizeof(struct sof_abi_hdr), 2913 scontrol->priv_size); 2914 ret = -EINVAL; 2915 goto err; 2916 } 2917 } 2918 2919 msg = &control_data->msg; 2920 msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); 2921 msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 2922 msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 2923 2924 return 0; 2925 2926 err: 2927 kfree(scontrol->ipc_control_data); 2928 scontrol->ipc_control_data = NULL; 2929 return ret; 2930 } 2931 2932 static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 2933 { 2934 switch (scontrol->info_type) { 2935 case SND_SOC_TPLG_CTL_VOLSW: 2936 case SND_SOC_TPLG_CTL_VOLSW_SX: 2937 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 2938 return sof_ipc4_control_load_volume(sdev, scontrol); 2939 case SND_SOC_TPLG_CTL_BYTES: 2940 return sof_ipc4_control_load_bytes(sdev, scontrol); 2941 case SND_SOC_TPLG_CTL_ENUM: 2942 case SND_SOC_TPLG_CTL_ENUM_VALUE: 2943 return sof_ipc4_control_load_enum(sdev, scontrol); 2944 default: 2945 break; 2946 } 2947 2948 return 0; 2949 } 2950 2951 static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 2952 { 2953 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 2954 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 2955 struct sof_ipc4_pipeline *pipeline; 2956 struct sof_ipc4_msg *msg; 2957 void *ipc_data = NULL; 2958 u32 ipc_size = 0; 2959 int ret; 2960 2961 switch (swidget->id) { 2962 case snd_soc_dapm_scheduler: 2963 pipeline = swidget->private; 2964 2965 if (pipeline->use_chain_dma) { 2966 dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", 2967 swidget->widget->name); 2968 return 0; 2969 } 2970 2971 dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id, 2972 pipeline->mem_usage); 2973 2974 msg = &pipeline->msg; 2975 msg->primary |= pipeline->mem_usage; 2976 2977 swidget->instance_id = ida_alloc_max(&pipeline_ida, ipc4_data->max_num_pipelines, 2978 GFP_KERNEL); 2979 if (swidget->instance_id < 0) { 2980 dev_err(sdev->dev, "failed to assign pipeline id for %s: %d\n", 2981 swidget->widget->name, swidget->instance_id); 2982 return swidget->instance_id; 2983 } 2984 msg->primary &= ~SOF_IPC4_GLB_PIPE_INSTANCE_MASK; 2985 msg->primary |= SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); 2986 break; 2987 case snd_soc_dapm_aif_in: 2988 case snd_soc_dapm_aif_out: 2989 case snd_soc_dapm_buffer: 2990 { 2991 struct sof_ipc4_copier *ipc4_copier = swidget->private; 2992 2993 pipeline = pipe_widget->private; 2994 if (pipeline->use_chain_dma) 2995 return 0; 2996 2997 ipc_size = ipc4_copier->ipc_config_size; 2998 ipc_data = ipc4_copier->ipc_config_data; 2999 3000 msg = &ipc4_copier->msg; 3001 break; 3002 } 3003 case snd_soc_dapm_dai_in: 3004 case snd_soc_dapm_dai_out: 3005 { 3006 struct snd_sof_dai *dai = swidget->private; 3007 struct sof_ipc4_copier *ipc4_copier = dai->private; 3008 3009 pipeline = pipe_widget->private; 3010 if (pipeline->use_chain_dma) 3011 return 0; 3012 3013 ipc_size = ipc4_copier->ipc_config_size; 3014 ipc_data = ipc4_copier->ipc_config_data; 3015 3016 msg = &ipc4_copier->msg; 3017 break; 3018 } 3019 case snd_soc_dapm_pga: 3020 { 3021 struct sof_ipc4_gain *gain = swidget->private; 3022 3023 ipc_size = sizeof(gain->data); 3024 ipc_data = &gain->data; 3025 3026 msg = &gain->msg; 3027 break; 3028 } 3029 case snd_soc_dapm_mixer: 3030 { 3031 struct sof_ipc4_mixer *mixer = swidget->private; 3032 3033 ipc_size = sizeof(mixer->base_config); 3034 ipc_data = &mixer->base_config; 3035 3036 msg = &mixer->msg; 3037 break; 3038 } 3039 case snd_soc_dapm_src: 3040 { 3041 struct sof_ipc4_src *src = swidget->private; 3042 3043 ipc_size = sizeof(src->data); 3044 ipc_data = &src->data; 3045 3046 msg = &src->msg; 3047 break; 3048 } 3049 case snd_soc_dapm_asrc: 3050 { 3051 struct sof_ipc4_asrc *asrc = swidget->private; 3052 3053 ipc_size = sizeof(asrc->data); 3054 ipc_data = &asrc->data; 3055 3056 msg = &asrc->msg; 3057 break; 3058 } 3059 case snd_soc_dapm_effect: 3060 { 3061 struct sof_ipc4_process *process = swidget->private; 3062 3063 if (!process->ipc_config_size) { 3064 dev_err(sdev->dev, "module %s has no config data!\n", 3065 swidget->widget->name); 3066 return -EINVAL; 3067 } 3068 3069 ipc_size = process->ipc_config_size; 3070 ipc_data = process->ipc_config_data; 3071 3072 msg = &process->msg; 3073 break; 3074 } 3075 default: 3076 dev_err(sdev->dev, "widget type %d not supported", swidget->id); 3077 return -EINVAL; 3078 } 3079 3080 if (swidget->id != snd_soc_dapm_scheduler) { 3081 int module_id = msg->primary & SOF_IPC4_MOD_ID_MASK; 3082 3083 ret = sof_ipc4_widget_assign_instance_id(sdev, swidget); 3084 if (ret < 0) { 3085 dev_err(sdev->dev, "failed to assign instance id for %s\n", 3086 swidget->widget->name); 3087 return ret; 3088 } 3089 3090 msg->primary &= ~SOF_IPC4_MOD_INSTANCE_MASK; 3091 msg->primary |= SOF_IPC4_MOD_INSTANCE(swidget->instance_id); 3092 3093 msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK; 3094 msg->extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(ipc_size >> 2); 3095 3096 msg->extension &= ~SOF_IPC4_MOD_EXT_PPL_ID_MASK; 3097 msg->extension |= SOF_IPC4_MOD_EXT_PPL_ID(pipe_widget->instance_id); 3098 3099 dev_dbg(sdev->dev, "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n", 3100 swidget->widget->name, swidget->pipeline_id, module_id, 3101 swidget->instance_id, swidget->core); 3102 } else { 3103 dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n", 3104 swidget->widget->name, swidget->pipeline_id, 3105 swidget->instance_id, swidget->core); 3106 } 3107 3108 msg->data_size = ipc_size; 3109 msg->data_ptr = ipc_data; 3110 3111 ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size); 3112 if (ret < 0) { 3113 dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name); 3114 3115 if (swidget->id != snd_soc_dapm_scheduler) { 3116 struct sof_ipc4_fw_module *fw_module = swidget->module_info; 3117 3118 ida_free(&fw_module->m_ida, swidget->instance_id); 3119 } else { 3120 ida_free(&pipeline_ida, swidget->instance_id); 3121 } 3122 } 3123 3124 return ret; 3125 } 3126 3127 static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 3128 { 3129 struct sof_ipc4_fw_module *fw_module = swidget->module_info; 3130 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 3131 int ret = 0; 3132 3133 mutex_lock(&ipc4_data->pipeline_state_mutex); 3134 3135 /* freeing a pipeline frees all the widgets associated with it */ 3136 if (swidget->id == snd_soc_dapm_scheduler) { 3137 struct sof_ipc4_pipeline *pipeline = swidget->private; 3138 struct sof_ipc4_msg msg = {{ 0 }}; 3139 u32 header; 3140 3141 if (pipeline->use_chain_dma) { 3142 dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", 3143 swidget->widget->name); 3144 mutex_unlock(&ipc4_data->pipeline_state_mutex); 3145 return 0; 3146 } 3147 3148 header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); 3149 header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE); 3150 header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 3151 header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); 3152 3153 msg.primary = header; 3154 3155 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); 3156 if (ret < 0) 3157 dev_err(sdev->dev, "failed to free pipeline widget %s\n", 3158 swidget->widget->name); 3159 3160 pipeline->mem_usage = 0; 3161 pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; 3162 ida_free(&pipeline_ida, swidget->instance_id); 3163 swidget->instance_id = -EINVAL; 3164 } else { 3165 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 3166 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 3167 3168 if (!pipeline->use_chain_dma) 3169 ida_free(&fw_module->m_ida, swidget->instance_id); 3170 } 3171 3172 mutex_unlock(&ipc4_data->pipeline_state_mutex); 3173 3174 return ret; 3175 } 3176 3177 static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, 3178 struct snd_sof_widget *sink_widget, bool pin_type) 3179 { 3180 struct snd_sof_widget *current_swidget; 3181 struct snd_soc_component *scomp; 3182 struct ida *queue_ida; 3183 const char *buddy_name; 3184 char **pin_binding; 3185 u32 num_pins; 3186 int i; 3187 3188 if (pin_type == SOF_PIN_TYPE_OUTPUT) { 3189 current_swidget = src_widget; 3190 pin_binding = src_widget->output_pin_binding; 3191 queue_ida = &src_widget->output_queue_ida; 3192 num_pins = src_widget->num_output_pins; 3193 buddy_name = sink_widget->widget->name; 3194 } else { 3195 current_swidget = sink_widget; 3196 pin_binding = sink_widget->input_pin_binding; 3197 queue_ida = &sink_widget->input_queue_ida; 3198 num_pins = sink_widget->num_input_pins; 3199 buddy_name = src_widget->widget->name; 3200 } 3201 3202 scomp = current_swidget->scomp; 3203 3204 if (num_pins < 1) { 3205 dev_err(scomp->dev, "invalid %s num_pins: %d for queue allocation for %s\n", 3206 (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), 3207 num_pins, current_swidget->widget->name); 3208 return -EINVAL; 3209 } 3210 3211 /* If there is only one input/output pin, queue id must be 0 */ 3212 if (num_pins == 1) 3213 return 0; 3214 3215 /* Allocate queue ID from pin binding array if it is defined in topology. */ 3216 if (pin_binding) { 3217 for (i = 0; i < num_pins; i++) { 3218 if (!strcmp(pin_binding[i], buddy_name)) 3219 return i; 3220 } 3221 /* 3222 * Fail if no queue ID found from pin binding array, so that we don't 3223 * mixed use pin binding array and ida for queue ID allocation. 3224 */ 3225 dev_err(scomp->dev, "no %s queue id found from pin binding array for %s\n", 3226 (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), 3227 current_swidget->widget->name); 3228 return -EINVAL; 3229 } 3230 3231 /* If no pin binding array specified in topology, use ida to allocate one */ 3232 return ida_alloc_max(queue_ida, num_pins, GFP_KERNEL); 3233 } 3234 3235 static void sof_ipc4_put_queue_id(struct snd_sof_widget *swidget, int queue_id, 3236 bool pin_type) 3237 { 3238 struct ida *queue_ida; 3239 char **pin_binding; 3240 int num_pins; 3241 3242 if (pin_type == SOF_PIN_TYPE_OUTPUT) { 3243 pin_binding = swidget->output_pin_binding; 3244 queue_ida = &swidget->output_queue_ida; 3245 num_pins = swidget->num_output_pins; 3246 } else { 3247 pin_binding = swidget->input_pin_binding; 3248 queue_ida = &swidget->input_queue_ida; 3249 num_pins = swidget->num_input_pins; 3250 } 3251 3252 /* Nothing to free if queue ID is not allocated with ida. */ 3253 if (num_pins == 1 || pin_binding) 3254 return; 3255 3256 ida_free(queue_ida, queue_id); 3257 } 3258 3259 static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, 3260 struct snd_sof_widget *src_widget, 3261 struct snd_sof_widget *sink_widget, 3262 struct snd_sof_route *sroute) 3263 { 3264 struct sof_ipc4_copier_config_set_sink_format format; 3265 const struct sof_ipc_ops *iops = sdev->ipc->ops; 3266 struct sof_ipc4_base_module_cfg *src_config; 3267 const struct sof_ipc4_audio_format *pin_fmt; 3268 struct sof_ipc4_fw_module *fw_module; 3269 struct sof_ipc4_msg msg = {{ 0 }}; 3270 3271 if (WIDGET_IS_DAI(src_widget->id)) { 3272 struct snd_sof_dai *dai = src_widget->private; 3273 3274 src_config = dai->private; 3275 } else { 3276 src_config = src_widget->private; 3277 } 3278 3279 fw_module = src_widget->module_info; 3280 3281 format.sink_id = sroute->src_queue_id; 3282 memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt)); 3283 3284 pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sroute->dst_queue_id); 3285 if (!pin_fmt) { 3286 dev_err(sdev->dev, 3287 "Failed to get input audio format of %s:%d for output of %s:%d\n", 3288 sink_widget->widget->name, sroute->dst_queue_id, 3289 src_widget->widget->name, sroute->src_queue_id); 3290 return -EINVAL; 3291 } 3292 3293 memcpy(&format.sink_fmt, pin_fmt, sizeof(format.sink_fmt)); 3294 3295 msg.data_size = sizeof(format); 3296 msg.data_ptr = &format; 3297 3298 msg.primary = fw_module->man4_module_entry.id; 3299 msg.primary |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id); 3300 msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 3301 msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 3302 3303 msg.extension = 3304 SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT); 3305 3306 return iops->set_get_data(sdev, &msg, msg.data_size, true); 3307 } 3308 3309 static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) 3310 { 3311 struct snd_sof_widget *src_widget = sroute->src_widget; 3312 struct snd_sof_widget *sink_widget = sroute->sink_widget; 3313 struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; 3314 struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; 3315 struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; 3316 struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; 3317 struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; 3318 struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; 3319 struct sof_ipc4_msg msg = {{ 0 }}; 3320 u32 header, extension; 3321 int ret; 3322 3323 /* no route set up if chain DMA is used */ 3324 if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) { 3325 if (!src_pipeline->use_chain_dma || !sink_pipeline->use_chain_dma) { 3326 dev_err(sdev->dev, 3327 "use_chain_dma must be set for both src %s and sink %s pipelines\n", 3328 src_widget->widget->name, sink_widget->widget->name); 3329 return -EINVAL; 3330 } 3331 return 0; 3332 } 3333 3334 if (!src_fw_module || !sink_fw_module) { 3335 dev_err(sdev->dev, 3336 "cannot bind %s -> %s, no firmware module for: %s%s\n", 3337 src_widget->widget->name, sink_widget->widget->name, 3338 src_fw_module ? "" : " source", 3339 sink_fw_module ? "" : " sink"); 3340 3341 return -ENODEV; 3342 } 3343 3344 sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, 3345 SOF_PIN_TYPE_OUTPUT); 3346 if (sroute->src_queue_id < 0) { 3347 dev_err(sdev->dev, 3348 "failed to get src_queue_id ID from source widget %s\n", 3349 src_widget->widget->name); 3350 return sroute->src_queue_id; 3351 } 3352 3353 sroute->dst_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, 3354 SOF_PIN_TYPE_INPUT); 3355 if (sroute->dst_queue_id < 0) { 3356 dev_err(sdev->dev, 3357 "failed to get dst_queue_id ID from sink widget %s\n", 3358 sink_widget->widget->name); 3359 sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, 3360 SOF_PIN_TYPE_OUTPUT); 3361 return sroute->dst_queue_id; 3362 } 3363 3364 /* Pin 0 format is already set during copier module init */ 3365 if (sroute->src_queue_id > 0 && WIDGET_IS_COPIER(src_widget->id)) { 3366 ret = sof_ipc4_set_copier_sink_format(sdev, src_widget, 3367 sink_widget, sroute); 3368 if (ret < 0) { 3369 dev_err(sdev->dev, 3370 "failed to set sink format for source %s:%d\n", 3371 src_widget->widget->name, sroute->src_queue_id); 3372 goto out; 3373 } 3374 } 3375 3376 dev_dbg(sdev->dev, "bind %s:%d -> %s:%d\n", 3377 src_widget->widget->name, sroute->src_queue_id, 3378 sink_widget->widget->name, sroute->dst_queue_id); 3379 3380 header = src_fw_module->man4_module_entry.id; 3381 header |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id); 3382 header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_BIND); 3383 header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 3384 header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 3385 3386 extension = sink_fw_module->man4_module_entry.id; 3387 extension |= SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(sink_widget->instance_id); 3388 extension |= SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(sroute->dst_queue_id); 3389 extension |= SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(sroute->src_queue_id); 3390 3391 msg.primary = header; 3392 msg.extension = extension; 3393 3394 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); 3395 if (ret < 0) { 3396 dev_err(sdev->dev, "failed to bind modules %s:%d -> %s:%d\n", 3397 src_widget->widget->name, sroute->src_queue_id, 3398 sink_widget->widget->name, sroute->dst_queue_id); 3399 goto out; 3400 } 3401 3402 return ret; 3403 3404 out: 3405 sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); 3406 sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); 3407 return ret; 3408 } 3409 3410 static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) 3411 { 3412 struct snd_sof_widget *src_widget = sroute->src_widget; 3413 struct snd_sof_widget *sink_widget = sroute->sink_widget; 3414 struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; 3415 struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; 3416 struct sof_ipc4_msg msg = {{ 0 }}; 3417 struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; 3418 struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; 3419 struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; 3420 struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; 3421 u32 header, extension; 3422 int ret = 0; 3423 3424 /* no route is set up if chain DMA is used */ 3425 if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) 3426 return 0; 3427 3428 dev_dbg(sdev->dev, "unbind modules %s:%d -> %s:%d\n", 3429 src_widget->widget->name, sroute->src_queue_id, 3430 sink_widget->widget->name, sroute->dst_queue_id); 3431 3432 /* 3433 * routes belonging to the same pipeline will be disconnected by the FW when the pipeline 3434 * is freed. So avoid sending this IPC which will be ignored by the FW anyway. 3435 */ 3436 if (src_widget->spipe->pipe_widget == sink_widget->spipe->pipe_widget) 3437 goto out; 3438 3439 header = src_fw_module->man4_module_entry.id; 3440 header |= SOF_IPC4_MOD_INSTANCE(src_widget->instance_id); 3441 header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_UNBIND); 3442 header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 3443 header |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 3444 3445 extension = sink_fw_module->man4_module_entry.id; 3446 extension |= SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(sink_widget->instance_id); 3447 extension |= SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(sroute->dst_queue_id); 3448 extension |= SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(sroute->src_queue_id); 3449 3450 msg.primary = header; 3451 msg.extension = extension; 3452 3453 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); 3454 if (ret < 0) 3455 dev_err(sdev->dev, "failed to unbind modules %s:%d -> %s:%d\n", 3456 src_widget->widget->name, sroute->src_queue_id, 3457 sink_widget->widget->name, sroute->dst_queue_id); 3458 out: 3459 sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); 3460 sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); 3461 3462 return ret; 3463 } 3464 3465 static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 3466 unsigned int flags, struct snd_sof_dai_config_data *data) 3467 { 3468 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 3469 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 3470 struct snd_sof_dai *dai = swidget->private; 3471 struct sof_ipc4_gtw_attributes *gtw_attr; 3472 struct sof_ipc4_copier_data *copier_data; 3473 struct sof_ipc4_copier *ipc4_copier; 3474 3475 if (!dai || !dai->private) { 3476 dev_err(sdev->dev, "Invalid DAI or DAI private data for %s\n", 3477 swidget->widget->name); 3478 return -EINVAL; 3479 } 3480 3481 ipc4_copier = (struct sof_ipc4_copier *)dai->private; 3482 copier_data = &ipc4_copier->data; 3483 3484 if (!data) 3485 return 0; 3486 3487 if (pipeline->use_chain_dma) { 3488 /* 3489 * Only configure the DMA Link ID for ChainDMA when this op is 3490 * invoked with SOF_DAI_CONFIG_FLAGS_HW_PARAMS 3491 */ 3492 if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 3493 pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK; 3494 pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data); 3495 } 3496 return 0; 3497 } 3498 3499 switch (ipc4_copier->dai_type) { 3500 case SOF_DAI_INTEL_HDA: 3501 gtw_attr = ipc4_copier->gtw_attr; 3502 gtw_attr->lp_buffer_alloc = pipeline->lp_mode; 3503 if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 3504 copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 3505 copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); 3506 } 3507 break; 3508 case SOF_DAI_INTEL_ALH: 3509 /* 3510 * Do not clear the node ID when this op is invoked with 3511 * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during 3512 * unprepare. The node_id for multi-gateway DAI's will be overwritten with the 3513 * group_id during copier's ipc_prepare op. 3514 */ 3515 if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 3516 struct sof_ipc4_alh_configuration_blob *blob; 3517 3518 blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; 3519 ipc4_copier->dai_index = data->dai_node_id; 3520 3521 /* 3522 * no need to set the node_id for aggregated DAI's. These will be assigned 3523 * a group_id during widget ipc_prepare 3524 */ 3525 if (blob->alh_cfg.device_count == 1) { 3526 copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 3527 copier_data->gtw_cfg.node_id |= 3528 SOF_IPC4_NODE_INDEX(data->dai_node_id); 3529 } 3530 } 3531 3532 break; 3533 case SOF_DAI_INTEL_DMIC: 3534 case SOF_DAI_INTEL_SSP: 3535 /* nothing to do for SSP/DMIC */ 3536 break; 3537 default: 3538 dev_err(sdev->dev, "%s: unsupported dai type %d\n", __func__, 3539 ipc4_copier->dai_type); 3540 return -EINVAL; 3541 } 3542 3543 return 0; 3544 } 3545 3546 static int sof_ipc4_parse_manifest(struct snd_soc_component *scomp, int index, 3547 struct snd_soc_tplg_manifest *man) 3548 { 3549 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3550 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 3551 struct sof_manifest_tlv *manifest_tlv; 3552 struct sof_manifest *manifest; 3553 u32 size = le32_to_cpu(man->priv.size); 3554 u8 *man_ptr = man->priv.data; 3555 u32 len_check; 3556 int i; 3557 3558 if (!size || size < SOF_IPC4_TPLG_ABI_SIZE) { 3559 dev_err(scomp->dev, "%s: Invalid topology ABI size: %u\n", 3560 __func__, size); 3561 return -EINVAL; 3562 } 3563 3564 manifest = (struct sof_manifest *)man_ptr; 3565 3566 dev_info(scomp->dev, 3567 "Topology: ABI %d:%d:%d Kernel ABI %u:%u:%u\n", 3568 le16_to_cpu(manifest->abi_major), le16_to_cpu(manifest->abi_minor), 3569 le16_to_cpu(manifest->abi_patch), 3570 SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH); 3571 3572 /* TODO: Add ABI compatibility check */ 3573 3574 /* no more data after the ABI version */ 3575 if (size <= SOF_IPC4_TPLG_ABI_SIZE) 3576 return 0; 3577 3578 manifest_tlv = manifest->items; 3579 len_check = sizeof(struct sof_manifest); 3580 for (i = 0; i < le16_to_cpu(manifest->count); i++) { 3581 len_check += sizeof(struct sof_manifest_tlv) + le32_to_cpu(manifest_tlv->size); 3582 if (len_check > size) 3583 return -EINVAL; 3584 3585 switch (le32_to_cpu(manifest_tlv->type)) { 3586 case SOF_MANIFEST_DATA_TYPE_NHLT: 3587 /* no NHLT in BIOS, so use the one from topology manifest */ 3588 if (ipc4_data->nhlt) 3589 break; 3590 ipc4_data->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data, 3591 le32_to_cpu(manifest_tlv->size), GFP_KERNEL); 3592 if (!ipc4_data->nhlt) 3593 return -ENOMEM; 3594 break; 3595 default: 3596 dev_warn(scomp->dev, "Skipping unknown manifest data type %d\n", 3597 manifest_tlv->type); 3598 break; 3599 } 3600 man_ptr += sizeof(struct sof_manifest_tlv) + le32_to_cpu(manifest_tlv->size); 3601 manifest_tlv = (struct sof_manifest_tlv *)man_ptr; 3602 } 3603 3604 return 0; 3605 } 3606 3607 static int sof_ipc4_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type) 3608 { 3609 struct sof_ipc4_copier *ipc4_copier = dai->private; 3610 struct snd_soc_tplg_hw_config *hw_config; 3611 struct snd_sof_dai_link *slink; 3612 bool dai_link_found = false; 3613 bool hw_cfg_found = false; 3614 int i; 3615 3616 if (!ipc4_copier) 3617 return 0; 3618 3619 list_for_each_entry(slink, &sdev->dai_link_list, list) { 3620 if (!strcmp(slink->link->name, dai->name)) { 3621 dai_link_found = true; 3622 break; 3623 } 3624 } 3625 3626 if (!dai_link_found) { 3627 dev_err(sdev->dev, "no DAI link found for DAI %s\n", dai->name); 3628 return -EINVAL; 3629 } 3630 3631 for (i = 0; i < slink->num_hw_configs; i++) { 3632 hw_config = &slink->hw_configs[i]; 3633 if (dai->current_config == le32_to_cpu(hw_config->id)) { 3634 hw_cfg_found = true; 3635 break; 3636 } 3637 } 3638 3639 if (!hw_cfg_found) { 3640 dev_err(sdev->dev, "no matching hw_config found for DAI %s\n", dai->name); 3641 return -EINVAL; 3642 } 3643 3644 switch (ipc4_copier->dai_type) { 3645 case SOF_DAI_INTEL_SSP: 3646 switch (param_type) { 3647 case SOF_DAI_PARAM_INTEL_SSP_MCLK: 3648 return le32_to_cpu(hw_config->mclk_rate); 3649 case SOF_DAI_PARAM_INTEL_SSP_BCLK: 3650 return le32_to_cpu(hw_config->bclk_rate); 3651 case SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS: 3652 return le32_to_cpu(hw_config->tdm_slots); 3653 default: 3654 dev_err(sdev->dev, "invalid SSP param %d\n", param_type); 3655 break; 3656 } 3657 break; 3658 default: 3659 dev_err(sdev->dev, "DAI type %d not supported yet!\n", ipc4_copier->dai_type); 3660 break; 3661 } 3662 3663 return -EINVAL; 3664 } 3665 3666 static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) 3667 { 3668 /* 3669 * This function is called during system suspend, we need to make sure 3670 * that all streams have been freed up. 3671 * Freeing might have been skipped when xrun happened just at the start 3672 * of the suspend and it sent a SNDRV_PCM_TRIGGER_STOP to the active 3673 * stream. This will call sof_pcm_stream_free() with 3674 * free_widget_list = false which will leave the kernel and firmware out 3675 * of sync during suspend/resume. 3676 * 3677 * This will also make sure that paused streams handled correctly. 3678 */ 3679 3680 return sof_pcm_free_all_streams(sdev); 3681 } 3682 3683 static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link) 3684 { 3685 if (link->no_pcm) 3686 return 0; 3687 3688 /* 3689 * set default trigger order for all links. Exceptions to 3690 * the rule will be handled in sof_pcm_dai_link_fixup() 3691 * For playback, the sequence is the following: start BE, 3692 * start FE, stop FE, stop BE; for Capture the sequence is 3693 * inverted start FE, start BE, stop BE, stop FE 3694 */ 3695 link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = SND_SOC_DPCM_TRIGGER_POST; 3696 link->trigger[SNDRV_PCM_STREAM_CAPTURE] = SND_SOC_DPCM_TRIGGER_PRE; 3697 3698 return 0; 3699 } 3700 3701 /* Tokens needed for different copier variants (aif, dai and buffer) */ 3702 static enum sof_tokens copier_token_list[] = { 3703 SOF_COMP_TOKENS, 3704 SOF_COPIER_TOKENS, 3705 SOF_AUDIO_FMT_NUM_TOKENS, 3706 SOF_IN_AUDIO_FORMAT_TOKENS, 3707 SOF_OUT_AUDIO_FORMAT_TOKENS, 3708 SOF_COMP_EXT_TOKENS, 3709 3710 SOF_COPIER_DEEP_BUFFER_TOKENS, /* for AIF copier */ 3711 SOF_DAI_TOKENS, /* for DAI copier */ 3712 }; 3713 3714 static enum sof_tokens pipeline_token_list[] = { 3715 SOF_SCHED_TOKENS, 3716 SOF_PIPELINE_TOKENS, 3717 }; 3718 3719 static enum sof_tokens pga_token_list[] = { 3720 SOF_COMP_TOKENS, 3721 SOF_GAIN_TOKENS, 3722 SOF_AUDIO_FMT_NUM_TOKENS, 3723 SOF_IN_AUDIO_FORMAT_TOKENS, 3724 SOF_OUT_AUDIO_FORMAT_TOKENS, 3725 SOF_COMP_EXT_TOKENS, 3726 }; 3727 3728 static enum sof_tokens mixer_token_list[] = { 3729 SOF_COMP_TOKENS, 3730 SOF_AUDIO_FMT_NUM_TOKENS, 3731 SOF_IN_AUDIO_FORMAT_TOKENS, 3732 SOF_OUT_AUDIO_FORMAT_TOKENS, 3733 SOF_COMP_EXT_TOKENS, 3734 }; 3735 3736 static enum sof_tokens src_token_list[] = { 3737 SOF_COMP_TOKENS, 3738 SOF_SRC_TOKENS, 3739 SOF_AUDIO_FMT_NUM_TOKENS, 3740 SOF_IN_AUDIO_FORMAT_TOKENS, 3741 SOF_OUT_AUDIO_FORMAT_TOKENS, 3742 SOF_COMP_EXT_TOKENS, 3743 }; 3744 3745 static enum sof_tokens asrc_token_list[] = { 3746 SOF_COMP_TOKENS, 3747 SOF_ASRC_TOKENS, 3748 SOF_AUDIO_FMT_NUM_TOKENS, 3749 SOF_IN_AUDIO_FORMAT_TOKENS, 3750 SOF_OUT_AUDIO_FORMAT_TOKENS, 3751 SOF_COMP_EXT_TOKENS, 3752 }; 3753 3754 static enum sof_tokens process_token_list[] = { 3755 SOF_COMP_TOKENS, 3756 SOF_AUDIO_FMT_NUM_TOKENS, 3757 SOF_IN_AUDIO_FORMAT_TOKENS, 3758 SOF_OUT_AUDIO_FORMAT_TOKENS, 3759 SOF_COMP_EXT_TOKENS, 3760 }; 3761 3762 static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { 3763 [snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3764 copier_token_list, ARRAY_SIZE(copier_token_list), 3765 NULL, sof_ipc4_prepare_copier_module, 3766 sof_ipc4_unprepare_copier_module}, 3767 [snd_soc_dapm_aif_out] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3768 copier_token_list, ARRAY_SIZE(copier_token_list), 3769 NULL, sof_ipc4_prepare_copier_module, 3770 sof_ipc4_unprepare_copier_module}, 3771 [snd_soc_dapm_dai_in] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai, 3772 copier_token_list, ARRAY_SIZE(copier_token_list), NULL, 3773 sof_ipc4_prepare_copier_module, 3774 sof_ipc4_unprepare_copier_module}, 3775 [snd_soc_dapm_dai_out] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai, 3776 copier_token_list, ARRAY_SIZE(copier_token_list), NULL, 3777 sof_ipc4_prepare_copier_module, 3778 sof_ipc4_unprepare_copier_module}, 3779 [snd_soc_dapm_buffer] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3780 copier_token_list, ARRAY_SIZE(copier_token_list), 3781 NULL, sof_ipc4_prepare_copier_module, 3782 sof_ipc4_unprepare_copier_module}, 3783 [snd_soc_dapm_scheduler] = {sof_ipc4_widget_setup_comp_pipeline, 3784 sof_ipc4_widget_free_comp_pipeline, 3785 pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL, 3786 NULL, NULL}, 3787 [snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga, 3788 pga_token_list, ARRAY_SIZE(pga_token_list), NULL, 3789 sof_ipc4_prepare_gain_module, 3790 NULL}, 3791 [snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer, 3792 mixer_token_list, ARRAY_SIZE(mixer_token_list), 3793 NULL, sof_ipc4_prepare_mixer_module, 3794 NULL}, 3795 [snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src, 3796 src_token_list, ARRAY_SIZE(src_token_list), 3797 NULL, sof_ipc4_prepare_src_module, 3798 NULL}, 3799 [snd_soc_dapm_asrc] = {sof_ipc4_widget_setup_comp_asrc, sof_ipc4_widget_free_comp_asrc, 3800 asrc_token_list, ARRAY_SIZE(asrc_token_list), 3801 NULL, sof_ipc4_prepare_src_module, /* Common prepare with SRC */ 3802 NULL}, 3803 [snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process, 3804 sof_ipc4_widget_free_comp_process, 3805 process_token_list, ARRAY_SIZE(process_token_list), 3806 NULL, sof_ipc4_prepare_process_module, 3807 NULL}, 3808 }; 3809 3810 const struct sof_ipc_tplg_ops ipc4_tplg_ops = { 3811 .widget = tplg_ipc4_widget_ops, 3812 .token_list = ipc4_token_list, 3813 .control_setup = sof_ipc4_control_setup, 3814 .control = &tplg_ipc4_control_ops, 3815 .widget_setup = sof_ipc4_widget_setup, 3816 .widget_free = sof_ipc4_widget_free, 3817 .route_setup = sof_ipc4_route_setup, 3818 .route_free = sof_ipc4_route_free, 3819 .dai_config = sof_ipc4_dai_config, 3820 .parse_manifest = sof_ipc4_parse_manifest, 3821 .dai_get_param = sof_ipc4_dai_get_param, 3822 .tear_down_all_pipelines = sof_ipc4_tear_down_all_pipelines, 3823 .link_setup = sof_ipc4_link_setup, 3824 }; 3825