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