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