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