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