Skip to content

Commit f920964

Browse files
ujfalusibroonie
authored andcommitted
ASoC: SOF: ipc4-topology: Correct DAI copier config and NHLT blob request
In case of capture and when the DAI copier have single bit depth supported on it's input side we should use this format instead of the one in fe_params. Regardless of the stream direction for the NHLT blob lookup when the DAI copier only supports single bit depth on the DAI side we should only look for a blob which matches with this single configuration. For DMIC if the DAI copier supports multiple bit depths, try to request 32-bit blob first if the requested bit depth is 16-bit. If the 32-bit blob is available then look for marching (32-bit) copier format to make sure that both the blob and copier have correct parameters. Reviewed-by: Seppo Ingalsuo <[email protected]> Reviewed-by: Ranjani Sridharan <[email protected]> Signed-off-by: Peter Ujfalusi <[email protected]> Signed-off-by: Pierre-Louis Bossart <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent b679302 commit f920964

File tree

1 file changed

+136
-26
lines changed

1 file changed

+136
-26
lines changed

sound/soc/sof/ipc4-topology.c

Lines changed: 136 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,13 +1420,16 @@ static int snd_sof_get_hw_config_params(struct snd_sof_dev *sdev, struct snd_sof
14201420
return 0;
14211421
}
14221422

1423-
static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1424-
struct snd_pcm_hw_params *params, u32 dai_index,
1425-
u32 linktype, u8 dir, u32 **dst, u32 *len)
1423+
static int
1424+
snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1425+
bool single_format,
1426+
struct snd_pcm_hw_params *params, u32 dai_index,
1427+
u32 linktype, u8 dir, u32 **dst, u32 *len)
14261428
{
14271429
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
14281430
struct nhlt_specific_cfg *cfg;
14291431
int sample_rate, channel_count;
1432+
bool format_change = false;
14301433
int bit_depth, ret;
14311434
u32 nhlt_type;
14321435
int dev_type = 0;
@@ -1435,9 +1438,18 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s
14351438
switch (linktype) {
14361439
case SOF_DAI_INTEL_DMIC:
14371440
nhlt_type = NHLT_LINK_DMIC;
1438-
bit_depth = params_width(params);
14391441
channel_count = params_channels(params);
14401442
sample_rate = params_rate(params);
1443+
bit_depth = params_width(params);
1444+
/*
1445+
* Look for 32-bit blob first instead of 16-bit if copier
1446+
* supports multiple formats
1447+
*/
1448+
if (bit_depth == 16 && !single_format) {
1449+
dev_dbg(sdev->dev, "Looking for 32-bit blob first for DMIC\n");
1450+
format_change = true;
1451+
bit_depth = 32;
1452+
}
14411453
break;
14421454
case SOF_DAI_INTEL_SSP:
14431455
nhlt_type = NHLT_LINK_SSP;
@@ -1471,22 +1483,56 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s
14711483
dir, dev_type);
14721484

14731485
if (!cfg) {
1486+
if (format_change) {
1487+
/*
1488+
* The 32-bit blob was not found in NHLT table, try to
1489+
* look for one based on the params
1490+
*/
1491+
bit_depth = params_width(params);
1492+
format_change = false;
1493+
1494+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt,
1495+
dai_index, nhlt_type,
1496+
bit_depth, bit_depth,
1497+
channel_count, sample_rate,
1498+
dir, dev_type);
1499+
if (cfg)
1500+
goto out;
1501+
}
1502+
14741503
dev_err(sdev->dev,
14751504
"no matching blob for sample rate: %d sample width: %d channels: %d\n",
14761505
sample_rate, bit_depth, channel_count);
14771506
return -EINVAL;
14781507
}
14791508

1509+
out:
14801510
/* config length should be in dwords */
14811511
*len = cfg->size >> 2;
14821512
*dst = (u32 *)cfg->caps;
14831513

1514+
if (format_change) {
1515+
/*
1516+
* Update the params to reflect that we have loaded 32-bit blob
1517+
* instead of the 16-bit.
1518+
* This information is going to be used by the caller to find
1519+
* matching copier format on the dai side.
1520+
*/
1521+
struct snd_mask *m;
1522+
1523+
m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1524+
snd_mask_none(m);
1525+
snd_mask_set_format(m, SNDRV_PCM_FORMAT_S32_LE);
1526+
}
1527+
14841528
return 0;
14851529
}
14861530
#else
1487-
static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1488-
struct snd_pcm_hw_params *params, u32 dai_index,
1489-
u32 linktype, u8 dir, u32 **dst, u32 *len)
1531+
static int
1532+
snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1533+
bool single_format,
1534+
struct snd_pcm_hw_params *params, u32 dai_index,
1535+
u32 linktype, u8 dir, u32 **dst, u32 *len)
14901536
{
14911537
return 0;
14921538
}
@@ -1517,6 +1563,68 @@ bool sof_ipc4_copier_is_single_format(struct snd_sof_dev *sdev,
15171563
return true;
15181564
}
15191565

1566+
static int
1567+
sof_ipc4_prepare_dai_copier(struct snd_sof_dev *sdev, struct snd_sof_dai *dai,
1568+
struct snd_pcm_hw_params *params, int dir)
1569+
{
1570+
struct sof_ipc4_available_audio_format *available_fmt;
1571+
struct snd_pcm_hw_params dai_params = *params;
1572+
struct sof_ipc4_copier_data *copier_data;
1573+
struct sof_ipc4_copier *ipc4_copier;
1574+
bool single_format;
1575+
int ret;
1576+
1577+
ipc4_copier = dai->private;
1578+
copier_data = &ipc4_copier->data;
1579+
available_fmt = &ipc4_copier->available_fmt;
1580+
1581+
/*
1582+
* If the copier on the DAI side supports only single bit depth then
1583+
* this depth (format) should be used to look for the NHLT blob (if
1584+
* needed) and in case of capture this should be used for the input
1585+
* format lookup
1586+
*/
1587+
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
1588+
single_format = sof_ipc4_copier_is_single_format(sdev,
1589+
available_fmt->output_pin_fmts,
1590+
available_fmt->num_output_formats);
1591+
1592+
/* Update the dai_params with the only supported format */
1593+
if (single_format) {
1594+
ret = sof_ipc4_update_hw_params(sdev, &dai_params,
1595+
&available_fmt->output_pin_fmts[0].audio_fmt,
1596+
BIT(SNDRV_PCM_HW_PARAM_FORMAT));
1597+
if (ret)
1598+
return ret;
1599+
}
1600+
} else {
1601+
single_format = sof_ipc4_copier_is_single_format(sdev,
1602+
available_fmt->input_pin_fmts,
1603+
available_fmt->num_input_formats);
1604+
1605+
/* Update the dai_params with the only supported format */
1606+
if (single_format) {
1607+
ret = sof_ipc4_update_hw_params(sdev, &dai_params,
1608+
&available_fmt->input_pin_fmts[0].audio_fmt,
1609+
BIT(SNDRV_PCM_HW_PARAM_FORMAT));
1610+
if (ret)
1611+
return ret;
1612+
}
1613+
}
1614+
1615+
ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, single_format,
1616+
&dai_params,
1617+
ipc4_copier->dai_index,
1618+
ipc4_copier->dai_type, dir,
1619+
&ipc4_copier->copier_config,
1620+
&copier_data->gtw_cfg.config_length);
1621+
/* Update the params to reflect the changes made in this function */
1622+
if (!ret)
1623+
*params = dai_params;
1624+
1625+
return ret;
1626+
}
1627+
15201628
static int
15211629
sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
15221630
struct snd_pcm_hw_params *fe_params,
@@ -1527,7 +1635,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
15271635
struct snd_soc_component *scomp = swidget->scomp;
15281636
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
15291637
struct sof_ipc4_copier_data *copier_data;
1530-
struct snd_pcm_hw_params *ref_params;
1638+
struct snd_pcm_hw_params ref_params;
15311639
struct sof_ipc4_copier *ipc4_copier;
15321640
struct snd_sof_dai *dai;
15331641
u32 gtw_cfg_config_length;
@@ -1605,9 +1713,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
16051713
* for capture.
16061714
*/
16071715
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
1608-
ref_params = fe_params;
1716+
ref_params = *fe_params;
16091717
else
1610-
ref_params = pipeline_params;
1718+
ref_params = *pipeline_params;
16111719

16121720
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
16131721
copier_data->gtw_cfg.node_id |=
@@ -1633,31 +1741,33 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
16331741
available_fmt = &ipc4_copier->available_fmt;
16341742

16351743
/*
1636-
* When there is format conversion within a pipeline, the number of supported
1637-
* output formats is typically limited to just 1 for the DAI copiers. But when there
1638-
* is no format conversion, the DAI copiers input format must match that of the
1639-
* FE hw_params for capture and the pipeline params for playback.
1744+
* Use the fe_params as a base for the copier configuration.
1745+
* The ref_params might get updated to reflect what format is
1746+
* supported by the copier on the DAI side.
1747+
*
1748+
* In case of capture the ref_params returned will be used to
1749+
* find the input configuration of the copier.
16401750
*/
1641-
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
1642-
ref_params = pipeline_params;
1643-
else
1644-
ref_params = fe_params;
1645-
1646-
ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, fe_params, ipc4_copier->dai_index,
1647-
ipc4_copier->dai_type, dir,
1648-
&ipc4_copier->copier_config,
1649-
&copier_data->gtw_cfg.config_length);
1751+
ref_params = *fe_params;
1752+
ret = sof_ipc4_prepare_dai_copier(sdev, dai, &ref_params, dir);
16501753
if (ret < 0)
16511754
return ret;
16521755

1756+
/*
1757+
* For playback the pipeline_params needs to be used to find the
1758+
* input configuration of the copier.
1759+
*/
1760+
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
1761+
ref_params = *pipeline_params;
1762+
16531763
break;
16541764
}
16551765
case snd_soc_dapm_buffer:
16561766
{
16571767
ipc4_copier = (struct sof_ipc4_copier *)swidget->private;
16581768
copier_data = &ipc4_copier->data;
16591769
available_fmt = &ipc4_copier->available_fmt;
1660-
ref_params = pipeline_params;
1770+
ref_params = *pipeline_params;
16611771

16621772
break;
16631773
}
@@ -1668,8 +1778,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
16681778
}
16691779

16701780
/* set input and output audio formats */
1671-
ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params,
1672-
available_fmt);
1781+
ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config,
1782+
&ref_params, available_fmt);
16731783
if (ret < 0)
16741784
return ret;
16751785

0 commit comments

Comments
 (0)