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