ASoC: imx-rpmsg: Add DSD format support with dynamic DAI format switching

Add hw_params callback to dynamically switch DAI format between I2S
and PDM based on audio stream format. When DSD formats are detected,
the DAI format is switched to PDM mode.

Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
Link: https://patch.msgid.link/20260326055614.3614104-1-chancel.liu@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Chancel Liu 2026-03-26 14:56:14 +09:00 committed by Mark Brown
parent ba2a0e81d4
commit ccd7e53b7d
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -30,6 +30,53 @@ static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Main MIC", NULL),
};
static int imx_rpmsg_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
snd_pcm_format_t format = params_format(params);
struct device *dev = rtd->card->dev;
unsigned int fmt = rtd->dai_link->dai_fmt;
bool format_is_dsd = false;
int ret;
switch (format) {
case SNDRV_PCM_FORMAT_DSD_U8:
case SNDRV_PCM_FORMAT_DSD_U16_LE:
case SNDRV_PCM_FORMAT_DSD_U16_BE:
case SNDRV_PCM_FORMAT_DSD_U32_LE:
case SNDRV_PCM_FORMAT_DSD_U32_BE:
format_is_dsd = true;
break;
default:
format_is_dsd = false;
break;
}
if (format_is_dsd)
fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) |
SND_SOC_DAIFMT_PDM;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
return ret;
}
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to set codec dai fmt: %d\n", ret);
return ret;
}
return 0;
}
static const struct snd_soc_ops imx_rpmsg_ops = {
.hw_params = imx_rpmsg_hw_params,
};
static int imx_rpmsg_late_probe(struct snd_soc_card *card)
{
struct imx_rpmsg *data = snd_soc_card_get_drvdata(card);
@ -135,6 +182,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
data->dai.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC;
data->dai.ops = &imx_rpmsg_ops;
/*
* i.MX rpmsg sound cards work on codec slave mode. MCLK will be