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