[Audio: SPDIF] Add standard system clock tree API
authorcurry.zhang <curry.zhang@starfivetech.com>
Thu, 5 May 2022 08:47:47 +0000 (01:47 -0700)
committercurry.zhang <curry.zhang@starfivetech.com>
Thu, 5 May 2022 08:47:47 +0000 (01:47 -0700)
Signed-off-by: curry.zhang <curry.zhang@starfivetech.com>
arch/riscv/boot/dts/starfive/jh7110.dtsi
sound/soc/starfive/starfive_spdif.c [changed mode: 0644->0755]
sound/soc/starfive/starfive_spdif.h [changed mode: 0644->0755]

index f6aabc2..30b6380 100755 (executable)
                spdif0: spdif0@100a0000 {
                        compatible = "starfive,sf-spdif";
                        reg = <0x0 0x100a0000 0x0 0x1000>;
-                       clocks = <&audioclk>;
-                       clock-names = "audioclk";
+                       clocks = <&clkgen JH7110_SPDIF_CLK_APB>,
+                               <&clkgen JH7110_SPDIF_CLK_CORE>,
+                               <&clkgen JH7110_MCLK>;
+                       clock-names = "spdif-apb", "spdif-core", "audioclk";
+                       resets = <&rstgen RSTN_U0_CDNS_SPDIF_APB>;
+                       reset-names = "rst_apb";
                        interrupts = <84>;
                        interrupt-names = "tx";
                        #sound-dai-cells = <0>;
old mode 100644 (file)
new mode 100755 (executable)
index 74fdcf1..3c255d2
@@ -26,6 +26,7 @@
 #include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -203,6 +204,72 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int sf_spdif_clks_get(struct platform_device *pdev,
+                               struct sf_spdif_dev *spdif)
+{
+
+       static struct clk_bulk_data clks[] = {
+                       { .id = "spdif-apb" },          //clock-names in dts file
+                       { .id = "spdif-core" },
+                       { .id = "audioclk" },
+       };
+       int ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(clks), clks);
+       spdif->spdif_apb = clks[0].clk;
+       spdif->spdif_core = clks[1].clk;
+       spdif->audioclk = clks[2].clk;
+       return ret;
+}
+
+static int sf_spdif_resets_get(struct platform_device *pdev,
+                               struct sf_spdif_dev *spdif)
+{
+       struct reset_control_bulk_data resets[] = {
+                       { .id = "rst_apb" },
+       };
+       int ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(resets), resets);
+       if (ret)
+               return ret;
+
+       spdif->rst_apb = resets[0].rstc;
+
+       return 0;
+}
+
+static int sf_spdif_clk_init(struct platform_device *pdev,
+                               struct sf_spdif_dev *spdif)
+{
+       int ret = 0;
+
+       ret = clk_prepare_enable(spdif->spdif_apb);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable spdif_apb\n");
+                       goto err_clk_spdif;
+       }
+
+       ret = clk_prepare_enable(spdif->spdif_core);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable spdif_core\n");
+               goto err_clk_spdif;
+       }
+
+       ret = clk_prepare_enable(spdif->audioclk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable audioclk\n");
+               goto err_clk_spdif;
+       }
+
+       ret = reset_control_deassert(spdif->rst_apb);
+       if (ret) {
+               printk(KERN_INFO "failed to deassert apb\n");
+               goto err_clk_spdif;
+       }
+
+       printk(KERN_INFO "Initialize spdif...success\n");
+
+err_clk_spdif:
+               return ret;
+}
+
 static int sf_spdif_dai_probe(struct snd_soc_dai *dai)
 {
        struct sf_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
@@ -342,6 +409,24 @@ static int sf_spdif_probe(struct platform_device *pdev)
                                            &sf_spdif_regmap_config);
        if (IS_ERR(spdif->regmap))
                return PTR_ERR(spdif->regmap);
+
+       ret = sf_spdif_clks_get(pdev, spdif);
+       if (ret) {
+                       dev_err(&pdev->dev, "failed to get audio clock\n");
+                       return ret;
+       }
+
+       ret = sf_spdif_resets_get(pdev, spdif);
+       if (ret) {
+                       dev_err(&pdev->dev, "failed to get audio reset controls\n");
+                       return ret;
+       }
+
+       ret = sf_spdif_clk_init(pdev, spdif);
+       if (ret) {
+                       dev_err(&pdev->dev, "failed to enable audio clock\n");
+                       return ret;
+       }
        
        spdif->dev = &pdev->dev;
        spdif->fifo_th = 16;
@@ -394,6 +479,6 @@ static struct platform_driver sf_spdif_driver = {
 };
 module_platform_driver(sf_spdif_driver);
 
-MODULE_AUTHOR("michael.yan <michael.yan@starfive.com>");
+MODULE_AUTHOR("curry.zhang <michael.yan@starfive.com>");
 MODULE_DESCRIPTION("starfive SPDIF driver");
-MODULE_LICENSE("GPL v2");
\ No newline at end of file
+MODULE_LICENSE("GPL v2");
old mode 100644 (file)
new mode 100755 (executable)
index ff641c6..8a9a417
@@ -149,6 +149,10 @@ struct sf_spdif_dev {
        //unsigned int sample_bits;
        unsigned int tx_ptr;
        unsigned int rx_ptr;
+       struct clk* spdif_apb;
+       struct clk* spdif_core;
+       struct clk* audioclk;
+       struct reset_control *rst_apb;
 
        struct snd_dmaengine_dai_dma_data dma_data;
 };