[PATCH 08/10] ASoC: rockchip: spdif: Add support for format S32_LE
From: Sebastian Reichel <hidden>
Date: 2026-01-27 16:08:54
Also in:
linux-rockchip, linux-sound, lkml
Subsystem:
arm/rockchip soc support, sound, sound - soc layer / dynamic audio power management (asoc), the rest · Maintainers:
Heiko Stuebner, Jaroslav Kysela, Takashi Iwai, Liam Girdwood, Mark Brown, Linus Torvalds
From: Sugar Zhang <redacted> Treat 32 bit sample width as if it was 24 bits using only the 24 most significant bits. Co-developed-by: Zohn Ni <redacted> Signed-off-by: Zohn Ni <redacted> Signed-off-by: Sugar Zhang <redacted> [I've merged the channel-swapping fix from Zohn Ni into Sugar Zhang's patch introducing the problem in the first place] Signed-off-by: Sebastian Reichel <redacted> --- sound/soc/rockchip/rockchip_spdif.c | 22 ++++++++++++++++++++-- sound/soc/rockchip/rockchip_spdif.h | 8 ++++++++ 2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c
index 8cf54470f931..5e9504220a1e 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c@@ -99,21 +99,38 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: val |= SPDIF_CFGR_VDW_16; + val |= SPDIF_CFGR_ADJ_RIGHT_J; break; case SNDRV_PCM_FORMAT_S20_3LE: val |= SPDIF_CFGR_VDW_20; + val |= SPDIF_CFGR_ADJ_RIGHT_J; break; case SNDRV_PCM_FORMAT_S24_LE: val |= SPDIF_CFGR_VDW_24; + val |= SPDIF_CFGR_ADJ_RIGHT_J; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val |= SPDIF_CFGR_VDW_24; + val |= SPDIF_CFGR_ADJ_LEFT_J; break; default: return -EINVAL; } + /* + * clear MCLK domain logic before setting Fmclk and Fsdo to ensure + * that switching between S16_LE and S32_LE audio does not result + * in accidential channels swap. + */ + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLR_MASK, + SPDIF_CFGR_CLR_EN); + udelay(1); + ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | - SDPIF_CFGR_VDW_MASK, val); + SDPIF_CFGR_VDW_MASK | + SPDIF_CFGR_ADJ_MASK, val); return ret; }
@@ -203,7 +220,8 @@ static struct snd_soc_dai_driver rk_spdif_dai = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE), + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), }, .ops = &rk_spdif_dai_ops, };
diff --git a/sound/soc/rockchip/rockchip_spdif.h b/sound/soc/rockchip/rockchip_spdif.h
index fcc28b6c4f58..acf64986a2e0 100644
--- a/sound/soc/rockchip/rockchip_spdif.h
+++ b/sound/soc/rockchip/rockchip_spdif.h@@ -17,6 +17,14 @@ #define SPDIF_CFGR_CLK_DIV_MASK (0xff << SPDIF_CFGR_CLK_DIV_SHIFT) #define SPDIF_CFGR_CLK_DIV(x) ((x-1) << SPDIF_CFGR_CLK_DIV_SHIFT) +#define SPDIF_CFGR_CLR_MASK BIT(7) +#define SPDIF_CFGR_CLR_EN BIT(7) +#define SPDIF_CFGR_CLR_DIS 0 + +#define SPDIF_CFGR_ADJ_MASK BIT(3) +#define SPDIF_CFGR_ADJ_LEFT_J BIT(3) +#define SPDIF_CFGR_ADJ_RIGHT_J 0 + #define SPDIF_CFGR_HALFWORD_SHIFT 2 #define SPDIF_CFGR_HALFWORD_DISABLE (0 << SPDIF_CFGR_HALFWORD_SHIFT) #define SPDIF_CFGR_HALFWORD_ENABLE (1 << SPDIF_CFGR_HALFWORD_SHIFT)
--
2.51.0