sound:starfive:spdif:Use mclk_inner about 11k and 22k
authorXingyu Wu <xingyu.wu@starfivetech.com>
Wed, 14 Sep 2022 06:11:39 +0000 (14:11 +0800)
committerXingyu Wu <xingyu.wu@starfivetech.com>
Thu, 15 Sep 2022 08:39:06 +0000 (16:39 +0800)
Use mclk_inner clock from 1188m PLL2
will be better about 11k and 22k.

Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
sound/soc/starfive/starfive_spdif.c

index 5d6be27..9608495 100755 (executable)
@@ -174,28 +174,62 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       audio_root = 204800000;
        switch (rate) {
        case 8000:
-               mclk = 4096000;
                break;
        case 11025:
-               mclk = 5644800;
+               audio_root = 148500000;
+               /* 11025 * 512 = 5644800 */
+               /* But now pll2 is 1188m and mclk should be 5711539 closely. */
+               mclk = 5711539;
                break;
        case 16000:
-               mclk = 8192000;
                break;
        case 22050:
-               audio_root = 153600000;
-               mclk = 11289600;
+               audio_root = 148500000;
+               mclk = 11423077;
                break;
        default:
                dev_err(dai->dev, "channel:%d sample rate:%d\n", channels, rate);
                return -EINVAL;
        }
 
-       mclk = clk_get_rate(spdif->mclk_ext);
-       dev_dbg(dai->dev, "mclk_ext get rate:%d\n", mclk);
+       /* use mclk_inner clock from 1188m PLL2 will be better about 11k and 22k*/
+       if ((rate == 11025) || (rate == 22050)) {
+               ret = clk_set_parent(spdif->mclk, spdif->mclk_inner);
+               if (ret) {
+                       dev_err(dai->dev,
+                               "failed to set parent to mclk_inner ret=%d\n", ret);
+                       goto fail_ext;
+               }
+
+               ret = clk_set_rate(spdif->audio_root, audio_root);
+               if (ret) {
+                       dev_err(dai->dev, "failed to set audio_root rate :%d\n", ret);
+                       goto fail_ext;
+               }
+               dev_dbg(dai->dev, "audio_root get rate:%ld\n",
+                               clk_get_rate(spdif->audio_root));
+
+               ret = clk_set_rate(spdif->mclk_inner, mclk);
+               if (ret) {
+                       dev_err(dai->dev, "failed to set mclk_inner rate :%d\n", ret);
+                       goto fail_ext;
+               }
+
+               mclk = clk_get_rate(spdif->mclk_inner);
+               dev_dbg(dai->dev, "mclk_inner get rate:%d\n", mclk);
+       } else {
+               ret = clk_set_parent(spdif->mclk, spdif->mclk_ext);
+               if (ret) {
+                       dev_err(dai->dev,
+                               "failed to set parent to mclk_ext ret=%d\n", ret);
+                       goto fail_ext;
+               }
+
+               mclk = clk_get_rate(spdif->mclk_ext);
+               dev_dbg(dai->dev, "mclk_ext get rate:%d\n", mclk);
+       }
 
        /* (FCLK)4096000/128=32000 */
        tsamplerate = (mclk / 128 + rate / 2) / rate - 1;
@@ -206,6 +240,9 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
        regmap_update_bits(spdif->regmap, SPDIF_CTRL, 0xFF, tsamplerate);
 
        return 0;
+
+fail_ext:
+       return ret;
 }
 
 static int sf_spdif_clks_get(struct platform_device *pdev,
@@ -490,5 +527,6 @@ static struct platform_driver sf_spdif_driver = {
 module_platform_driver(sf_spdif_driver);
 
 MODULE_AUTHOR("curry.zhang <curry.zhang@starfive.com>");
+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
 MODULE_DESCRIPTION("starfive SPDIF driver");
 MODULE_LICENSE("GPL v2");