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