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