summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSugar Zhang <sugar.zhang@rock-chips.com>2026-02-03 17:46:30 +0100
committerMark Brown <broonie@kernel.org>2026-02-05 18:46:47 +0000
commitc43ec509019842c0b836e858dc486c216b51b087 (patch)
tree43d148dd24d57d8012cf1b9674385d76b65b0158 /sound
parent298082783a0d6d07109f8ce09ab410a1de12876d (diff)
ASoC: rockchip: spdif: Add support for format S32_LE
Treat 32 bit sample width as if it was 24 bits using only the 24 most significant bits. [I've merged the channel-swapping fix from Zohn Ni into Sugar Zhang's patch introducing the problem in the first place] Co-developed-by: Zohn Ni <zohn.ni@rock-chips.com> Signed-off-by: Zohn Ni <zohn.ni@rock-chips.com> Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Link: https://patch.msgid.link/20260203-rockchip-spdif-cleanup-and-bsp-sync-v2-8-4412016cf577@collabora.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/rockchip/rockchip_spdif.c22
-rw-r--r--sound/soc/rockchip/rockchip_spdif.h8
2 files changed, 28 insertions, 2 deletions
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c
index 3b66d97f0582..d06573f22805 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)