Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: ipc4: upport multiple configs for BE DAIs

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

Backend DAIs may support multiple audio formats. Modify pipeline setup to select
a suitable configuration based on topology and frontend DAI runtime configuration.

The prime use case is BT offload support where we need the abality to select
different configuration on the BE side.

+128 -30
+58 -8
sound/soc/sof/ipc4-pcm.c
··· 362 362 } 363 363 } 364 364 365 + /* 366 + * Fixup DAI link parameters for sampling rate based on 367 + * DAI copier configuration. 368 + */ 369 + static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, 370 + struct snd_pcm_hw_params *params, 371 + struct sof_ipc4_copier *ipc4_copier) 372 + { 373 + struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts; 374 + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 375 + int num_input_formats = ipc4_copier->available_fmt.num_input_formats; 376 + unsigned int fe_rate = params_rate(params); 377 + bool fe_be_rate_match = false; 378 + bool single_be_rate = true; 379 + unsigned int be_rate; 380 + int i; 381 + 382 + /* 383 + * Copier does not change sampling rate, so we 384 + * need to only consider the input pin information. 385 + */ 386 + for (i = 0; i < num_input_formats; i++) { 387 + unsigned int val = pin_fmts[i].audio_fmt.sampling_frequency; 388 + 389 + if (i == 0) 390 + be_rate = val; 391 + else if (val != be_rate) 392 + single_be_rate = false; 393 + 394 + if (val == fe_rate) { 395 + fe_be_rate_match = true; 396 + break; 397 + } 398 + } 399 + 400 + /* 401 + * If rate is different than FE rate, topology must 402 + * contain an SRC. But we do require topology to 403 + * define a single rate in the DAI copier config in 404 + * this case (FE rate may be variable). 405 + */ 406 + if (!fe_be_rate_match) { 407 + if (!single_be_rate) { 408 + dev_err(sdev->dev, "Unable to select sampling rate for DAI link\n"); 409 + return -EINVAL; 410 + } 411 + 412 + rate->min = be_rate; 413 + rate->max = rate->min; 414 + } 415 + 416 + return 0; 417 + } 418 + 365 419 static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, 366 420 struct snd_pcm_hw_params *params) 367 421 { 368 422 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 369 423 struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); 370 - struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 371 - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 372 424 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 373 425 struct sof_ipc4_copier *ipc4_copier; 426 + int ret; 374 427 375 428 if (!dai) { 376 429 dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, ··· 438 385 return -EINVAL; 439 386 } 440 387 441 - /* always set BE format to 32-bits for both playback and capture */ 442 - snd_mask_none(fmt); 443 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 444 - 445 - rate->min = ipc4_copier->available_fmt.input_pin_fmts->audio_fmt.sampling_frequency; 446 - rate->max = rate->min; 388 + ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); 389 + if (ret) 390 + return ret; 447 391 448 392 switch (ipc4_copier->dai_type) { 449 393 case SOF_DAI_INTEL_SSP:
+70 -22
sound/soc/sof/ipc4-topology.c
··· 1070 1070 } 1071 1071 #endif 1072 1072 1073 + static int ipc4_set_fmt_mask(struct snd_mask *fmt, unsigned int bit_depth) 1074 + { 1075 + switch (bit_depth) { 1076 + case 16: 1077 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 1078 + break; 1079 + case 24: 1080 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 1081 + break; 1082 + case 32: 1083 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 1084 + break; 1085 + default: 1086 + return -EINVAL; 1087 + } 1088 + 1089 + return 0; 1090 + } 1091 + 1092 + static int ipc4_copier_set_capture_fmt(struct snd_sof_dev *sdev, 1093 + struct snd_pcm_hw_params *pipeline_params, 1094 + struct snd_pcm_hw_params *fe_params, 1095 + struct sof_ipc4_available_audio_format *available_fmt) 1096 + { 1097 + struct sof_ipc4_audio_format *audio_fmt; 1098 + unsigned int sample_valid_bits; 1099 + bool multiple_formats = false; 1100 + bool fe_format_match = false; 1101 + struct snd_mask *fmt; 1102 + int i; 1103 + 1104 + for (i = 0; i < available_fmt->num_output_formats; i++) { 1105 + unsigned int val; 1106 + 1107 + audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; 1108 + val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(audio_fmt->fmt_cfg); 1109 + 1110 + if (i == 0) 1111 + sample_valid_bits = val; 1112 + else if (sample_valid_bits != val) 1113 + multiple_formats = true; 1114 + 1115 + if (snd_pcm_format_width(params_format(fe_params)) == val) 1116 + fe_format_match = true; 1117 + } 1118 + 1119 + fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); 1120 + snd_mask_none(fmt); 1121 + 1122 + if (multiple_formats) { 1123 + if (fe_format_match) { 1124 + /* multiple formats defined and one matches FE */ 1125 + snd_mask_set_format(fmt, params_format(fe_params)); 1126 + return 0; 1127 + } 1128 + 1129 + dev_err(sdev->dev, "Multiple audio formats for single dai_out not supported\n"); 1130 + return -EINVAL; 1131 + } 1132 + 1133 + return ipc4_set_fmt_mask(fmt, sample_valid_bits); 1134 + } 1135 + 1073 1136 static int 1074 1137 sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, 1075 1138 struct snd_pcm_hw_params *fe_params, ··· 1216 1153 format_list_to_search = available_fmt->output_pin_fmts; 1217 1154 format_list_count = available_fmt->num_output_formats; 1218 1155 1219 - /* 1220 - * modify the input params for the dai copier as it only supports 1221 - * 32-bit always 1222 - */ 1223 - fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); 1224 - snd_mask_none(fmt); 1225 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 1156 + ret = ipc4_copier_set_capture_fmt(sdev, pipeline_params, fe_params, 1157 + available_fmt); 1158 + if (ret < 0) 1159 + return ret; 1226 1160 } else { 1227 1161 format_list_to_search = available_fmt->input_pin_fmts; 1228 1162 format_list_count = available_fmt->num_input_formats; ··· 1364 1304 out_sample_valid_bits = 1365 1305 SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(copier_data->out_format.fmt_cfg); 1366 1306 snd_mask_none(fmt); 1367 - switch (out_sample_valid_bits) { 1368 - case 16: 1369 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 1370 - break; 1371 - case 24: 1372 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 1373 - break; 1374 - case 32: 1375 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 1376 - break; 1377 - default: 1378 - dev_err(sdev->dev, "invalid sample frame format %d\n", 1379 - params_format(pipeline_params)); 1380 - return -EINVAL; 1381 - } 1307 + ret = ipc4_set_fmt_mask(fmt, out_sample_valid_bits); 1308 + if (ret) 1309 + return ret; 1382 1310 1383 1311 /* 1384 1312 * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the