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