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