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