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