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