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