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