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