]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: rockchip: spdif: Add support for set mclk rate
authorSugar Zhang <sugar.zhang@rock-chips.com>
Tue, 3 Feb 2026 16:46:29 +0000 (17:46 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 5 Feb 2026 18:46:46 +0000 (18:46 +0000)
Allow setting the mclk rate from the machine driver.

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-7-4412016cf577@collabora.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/rockchip/rockchip_spdif.c
sound/soc/rockchip/rockchip_spdif.h

index c1221ff00ed70296d0899be075b4b4b131f730b3..3b66d97f058294f64c1ab6d848106ff2d9a69400 100644 (file)
@@ -86,12 +86,15 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
                              struct snd_soc_dai *dai)
 {
        struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
+       unsigned int mclk_rate = clk_get_rate(spdif->mclk);
        unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE;
-       int srate, mclk;
+       int bmc, div;
        int ret;
 
-       srate = params_rate(params);
-       mclk = srate * 128;
+       /* bmc = 128fs */
+       bmc = 128 * params_rate(params);
+       div = DIV_ROUND_CLOSEST(mclk_rate, bmc);
+       val |= SPDIF_CFGR_CLK_DIV(div);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -107,14 +110,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       /* Set clock and calculate divider */
-       ret = clk_set_rate(spdif->mclk, mclk);
-       if (ret != 0) {
-               dev_err(spdif->dev, "Failed to set module clock rate: %d\n",
-                       ret);
-               return ret;
-       }
-
        ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR,
                                 SPDIF_CFGR_CLK_DIV_MASK |
                                 SPDIF_CFGR_HALFWORD_ENABLE |
@@ -177,7 +172,24 @@ static int rk_spdif_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
+static int rk_spdif_set_sysclk(struct snd_soc_dai *dai,
+                              int clk_id, unsigned int freq, int dir)
+{
+       struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
+       int ret;
+
+       if (!freq)
+               return 0;
+
+       ret = clk_set_rate(spdif->mclk, freq);
+       if (ret)
+               dev_err(spdif->dev, "Failed to set mclk: %d\n", ret);
+
+       return ret;
+}
+
 static const struct snd_soc_dai_ops rk_spdif_dai_ops = {
+       .set_sysclk = rk_spdif_set_sysclk,
        .probe = rk_spdif_dai_probe,
        .hw_params = rk_spdif_hw_params,
        .trigger = rk_spdif_trigger,
index d8be9aae5b195cd0c3e12a526fb6476bba5be507..fcc28b6c4f5863cd8dfdba094aff264bc31b5777 100644 (file)
@@ -15,7 +15,7 @@
 */
 #define SPDIF_CFGR_CLK_DIV_SHIFT       (16)
 #define SPDIF_CFGR_CLK_DIV_MASK                (0xff << SPDIF_CFGR_CLK_DIV_SHIFT)
-#define SPDIF_CFGR_CLK_DIV(x)          (x << SPDIF_CFGR_CLK_DIV_SHIFT)
+#define SPDIF_CFGR_CLK_DIV(x)          ((x-1) << SPDIF_CFGR_CLK_DIV_SHIFT)
 
 #define SPDIF_CFGR_HALFWORD_SHIFT      2
 #define SPDIF_CFGR_HALFWORD_DISABLE    (0 << SPDIF_CFGR_HALFWORD_SHIFT)