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