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