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