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: Fixes for pipelines with SRC

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

The SRC component in a pipeline provides flexibility on the sampling
rate which was not handled previously. This series will improve the
kernel side with the needed logic to be able to deal with the SRC type
of components in pipelines.

+89 -45
+89 -45
sound/soc/sof/ipc4-topology.c
··· 1349 1349 } 1350 1350 #endif 1351 1351 1352 - static int ipc4_set_fmt_mask(struct snd_mask *fmt, unsigned int bit_depth) 1352 + static bool sof_ipc4_copier_is_single_format(struct snd_sof_dev *sdev, 1353 + struct sof_ipc4_pin_format *pin_fmts, 1354 + u32 pin_fmts_size) 1353 1355 { 1354 - switch (bit_depth) { 1355 - case 16: 1356 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 1357 - break; 1358 - case 24: 1359 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 1360 - break; 1361 - case 32: 1362 - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 1363 - break; 1364 - default: 1365 - return -EINVAL; 1356 + struct sof_ipc4_audio_format *fmt; 1357 + u32 valid_bits; 1358 + int i; 1359 + 1360 + fmt = &pin_fmts[0].audio_fmt; 1361 + valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1362 + 1363 + /* check if all output formats in topology are the same */ 1364 + for (i = 1; i < pin_fmts_size; i++) { 1365 + u32 _valid_bits; 1366 + 1367 + fmt = &pin_fmts[i].audio_fmt; 1368 + _valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); 1369 + 1370 + if (_valid_bits != valid_bits) 1371 + return false; 1366 1372 } 1367 1373 1368 - return 0; 1374 + return true; 1369 1375 } 1370 1376 1371 1377 static int ··· 1387 1381 struct snd_pcm_hw_params *ref_params; 1388 1382 struct sof_ipc4_copier *ipc4_copier; 1389 1383 struct snd_sof_dai *dai; 1390 - struct snd_mask *fmt; 1391 - int out_sample_valid_bits; 1392 1384 u32 gtw_cfg_config_length; 1393 1385 u32 dma_config_tlv_size = 0; 1394 1386 void **ipc_config_data; ··· 1396 1392 u32 out_ref_rate, out_ref_channels; 1397 1393 u32 deep_buffer_dma_ms = 0; 1398 1394 int output_fmt_index; 1395 + bool single_output_format; 1399 1396 1400 1397 dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); 1401 1398 ··· 1530 1525 return ret; 1531 1526 1532 1527 /* set the reference params for output format selection */ 1528 + single_output_format = sof_ipc4_copier_is_single_format(sdev, 1529 + available_fmt->output_pin_fmts, 1530 + available_fmt->num_output_formats); 1533 1531 switch (swidget->id) { 1534 1532 case snd_soc_dapm_aif_in: 1535 1533 case snd_soc_dapm_dai_out: ··· 1543 1535 in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1544 1536 out_ref_rate = in_fmt->sampling_frequency; 1545 1537 out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1546 - out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1538 + 1539 + if (!single_output_format) 1540 + out_ref_valid_bits = 1541 + SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1547 1542 break; 1548 1543 } 1549 1544 case snd_soc_dapm_aif_out: 1550 1545 case snd_soc_dapm_dai_in: 1551 - out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); 1552 - if (out_ref_valid_bits < 0) 1553 - return out_ref_valid_bits; 1554 - 1555 1546 out_ref_rate = params_rate(fe_params); 1556 1547 out_ref_channels = params_channels(fe_params); 1548 + if (!single_output_format) { 1549 + out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); 1550 + if (out_ref_valid_bits < 0) 1551 + return out_ref_valid_bits; 1552 + } 1557 1553 break; 1558 1554 default: 1559 1555 /* ··· 1566 1554 */ 1567 1555 return -EINVAL; 1568 1556 } 1557 + 1558 + /* 1559 + * if the output format is the same across all available output formats, choose 1560 + * that as the reference. 1561 + */ 1562 + if (single_output_format) { 1563 + struct sof_ipc4_audio_format *out_fmt; 1564 + 1565 + out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; 1566 + out_ref_valid_bits = 1567 + SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); 1568 + } 1569 + 1570 + dev_dbg(sdev->dev, "copier %s: reference output rate %d, channels %d valid_bits %d\n", 1571 + swidget->widget->name, out_ref_rate, out_ref_channels, out_ref_valid_bits); 1569 1572 1570 1573 output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &copier_data->base_config, 1571 1574 available_fmt, out_ref_rate, ··· 1691 1664 } 1692 1665 1693 1666 /* modify the input params for the next widget */ 1694 - fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); 1695 - out_sample_valid_bits = 1696 - SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(copier_data->out_format.fmt_cfg); 1697 - snd_mask_none(fmt); 1698 - ret = ipc4_set_fmt_mask(fmt, out_sample_valid_bits); 1667 + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, &copier_data->out_format); 1699 1668 if (ret) 1700 1669 return ret; 1701 1670 ··· 1861 1838 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1862 1839 struct sof_ipc4_src *src = swidget->private; 1863 1840 struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; 1864 - struct sof_ipc4_audio_format *in_fmt; 1841 + struct sof_ipc4_audio_format *out_audio_fmt; 1842 + struct sof_ipc4_audio_format *in_audio_fmt; 1865 1843 u32 out_ref_rate, out_ref_channels, out_ref_valid_bits; 1866 - struct snd_interval *rate; 1867 - int ret; 1844 + int output_format_index, input_format_index; 1868 1845 1869 - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->base_config, 1870 - pipeline_params, available_fmt); 1871 - if (ret < 0) 1872 - return ret; 1846 + input_format_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &src->base_config, 1847 + pipeline_params, available_fmt); 1848 + if (input_format_index < 0) 1849 + return input_format_index; 1873 1850 1874 - in_fmt = &available_fmt->input_pin_fmts[ret].audio_fmt; 1875 - out_ref_rate = in_fmt->sampling_frequency; 1876 - out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg); 1877 - out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg); 1851 + /* 1852 + * For playback, the SRC sink rate will be configured based on the requested output 1853 + * format, which is restricted to only deal with DAI's with a single format for now. 1854 + */ 1855 + if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) { 1856 + dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n", 1857 + available_fmt->num_output_formats, swidget->widget->name); 1858 + return -EINVAL; 1859 + } 1878 1860 1879 - ret = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, available_fmt, 1880 - out_ref_rate, out_ref_channels, out_ref_valid_bits); 1881 - if (ret < 0) { 1861 + /* 1862 + * SRC does not perform format conversion, so the output channels and valid bit depth must 1863 + * be the same as that of the input. 1864 + */ 1865 + in_audio_fmt = &available_fmt->input_pin_fmts[input_format_index].audio_fmt; 1866 + out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_audio_fmt->fmt_cfg); 1867 + out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); 1868 + 1869 + /* 1870 + * For capture, the SRC module should convert the rate to match the rate requested by the 1871 + * PCM hw_params. Set the reference params based on the fe_params unconditionally as it 1872 + * will be ignored for playback anyway. 1873 + */ 1874 + out_ref_rate = params_rate(fe_params); 1875 + 1876 + output_format_index = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, 1877 + available_fmt, out_ref_rate, 1878 + out_ref_channels, out_ref_valid_bits); 1879 + if (output_format_index < 0) { 1882 1880 dev_err(sdev->dev, "Failed to initialize output format for %s", 1883 1881 swidget->widget->name); 1882 + return output_format_index; 1884 1883 } 1885 1884 1886 1885 /* update pipeline memory usage */ 1887 1886 sof_ipc4_update_resource_usage(sdev, swidget, &src->base_config); 1888 1887 1889 - /* update pipeline_params for sink widgets */ 1890 - rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE); 1891 - rate->min = src->sink_rate; 1892 - rate->max = rate->min; 1888 + out_audio_fmt = &available_fmt->output_pin_fmts[output_format_index].audio_fmt; 1889 + src->sink_rate = out_audio_fmt->sampling_frequency; 1893 1890 1894 - return 0; 1891 + /* update pipeline_params for sink widgets */ 1892 + return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt); 1895 1893 } 1896 1894 1897 1895 static int