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