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-topology: Improve the audio format

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

Improve the logic to account for the current restrictions in topology while
making it extensible for future topology modifications.

The current topology definitions assume that input/output formats come in pairs.
For example even if there's only 1 output format for a module, we add 3 output
formats to match that of the input format count with the same parameters.
This is unnecessary but we have to deal with it until the topologies are
modified. Additionally, choosing the input/output audio format should
depend only on the pipeline params or the runtime FE hw_params depending
on where the module is in the pipeline.

This series modifies the logic for selection based on this and removes
unnecessary dependencies between the input and output formats.

+238 -122
+238 -122
sound/soc/sof/ipc4-topology.c
··· 1028 1028 return 0; 1029 1029 } 1030 1030 1031 - static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, 1032 - struct snd_sof_widget *swidget, 1033 - struct sof_ipc4_base_module_cfg *base_config, 1034 - struct snd_pcm_hw_params *params, 1035 - struct sof_ipc4_available_audio_format *available_fmt, 1036 - struct sof_ipc4_pin_format *pin_fmts, u32 pin_fmts_size) 1031 + static bool sof_ipc4_is_single_format(struct snd_sof_dev *sdev, 1032 + struct sof_ipc4_pin_format *pin_fmts, u32 pin_fmts_size) 1037 1033 { 1038 - u32 valid_bits; 1039 - u32 channels; 1040 - u32 rate; 1041 - int sample_valid_bits; 1034 + struct sof_ipc4_audio_format *fmt; 1035 + u32 rate, channels, valid_bits; 1042 1036 int i; 1043 1037 1044 - if (!pin_fmts) { 1045 - dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); 1046 - return -EINVAL; 1038 + fmt = &pin_fmts[0].audio_fmt; 1039 + rate = fmt->sampling_frequency; 1040 + channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); 1041 + valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1042 + 1043 + /* check if all output formats in topology are the same */ 1044 + for (i = 1; i < pin_fmts_size; i++) { 1045 + u32 _rate, _channels, _valid_bits; 1046 + 1047 + fmt = &pin_fmts[i].audio_fmt; 1048 + _rate = fmt->sampling_frequency; 1049 + _channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); 1050 + _valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1051 + 1052 + if (_rate != rate || _channels != channels || _valid_bits != valid_bits) 1053 + return false; 1047 1054 } 1048 1055 1056 + return true; 1057 + } 1058 + 1059 + static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, 1060 + struct sof_ipc4_base_module_cfg *base_config, 1061 + struct sof_ipc4_available_audio_format *available_fmt, 1062 + u32 out_ref_rate, u32 out_ref_channels, 1063 + u32 out_ref_valid_bits) 1064 + { 1065 + struct sof_ipc4_audio_format *out_fmt; 1066 + bool single_format; 1067 + int i; 1068 + 1069 + if (!available_fmt->num_output_formats) 1070 + return -EINVAL; 1071 + 1072 + single_format = sof_ipc4_is_single_format(sdev, available_fmt->output_pin_fmts, 1073 + available_fmt->num_output_formats); 1074 + 1075 + /* pick the first format if there's only one available or if all formats are the same */ 1076 + if (single_format) { 1077 + base_config->obs = available_fmt->output_pin_fmts[0].buffer_size; 1078 + return 0; 1079 + } 1080 + 1081 + /* 1082 + * if there are multiple output formats, then choose the output format that matches 1083 + * the reference params 1084 + */ 1085 + for (i = 0; i < available_fmt->num_output_formats; i++) { 1086 + u32 _out_rate, _out_channels, _out_valid_bits; 1087 + 1088 + out_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; 1089 + _out_rate = out_fmt->sampling_frequency; 1090 + _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg); 1091 + _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); 1092 + 1093 + if (_out_rate == out_ref_rate && _out_channels == out_ref_channels && 1094 + _out_valid_bits == out_ref_valid_bits) { 1095 + base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; 1096 + return i; 1097 + } 1098 + } 1099 + 1100 + return -EINVAL; 1101 + } 1102 + 1103 + static int sof_ipc4_get_valid_bits(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) 1104 + { 1049 1105 switch (params_format(params)) { 1050 1106 case SNDRV_PCM_FORMAT_S16_LE: 1051 - sample_valid_bits = 16; 1052 - break; 1107 + return 16; 1053 1108 case SNDRV_PCM_FORMAT_S24_LE: 1054 - sample_valid_bits = 24; 1055 - break; 1109 + return 24; 1056 1110 case SNDRV_PCM_FORMAT_S32_LE: 1057 - sample_valid_bits = 32; 1058 - break; 1111 + return 32; 1059 1112 default: 1060 1113 dev_err(sdev->dev, "invalid pcm frame format %d\n", params_format(params)); 1061 1114 return -EINVAL; 1062 1115 } 1116 + } 1063 1117 1064 - if (!pin_fmts_size) { 1065 - dev_err(sdev->dev, "no formats available for %s\n", swidget->widget->name); 1118 + static int sof_ipc4_init_input_audio_fmt(struct snd_sof_dev *sdev, 1119 + struct snd_sof_widget *swidget, 1120 + struct sof_ipc4_base_module_cfg *base_config, 1121 + struct snd_pcm_hw_params *params, 1122 + struct sof_ipc4_available_audio_format *available_fmt) 1123 + { 1124 + struct sof_ipc4_pin_format *pin_fmts = available_fmt->input_pin_fmts; 1125 + u32 pin_fmts_size = available_fmt->num_input_formats; 1126 + u32 valid_bits; 1127 + u32 channels; 1128 + u32 rate; 1129 + bool single_format; 1130 + int sample_valid_bits; 1131 + int i = 0; 1132 + 1133 + if (!available_fmt->num_input_formats) { 1134 + dev_err(sdev->dev, "no input formats for %s\n", swidget->widget->name); 1066 1135 return -EINVAL; 1067 1136 } 1068 1137 1138 + single_format = sof_ipc4_is_single_format(sdev, available_fmt->input_pin_fmts, 1139 + available_fmt->num_input_formats); 1140 + if (single_format) 1141 + goto in_fmt; 1142 + 1143 + sample_valid_bits = sof_ipc4_get_valid_bits(sdev, params); 1144 + if (sample_valid_bits < 0) 1145 + return sample_valid_bits; 1146 + 1069 1147 /* 1070 - * Search supported audio formats with pin index 0 to match rate, channels ,and 1071 - * sample_valid_bytes from runtime params 1148 + * Search supported input audio formats with pin index 0 to match rate, channels and 1149 + * sample_valid_bits from reference params 1072 1150 */ 1073 1151 for (i = 0; i < pin_fmts_size; i++) { 1074 1152 struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; ··· 1171 1093 return -EINVAL; 1172 1094 } 1173 1095 1096 + in_fmt: 1174 1097 /* copy input format */ 1175 1098 if (available_fmt->num_input_formats && i < available_fmt->num_input_formats) { 1176 1099 memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, ··· 1184 1105 sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); 1185 1106 } 1186 1107 1187 - if (available_fmt->num_output_formats && i < available_fmt->num_output_formats) 1188 - base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; 1189 - 1190 - /* Return the index of the matched format */ 1191 1108 return i; 1192 1109 } 1193 1110 ··· 1363 1288 return 0; 1364 1289 } 1365 1290 1366 - static int ipc4_copier_set_capture_fmt(struct snd_sof_dev *sdev, 1367 - struct snd_pcm_hw_params *pipeline_params, 1368 - struct snd_pcm_hw_params *fe_params, 1369 - struct sof_ipc4_available_audio_format *available_fmt) 1370 - { 1371 - struct sof_ipc4_audio_format *audio_fmt; 1372 - unsigned int sample_valid_bits; 1373 - bool multiple_formats = false; 1374 - bool fe_format_match = false; 1375 - struct snd_mask *fmt; 1376 - int i; 1377 - 1378 - for (i = 0; i < available_fmt->num_output_formats; i++) { 1379 - unsigned int val; 1380 - 1381 - audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; 1382 - val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(audio_fmt->fmt_cfg); 1383 - 1384 - if (i == 0) 1385 - sample_valid_bits = val; 1386 - else if (sample_valid_bits != val) 1387 - multiple_formats = true; 1388 - 1389 - if (snd_pcm_format_width(params_format(fe_params)) == val) 1390 - fe_format_match = true; 1391 - } 1392 - 1393 - fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); 1394 - snd_mask_none(fmt); 1395 - 1396 - if (multiple_formats) { 1397 - if (fe_format_match) { 1398 - /* multiple formats defined and one matches FE */ 1399 - snd_mask_set_format(fmt, params_format(fe_params)); 1400 - return 0; 1401 - } 1402 - 1403 - dev_err(sdev->dev, "Multiple audio formats for single dai_out not supported\n"); 1404 - return -EINVAL; 1405 - } 1406 - 1407 - return ipc4_set_fmt_mask(fmt, sample_valid_bits); 1408 - } 1409 - 1410 1291 static int 1411 1292 sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, 1412 1293 struct snd_pcm_hw_params *fe_params, ··· 1372 1341 struct sof_ipc4_available_audio_format *available_fmt; 1373 1342 struct snd_soc_component *scomp = swidget->scomp; 1374 1343 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1375 - struct sof_ipc4_pin_format *format_list_to_search; 1376 1344 struct sof_ipc4_copier_data *copier_data; 1377 1345 struct snd_pcm_hw_params *ref_params; 1378 1346 struct sof_ipc4_copier *ipc4_copier; ··· 1382 1352 int *ipc_config_size; 1383 1353 u32 **data; 1384 1354 int ipc_size, ret; 1355 + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1385 1356 u32 deep_buffer_dma_ms = 0; 1386 - u32 format_list_count; 1357 + int output_fmt_index; 1387 1358 1388 1359 dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); 1389 1360 ··· 1448 1417 * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts 1449 1418 * for capture. 1450 1419 */ 1451 - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 1452 - format_list_to_search = available_fmt->input_pin_fmts; 1453 - format_list_count = available_fmt->num_input_formats; 1454 - } else { 1455 - format_list_to_search = available_fmt->output_pin_fmts; 1456 - format_list_count = available_fmt->num_output_formats; 1457 - } 1420 + if (dir == SNDRV_PCM_STREAM_PLAYBACK) 1421 + ref_params = fe_params; 1422 + else 1423 + ref_params = pipeline_params; 1458 1424 1459 1425 copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 1460 1426 copier_data->gtw_cfg.node_id |= ··· 1459 1431 1460 1432 /* set gateway attributes */ 1461 1433 gtw_attr->lp_buffer_alloc = pipeline->lp_mode; 1462 - ref_params = fe_params; 1463 1434 break; 1464 1435 } 1465 1436 case snd_soc_dapm_dai_in: ··· 1475 1448 ipc4_copier = (struct sof_ipc4_copier *)dai->private; 1476 1449 copier_data = &ipc4_copier->data; 1477 1450 available_fmt = &ipc4_copier->available_fmt; 1478 - if (dir == SNDRV_PCM_STREAM_CAPTURE) { 1479 - format_list_to_search = available_fmt->output_pin_fmts; 1480 - format_list_count = available_fmt->num_output_formats; 1481 1451 1482 - ret = ipc4_copier_set_capture_fmt(sdev, pipeline_params, fe_params, 1483 - available_fmt); 1484 - if (ret < 0) 1485 - return ret; 1486 - } else { 1487 - format_list_to_search = available_fmt->input_pin_fmts; 1488 - format_list_count = available_fmt->num_input_formats; 1489 - } 1490 - 1491 - ref_params = pipeline_params; 1452 + /* 1453 + * When there is format conversion within a pipeline, the number of supported 1454 + * output formats is typically limited to just 1 for the DAI copiers. But when there 1455 + * is no format conversion, the DAI copiers input format must match that of the 1456 + * FE hw_params for capture and the pipeline params for playback. 1457 + */ 1458 + if (dir == SNDRV_PCM_STREAM_PLAYBACK) 1459 + ref_params = pipeline_params; 1460 + else 1461 + ref_params = fe_params; 1492 1462 1493 1463 ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, fe_params, ipc4_copier->dai_index, 1494 1464 ipc4_copier->dai_type, dir, ··· 1501 1477 ipc4_copier = (struct sof_ipc4_copier *)swidget->private; 1502 1478 copier_data = &ipc4_copier->data; 1503 1479 available_fmt = &ipc4_copier->available_fmt; 1504 - 1505 - /* Use the input formats to match pcm params */ 1506 - format_list_to_search = available_fmt->input_pin_fmts; 1507 - format_list_count = available_fmt->num_input_formats; 1508 1480 ref_params = pipeline_params; 1509 1481 1510 1482 break; ··· 1512 1492 } 1513 1493 1514 1494 /* set input and output audio formats */ 1515 - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, 1516 - available_fmt, format_list_to_search, format_list_count); 1495 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, 1496 + available_fmt); 1517 1497 if (ret < 0) 1518 1498 return ret; 1499 + 1500 + /* set the reference params for output format selection */ 1501 + switch (swidget->id) { 1502 + case snd_soc_dapm_aif_in: 1503 + case snd_soc_dapm_dai_out: 1504 + case snd_soc_dapm_buffer: 1505 + { 1506 + struct sof_ipc4_audio_format *in_fmt; 1507 + 1508 + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1509 + out_ref_rate = in_fmt->sampling_frequency; 1510 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1511 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1512 + break; 1513 + } 1514 + case snd_soc_dapm_aif_out: 1515 + case snd_soc_dapm_dai_in: 1516 + out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); 1517 + if (out_ref_valid_bits < 0) 1518 + return out_ref_valid_bits; 1519 + 1520 + out_ref_rate = params_rate(fe_params); 1521 + out_ref_channels = params_channels(fe_params); 1522 + break; 1523 + default: 1524 + /* 1525 + * Unsupported type should be caught by the former switch default 1526 + * case, this should never happen in reality. 1527 + */ 1528 + return -EINVAL; 1529 + } 1530 + 1531 + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &copier_data->base_config, 1532 + available_fmt, out_ref_rate, 1533 + out_ref_channels, out_ref_valid_bits); 1534 + if (output_fmt_index < 0) { 1535 + dev_err(sdev->dev, "Failed to initialize output format for %s", 1536 + swidget->widget->name); 1537 + return output_fmt_index; 1538 + } 1519 1539 1520 1540 /* 1521 1541 * Set the output format. Current topology defines pin 0 input and output formats in pairs. ··· 1564 1504 * input format. This logic will need to be updated when the format definitions 1565 1505 * in topology change. 1566 1506 */ 1567 - memcpy(&copier_data->out_format, &available_fmt->output_pin_fmts[ret].audio_fmt, 1507 + memcpy(&copier_data->out_format, 1508 + &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt, 1568 1509 sizeof(struct sof_ipc4_audio_format)); 1569 1510 dev_dbg(sdev->dev, "Output audio format for %s\n", swidget->widget->name); 1570 - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[ret], 1); 1511 + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[output_fmt_index], 1); 1571 1512 1572 1513 switch (swidget->id) { 1573 1514 case snd_soc_dapm_dai_in: ··· 1576 1515 { 1577 1516 /* 1578 1517 * Only SOF_DAI_INTEL_ALH needs copier_data to set blob. 1579 - * That's why only ALH dai's blob is set after sof_ipc4_init_audio_fmt 1518 + * That's why only ALH dai's blob is set after sof_ipc4_init_input_audio_fmt 1580 1519 */ 1581 1520 if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { 1582 1521 struct sof_ipc4_alh_configuration_blob *blob; ··· 1725 1664 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1726 1665 struct sof_ipc4_gain *gain = swidget->private; 1727 1666 struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; 1667 + struct sof_ipc4_audio_format *in_fmt; 1668 + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1728 1669 int ret; 1729 1670 1730 - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, 1731 - pipeline_params, available_fmt, 1732 - available_fmt->input_pin_fmts, 1733 - available_fmt->num_input_formats); 1671 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &gain->base_config, 1672 + pipeline_params, available_fmt); 1734 1673 if (ret < 0) 1735 1674 return ret; 1675 + 1676 + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1677 + out_ref_rate = in_fmt->sampling_frequency; 1678 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1679 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1680 + 1681 + ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->base_config, available_fmt, 1682 + out_ref_rate, out_ref_channels, out_ref_valid_bits); 1683 + if (ret < 0) { 1684 + dev_err(sdev->dev, "Failed to initialize output format for %s", 1685 + swidget->widget->name); 1686 + return ret; 1687 + } 1736 1688 1737 1689 /* update pipeline memory usage */ 1738 1690 sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &gain->base_config); ··· 1762 1688 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1763 1689 struct sof_ipc4_mixer *mixer = swidget->private; 1764 1690 struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; 1691 + struct sof_ipc4_audio_format *in_fmt; 1692 + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1765 1693 int ret; 1766 1694 1767 - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, 1768 - pipeline_params, available_fmt, 1769 - available_fmt->input_pin_fmts, 1770 - available_fmt->num_input_formats); 1695 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &mixer->base_config, 1696 + pipeline_params, available_fmt); 1771 1697 if (ret < 0) 1772 1698 return ret; 1699 + 1700 + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1701 + out_ref_rate = in_fmt->sampling_frequency; 1702 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1703 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1704 + 1705 + ret = sof_ipc4_init_output_audio_fmt(sdev, &mixer->base_config, available_fmt, 1706 + out_ref_rate, out_ref_channels, out_ref_valid_bits); 1707 + if (ret < 0) { 1708 + dev_err(sdev->dev, "Failed to initialize output format for %s", 1709 + swidget->widget->name); 1710 + return ret; 1711 + } 1773 1712 1774 1713 /* update pipeline memory usage */ 1775 1714 sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &mixer->base_config); ··· 1799 1712 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1800 1713 struct sof_ipc4_src *src = swidget->private; 1801 1714 struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; 1715 + struct sof_ipc4_audio_format *in_fmt; 1716 + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1802 1717 struct snd_interval *rate; 1803 1718 int ret; 1804 1719 1805 - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, 1806 - pipeline_params, available_fmt, 1807 - available_fmt->input_pin_fmts, 1808 - available_fmt->num_input_formats); 1720 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->base_config, 1721 + pipeline_params, available_fmt); 1809 1722 if (ret < 0) 1810 1723 return ret; 1724 + 1725 + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1726 + out_ref_rate = in_fmt->sampling_frequency; 1727 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1728 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1729 + 1730 + ret = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, available_fmt, 1731 + out_ref_rate, out_ref_channels, out_ref_valid_bits); 1732 + if (ret < 0) { 1733 + dev_err(sdev->dev, "Failed to initialize output format for %s", 1734 + swidget->widget->name); 1735 + } 1811 1736 1812 1737 /* update pipeline memory usage */ 1813 1738 sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config); ··· 1919 1820 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1920 1821 struct sof_ipc4_process *process = swidget->private; 1921 1822 struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; 1823 + struct sof_ipc4_audio_format *in_fmt; 1824 + u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1922 1825 void *cfg = process->ipc_config_data; 1826 + int output_fmt_index; 1923 1827 int ret; 1924 1828 1925 - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &process->base_config, 1926 - pipeline_params, available_fmt, 1927 - available_fmt->input_pin_fmts, 1928 - available_fmt->num_input_formats); 1829 + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &process->base_config, 1830 + pipeline_params, available_fmt); 1929 1831 if (ret < 0) 1930 1832 return ret; 1931 1833 1834 + in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1835 + out_ref_rate = in_fmt->sampling_frequency; 1836 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1837 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1838 + 1839 + output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &process->base_config, 1840 + available_fmt, out_ref_rate, 1841 + out_ref_channels, out_ref_valid_bits); 1842 + if (output_fmt_index < 0 && available_fmt->num_output_formats) { 1843 + dev_err(sdev->dev, "Failed to initialize output format for %s", 1844 + swidget->widget->name); 1845 + return output_fmt_index; 1846 + } 1847 + 1932 1848 /* copy Pin 0 output format */ 1933 - if (available_fmt->num_output_formats && ret < available_fmt->num_output_formats && 1934 - !available_fmt->output_pin_fmts[ret].pin_index) { 1935 - memcpy(&process->output_format, &available_fmt->output_pin_fmts[ret].audio_fmt, 1849 + if (available_fmt->num_output_formats && 1850 + output_fmt_index < available_fmt->num_output_formats && 1851 + !available_fmt->output_pin_fmts[output_fmt_index].pin_index) { 1852 + memcpy(&process->output_format, 1853 + &available_fmt->output_pin_fmts[output_fmt_index].audio_fmt, 1936 1854 sizeof(struct sof_ipc4_audio_format)); 1937 1855 1938 1856 /* modify the pipeline params with the pin 0 output format */