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