]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: rockchip: spdif: Add support for format S32_LE
authorSugar Zhang <sugar.zhang@rock-chips.com>
Tue, 3 Feb 2026 16:46:30 +0000 (17:46 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 5 Feb 2026 18:46:47 +0000 (18:46 +0000)
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>
sound/soc/rockchip/rockchip_spdif.c
sound/soc/rockchip/rockchip_spdif.h

index 3b66d97f058294f64c1ab6d848106ff2d9a69400..d06573f228052ec6b7bfd1f43b3f8a6f9e2eec03 100644 (file)
@@ -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,
 };
index fcc28b6c4f5863cd8dfdba094aff264bc31b5777..acf64986a2e09a6c37595e5c5fa4418f83e00b68 100644 (file)
 #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)