[Audio: SPDIF] Fixed spdif function driver in linux 5.15
authorcurry.zhang <curry.zhang@starfivetech.com>
Wed, 29 Jun 2022 06:48:50 +0000 (02:48 -0400)
committerandy.hu <andy.hu@starfivetech.com>
Wed, 29 Jun 2022 06:48:50 +0000 (02:48 -0400)
Signed-off-by: curry.zhang <curry.zhang@starfivetech.com>
arch/riscv/boot/dts/starfive/codecs/sf_spdif.dtsi [new file with mode: 0644]
arch/riscv/boot/dts/starfive/jh7110-common.dtsi
arch/riscv/boot/dts/starfive/jh7110-evb-pinctrl.dtsi
arch/riscv/boot/dts/starfive/jh7110.dtsi
arch/riscv/configs/starfive_jh7110_defconfig
sound/soc/starfive/starfive_spdif.c
sound/soc/starfive/starfive_spdif.h
sound/soc/starfive/starfive_spdif_pcm.c [changed mode: 0644->0755]

diff --git a/arch/riscv/boot/dts/starfive/codecs/sf_spdif.dtsi b/arch/riscv/boot/dts/starfive/codecs/sf_spdif.dtsi
new file mode 100644 (file)
index 0000000..cac5436
--- /dev/null
@@ -0,0 +1,19 @@
+&sound {\r
+\r
+        simple-audio-card,dai-link@1 {\r
+                reg = <0>;\r
+                format = "left_j";\r
+                bitclock-master = <&sndcpu0>;\r
+                frame-master = <&sndcpu0>;\r
+                status = "okay";\r
+\r
+                sndcpu0: cpu {\r
+                        sound-dai = <&spdif0>;\r
+                };\r
+\r
+                codec {\r
+                        sound-dai = <&spdif_transmitter>;\r
+                };\r
+        };\r
+\r
+};\r
index 3591e82..257d38d 100755 (executable)
 };
 
 &spdif0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spdif0_pins>;
        status = "disabled";
 };
 
 };
 
 &spdif_transmitter {
+       compatible = "linux,spdif-dit";
+       #sound-dai-cells = <0>;
        status = "disabled";
 };
 
 &spdif_receiver {
+       compatible = "linux,spdif-dir";
+       #sound-dai-cells = <0>;
        status = "disabled";
 };
 
index 54ab3e0..7c797c5 100755 (executable)
                };
        };
 
+       spdif0_pins: spdif0-pins {
+               spdif0-pins {
+                       sf,pins = <PAD_GPIO57>;
+                       sf,pinmux = <PAD_GPIO57_FUNC_SEL 0>;
+                       sf,pin-ioconfig = <IO(GPIO_IE(1)|(GPIO_PU(1)))>;
+                       sf,pin-gpio-dout = <GPO_SPDIF0_SPDIFO>;
+                       sf,pin-gpio-doen = <OEN_LOW>;
+               };
+       };
+
        pwmdac0_pins: pwmdac0-pins {
                pwmdac0-pins-left {
                        sf,pins = <PAD_GPIO57>;
                        sf,pin-gpio-doen = <U0_PWM_8CH_PTC_OE_N_7>;
                };
        };
-};
\ No newline at end of file
+};
index b45860e..518f58a 100755 (executable)
                        reg = <0x0 0x100a0000 0x0 0x1000>;
                        clocks = <&clkgen JH7110_SPDIF_CLK_APB>,
                                 <&clkgen JH7110_SPDIF_CLK_CORE>,
-                                <&clkgen JH7110_MCLK>;
-                       clock-names = "spdif-apb", "spdif-core", "audioclk";
+                                <&clkgen JH7110_APB0>,
+                                <&clkgen JH7110_AUDIO_ROOT>,
+                                <&clkgen JH7110_MCLK_INNER>;
+                       clock-names = "spdif-apb", "spdif-core", "apb0",
+                                     "audroot", "mclk_inner";
                        resets = <&rstgen RSTN_U0_CDNS_SPDIF_APB>;
                        reset-names = "rst_apb";
                        interrupts = <84>;
index 45bc722..34e2a93 100644 (file)
@@ -198,7 +198,10 @@ CONFIG_SND_SOC=y
 CONFIG_SND_DESIGNWARE_I2S=y
 CONFIG_SND_DESIGNWARE_I2S_STARFIVE_JH7110=y
 CONFIG_SND_SOC_WM8960=y
+CONFIG_SND_STARFIVE_SPDIF=y
+CONFIG_SND_STARFIVE_SPDIF_PCM=y
 CONFIG_SND_STARFIVE_PWMDAC=y
+CONFIG_SND_SOC_SPDIF=y
 CONFIG_SND_SIMPLE_CARD=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
index 3c255d2..177c361 100755 (executable)
@@ -1,22 +1,9 @@
-/**
-  ******************************************************************************
-  * @file  sf_spdif.c
-  * @author  StarFive Technology
-  * @version  V1.0
-  * @date  05/27/2021
-  * @brief
-  ******************************************************************************
-  * @copy
-  *
-  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-  *
-  * <h2><center>&copy; COPYRIGHT 20120 Shanghai StarFive Technology Co., Ltd. </center></h2>
-  */
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * SPDIF driver for the StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
 
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -47,46 +34,39 @@ static irqreturn_t spdif_irq_handler(int irq, void *dev_id)
        regmap_read(dev->regmap, SPDIF_STAT_REG, &stat);
        regmap_update_bits(dev->regmap, SPDIF_CTRL,
                SPDIF_MASK_ENABLE, 0);
-       regmap_update_bits(dev->regmap, SPDIF_INT_REG, 
+       regmap_update_bits(dev->regmap, SPDIF_INT_REG,
                SPDIF_INT_REG_BIT, 0);
 
        if ((stat & SPDIF_EMPTY_FLAG) || (stat & SPDIF_AEMPTY_FLAG)) {
                sf_spdif_pcm_push_tx(dev);
                irq_valid = true;
-       } 
-       
+       }
+
        if ((stat & SPDIF_FULL_FLAG) || (stat & SPDIF_AFULL_FLAG)) {
                sf_spdif_pcm_pop_rx(dev);
                irq_valid = true;
-       } 
+       }
 
-       if (stat & SPDIF_PARITY_FLAG) {
+       if (stat & SPDIF_PARITY_FLAG)
                irq_valid = true;
-       } 
-       
-       if (stat & SPDIF_UNDERR_FLAG) {
+
+       if (stat & SPDIF_UNDERR_FLAG)
                irq_valid = true;
-       }
-       
-       if (stat & SPDIF_OVRERR_FLAG) {
+
+       if (stat & SPDIF_OVRERR_FLAG)
                irq_valid = true;
-       }
-       
-       if (stat & SPDIF_SYNCERR_FLAG) {
+
+       if (stat & SPDIF_SYNCERR_FLAG)
                irq_valid = true;
-       }
-       
-       if (stat & SPDIF_LOCK_FLAG) {
+
+       if (stat & SPDIF_LOCK_FLAG)
                irq_valid = true;
-       }
-       
-       if (stat & SPDIF_BEGIN_FLAG) {
+
+       if (stat & SPDIF_BEGIN_FLAG)
                irq_valid = true;
-       }
 
-       if (stat & SPDIF_RIGHT_LEFT) {
+       if (stat & SPDIF_RIGHT_LEFT)
                irq_valid = true;
-       }
 
        regmap_update_bits(dev->regmap, SPDIF_CTRL,
                SPDIF_MASK_ENABLE, SPDIF_MASK_ENABLE);
@@ -108,14 +88,14 @@ static int sf_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
                /* tx mode */
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_TR_MODE, SPDIF_TR_MODE);
-       
+
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_MASK_FIFO, SPDIF_EMPTY_MASK | SPDIF_AEMPTY_MASK);
        } else {
                /* rx mode */
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_TR_MODE, 0);
-               
+
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_MASK_FIFO, SPDIF_FULL_MASK | SPDIF_AFULL_MASK);
        }
@@ -127,7 +107,7 @@ static int sf_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
                /* clock recovery form the SPDIF data stream  0:clk_enable */
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_CLK_ENABLE, 0);
-       
+
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_ENABLE, SPDIF_ENABLE);
                break;
@@ -137,12 +117,12 @@ static int sf_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
                /* clock recovery form the SPDIF data stream  1:power save mode */
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_CLK_ENABLE, SPDIF_CLK_ENABLE);
-       
+
                regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                        SPDIF_ENABLE, 0);
                break;
        default:
-               printk(KERN_ERR "%s L.%d cmd:%d\n", __func__, __LINE__, cmd);
+               dev_err(dai->dev, "%s L.%d cmd:%d\n", __func__, __LINE__, cmd);
                return -EINVAL;
        }
 
@@ -157,11 +137,13 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
        unsigned int rate;
        unsigned int format;
        unsigned int tsamplerate;
+       unsigned int mclk;
+       int ret;
 
        channels = params_channels(params);
        rate = params_rate(params);
        format = params_format(params);
-       
+
        switch (channels) {
        case 2:
                break;
@@ -176,28 +158,40 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S32_LE:
                break;
        default:
-               dev_err(spdif->dev, "invalid format\n");
+               dev_err(dai->dev, "invalid format\n");
                return -EINVAL;
        }
 
        switch (rate) {
        case 8000:
+               mclk = 4096000;
+               break;
        case 11025:
+               mclk = 5644800;
+               break;
        case 16000:
+               mclk = 8192000;
+               break;
        case 22050:
+               mclk = 11289600;
                break;
        default:
-               printk(KERN_ERR "channel:%d sample rate:%d\n", channels, rate);
+               dev_err(dai->dev, "channel:%d sample rate:%d\n", channels, rate);
                return -EINVAL;
        }
 
-       /* 4096000/128=32000 */
-       tsamplerate = (32000 + rate/2)/rate - 1;
-       
-       if (rate < 3) {
-               return -EINVAL;
+       ret = clk_set_rate(spdif->mclk_inner, mclk);
+       if (ret) {
+               dev_err(dai->dev, "failed to set rate for spdif mclk_inner ret=%d\n", ret);
+               return ret;
        }
-       
+
+       /* (FCLK)4096000/128=32000 */
+       tsamplerate = (32000 + rate/2)/rate - 1;
+
+       if (tsamplerate < 3)
+               tsamplerate = 3;
+
        /* transmission sample rate */
        regmap_update_bits(spdif->regmap, SPDIF_CTRL, 0xFF, tsamplerate);
 
@@ -207,16 +201,20 @@ static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
 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" },
+               { .id = "spdif-apb" },          /* clock-names in dts file */
+               { .id = "spdif-core" },
+               { .id = "apb0" },
+               { .id = "audroot" },
+               { .id = "mclk_inner"},
        };
        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;
+       spdif->apb0_clk = clks[2].clk;
+       spdif->audio_root = clks[3].clk;
+       spdif->mclk_inner = clks[4].clk;
        return ret;
 }
 
@@ -243,57 +241,82 @@ static int sf_spdif_clk_init(struct platform_device *pdev,
        ret = clk_prepare_enable(spdif->spdif_apb);
        if (ret) {
                dev_err(&pdev->dev, "failed to prepare enable spdif_apb\n");
-                       goto err_clk_spdif;
+               goto disable_apb_clk;
        }
 
        ret = clk_prepare_enable(spdif->spdif_core);
        if (ret) {
                dev_err(&pdev->dev, "failed to prepare enable spdif_core\n");
-               goto err_clk_spdif;
+               goto disable_core_clk;
+       }
+
+       ret = clk_prepare_enable(spdif->apb0_clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable apb0_clk\n");
+               goto disable_apb0_clk;
+       }
+
+       ret = clk_prepare_enable(spdif->audio_root);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable spdif->audio_root\n");
+               goto disable_audroot_clk;
        }
 
-       ret = clk_prepare_enable(spdif->audioclk);
+       ret = clk_set_rate(spdif->audio_root, 204800000);
        if (ret) {
-               dev_err(&pdev->dev, "failed to prepare enable audioclk\n");
-               goto err_clk_spdif;
+               dev_err(&pdev->dev, "failed to set rate for spdif audroot ret=%d\n", ret);
+               goto disable_audroot_clk;
        }
 
+       ret = clk_prepare_enable(spdif->mclk_inner);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare enable spdif->mclk_inner\n");
+               goto disable_mclk_clk;
+       }
+
+       ret = clk_set_rate(spdif->mclk_inner, 8192000);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to set rate for spdif mclk_inner ret=%d\n", ret);
+               goto disable_mclk_clk;
+       }
+
+       dev_dbg(&pdev->dev, "spdif->spdif_apb = %lu\n", clk_get_rate(spdif->spdif_apb));
+       dev_dbg(&pdev->dev, "spdif->spdif_core = %lu\n", clk_get_rate(spdif->spdif_core));
+       dev_dbg(&pdev->dev, "spdif->apb0_clk = %lu\n", clk_get_rate(spdif->apb0_clk));
+
        ret = reset_control_deassert(spdif->rst_apb);
        if (ret) {
-               printk(KERN_INFO "failed to deassert apb\n");
-               goto err_clk_spdif;
+               dev_err(&pdev->dev, "failed to deassert apb\n");
+               goto disable_mclk_clk;
        }
 
-       printk(KERN_INFO "Initialize spdif...success\n");
+       return 0;
 
-err_clk_spdif:
-               return ret;
+disable_mclk_clk:
+       clk_disable_unprepare(spdif->mclk_inner);
+disable_audroot_clk:
+       clk_disable_unprepare(spdif->audio_root);
+disable_apb0_clk:
+       clk_disable_unprepare(spdif->apb0_clk);
+disable_core_clk:
+       clk_disable_unprepare(spdif->spdif_core);
+disable_apb_clk:
+       clk_disable_unprepare(spdif->spdif_apb);
+
+       return ret;
 }
 
 static int sf_spdif_dai_probe(struct snd_soc_dai *dai)
 {
        struct sf_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
 
-       #if 0
-       spdif->play_dma_data.addr = (dma_addr_t)spdif->spdif_base + SPDIF_FIFO_ADDR;
-       spdif->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       spdif->play_dma_data.fifo_size = 16;
-       spdif->play_dma_data.maxburst = 16;
-       spdif->capture_dma_data.addr = (dma_addr_t)spdif->spdif_base + SPDIF_FIFO_ADDR;
-       spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       spdif->capture_dma_data.fifo_size = 16;
-       spdif->capture_dma_data.maxburst = 16;
-       snd_soc_dai_init_dma_data(dai, &spdif->play_dma_data, &spdif->capture_dma_data);
-       snd_soc_dai_set_drvdata(dai, spdif);
-       #endif
-
        /* reset */
        regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                SPDIF_ENABLE | SPDIF_SFR_ENABLE | SPDIF_FIFO_ENABLE, 0);
 
        /* clear irq */
        regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
-               SPDIF_INT_REG_BIT, 0);  
+               SPDIF_INT_REG_BIT, 0);
 
        /* power save mode */
        regmap_update_bits(spdif->regmap, SPDIF_CTRL,
@@ -311,10 +334,10 @@ static int sf_spdif_dai_probe(struct snd_soc_dai *dai)
                SPDIF_SETPREAMBB, SPDIF_SETPREAMBB);
 
        regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
-               0x1FFF<<SPDIF_PREAMBLEDEL, 0x3<<SPDIF_PREAMBLEDEL);
+               BIT8TO20MASK<<SPDIF_PREAMBLEDEL, 0x3<<SPDIF_PREAMBLEDEL);
 
        regmap_update_bits(spdif->regmap, SPDIF_FIFO_CTRL,
-               0xFFFFFFFF, 0x20|(0x20<<SPDIF_AFULL_THRESHOLD));
+               ALLBITMASK, 0x20|(0x20<<SPDIF_AFULL_THRESHOLD));
 
        regmap_update_bits(spdif->regmap, SPDIF_CTRL,
                SPDIF_PARITYGEN, SPDIF_PARITYGEN);
@@ -339,14 +362,14 @@ static const struct snd_soc_dai_ops sf_spdif_dai_ops = {
 };
 
 #define SF_PCM_RATE_44100_192000  (SNDRV_PCM_RATE_44100 | \
-                                                                       SNDRV_PCM_RATE_48000 | \
-                                                                       SNDRV_PCM_RATE_96000 | \
-                                                                       SNDRV_PCM_RATE_192000)
-                                                                       
+                                  SNDRV_PCM_RATE_48000 | \
+                                  SNDRV_PCM_RATE_96000 | \
+                                  SNDRV_PCM_RATE_192000)
+
 #define SF_PCM_RATE_8000_22050  (SNDRV_PCM_RATE_8000 | \
-                                                                       SNDRV_PCM_RATE_11025 | \
-                                                                       SNDRV_PCM_RATE_16000 | \
-                                                                       SNDRV_PCM_RATE_22050)                                                                   
+                                SNDRV_PCM_RATE_11025 | \
+                                SNDRV_PCM_RATE_16000 | \
+                                SNDRV_PCM_RATE_22050)
 
 static struct snd_soc_dai_driver sf_spdif_dai = {
        .name = "spdif",
@@ -357,18 +380,18 @@ static struct snd_soc_dai_driver sf_spdif_dai = {
                .channels_min = 2,
                .channels_max = 2,
                .rates = SF_PCM_RATE_8000_22050,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE \
-                                       |SNDRV_PCM_FMTBIT_S24_LE \
-                                       |SNDRV_PCM_FMTBIT_S32_LE,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE \
+                          SNDRV_PCM_FMTBIT_S24_LE | \
+                          SNDRV_PCM_FMTBIT_S32_LE,
        },
        .capture =  {
                .stream_name = "Capture",
                .channels_min = 2,
                .channels_max = 2,
                .rates = SF_PCM_RATE_8000_22050,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE \
-                                       |SNDRV_PCM_FMTBIT_S24_LE \
-                                       |SNDRV_PCM_FMTBIT_S32_LE,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE \
+                          SNDRV_PCM_FMTBIT_S24_LE | \
+                          SNDRV_PCM_FMTBIT_S32_LE,
        },
        .ops = &sf_spdif_dai_ops,
        .symmetric_rate = 1,
@@ -412,25 +435,25 @@ static int sf_spdif_probe(struct platform_device *pdev)
 
        ret = sf_spdif_clks_get(pdev, spdif);
        if (ret) {
-                       dev_err(&pdev->dev, "failed to get audio clock\n");
-                       return 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;
+               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;
+               dev_err(&pdev->dev, "failed to enable audio clock\n");
+               return ret;
        }
-       
+
        spdif->dev = &pdev->dev;
        spdif->fifo_th = 16;
-       
+
        irq = platform_get_irq(pdev, 0);
        if (irq >= 0) {
                ret = devm_request_irq(&pdev->dev, irq, spdif_irq_handler, 0,
@@ -445,7 +468,7 @@ static int sf_spdif_probe(struct platform_device *pdev)
                                         &sf_spdif_dai, 1);
        if (ret)
                goto err_clk_disable;
-       
+
        if (irq >= 0) {
                ret = sf_spdif_pcm_register(pdev);
                spdif->use_pio = true;
@@ -479,6 +502,6 @@ static struct platform_driver sf_spdif_driver = {
 };
 module_platform_driver(sf_spdif_driver);
 
-MODULE_AUTHOR("curry.zhang <michael.yan@starfive.com>");
+MODULE_AUTHOR("curry.zhang <curry.zhang@starfive.com>");
 MODULE_DESCRIPTION("starfive SPDIF driver");
 MODULE_LICENSE("GPL v2");
index 8a9a417..805e93e 100755 (executable)
@@ -1,22 +1,9 @@
-/**
-  ******************************************************************************
-  * @file  sf_spdif.h
-  * @author  StarFive Technology
-  * @version  V1.0
-  * @date  05/27/2021
-  * @brief
-  ******************************************************************************
-  * @copy
-  *
-  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-  *
-  * <h2><center>&copy; COPYRIGHT 20120 Shanghai StarFive Technology Co., Ltd. </center></h2>
-  */
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * SPDIF driver for the StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
 
 #ifndef __SND_SOC_STARFIVE_SPDIF_H
 #define __SND_SOC_STARFIVE_SPDIF_H
 #include <linux/dmaengine.h>
 #include <linux/types.h>
 
-#define SPDIF_CTRL                             (0x0)
-#define SPDIF_INT_REG                  (0x4)
-#define SPDIF_FIFO_CTRL                        (0x8)
-#define SPDIF_STAT_REG                 (0xC)
-
-#define SPDIF_FIFO_ADDR                        (0x100)
-#define DMAC_SPDIF_POLLING_LEN (256)
-
-///ctrl: sampled on the rising clock edge
-#define        SPDIF_TSAMPLERATE       0///[SRATEW-1:0]
-#define SPDIF_SFR_ENABLE       (1<<8)  ///0:SFR reg reset to defualt value; auto set back to '1' after reset
-#define SPDIF_ENABLE           (1<<9)  ///0:reset of SPDIF block, SRF bits are unchanged; 1:enables SPDIF module
-#define SPDIF_FIFO_ENABLE      (1<<10) ///0:FIFO pointers are reset to zero,threshold levels for FIFO are unchaned; auto set back to '1'
-#define SPDIF_CLK_ENABLE       (1<<11) ///1:blocked and the modules are in power save mode; 0:block feeds the modules
-#define SPDIF_TR_MODE          (1<<12) ///0:rx; 1:tx
-#define        SPDIF_PARITCHECK        (1<<13) ///0:party bit rx in a sub-frame is repeated on the parity; 1:check on a parity error
-#define        SPDIF_PARITYGEN         (1<<14) ///0:parity bit from FIFO is transmitted in sub-frame;1:parity bit generated inside the core and added to a transmitted sub-frame
-#define SPDIF_VALIDITYCHECK    (1<<15) ///0:validity bit in frame isn't checked and all frame are written; 1:validity bit rx is checked
-#define SPDIF_CHANNEL_MODE     (1<<16) ///0:two-channel; 1:single-channel
-#define SPDIF_DUPLICATE                (1<<17) ///only tx -single-channel mode; 0:secondary channel; 1: left(primary) channel
-#define SPDIF_SETPREAMBB       (1<<18) ///only tx; 0:first preamble B after reset tx valid sub-frame; 1:first preamble B is tx after preambleddel(INT_REG)
-#define        SPDIF_USE_FIFO_IF       (1<<19) ///0:FIFO disabled ,APB accese FIFO; 1:FIFO enable, APB access to FIFO disable;
-///#define RESERVED            (1<<20)
+#define SPDIF_CTRL                     0x0
+#define SPDIF_INT_REG                  0x4
+#define SPDIF_FIFO_CTRL                        0x8
+#define SPDIF_STAT_REG                 0xC
+
+#define SPDIF_FIFO_ADDR                        0x100
+#define DMAC_SPDIF_POLLING_LEN         256
+
+/* ctrl: sampled on the rising clock edge */
+#define        SPDIF_TSAMPLERATE       0       /* [SRATEW-1:0] */
+#define SPDIF_SFR_ENABLE       (1<<8)  /* 0:SFR reg reset to defualt value; auto set back to '1' after reset */
+#define SPDIF_ENABLE           (1<<9)  /* 0:reset of SPDIF block, SRF bits are unchanged; 1:enables SPDIF module */
+#define SPDIF_FIFO_ENABLE      (1<<10) /* 0:FIFO pointers are reset to zero,threshold levels for FIFO are unchaned; auto set back to '1' */
+#define SPDIF_CLK_ENABLE       (1<<11) /* 1:blocked and the modules are in power save mode; 0:block feeds the modules */
+#define SPDIF_TR_MODE          (1<<12) /* 0:rx; 1:tx */
+#define SPDIF_PARITCHECK       (1<<13) /* 0:party bit rx in a sub-frame is repeated on the parity; 1:check on a parity error */
+#define SPDIF_PARITYGEN                (1<<14) /* 0:parity bit from FIFO is transmitted in sub-frame;1:parity bit generated inside the core and added to a transmitted sub-frame */
+#define SPDIF_VALIDITYCHECK    (1<<15) /* 0:validity bit in frame isn't checked and all frame are written; 1:validity bit rx is checked */
+#define SPDIF_CHANNEL_MODE     (1<<16) /* 0:two-channel; 1:single-channel */
+#define SPDIF_DUPLICATE                (1<<17) /* only tx -single-channel mode; 0:secondary channel; 1: left(primary) channel */
+#define SPDIF_SETPREAMBB       (1<<18) /* only tx; 0:first preamble B after reset tx valid sub-frame; 1:first preamble B is tx after preambleddel(INT_REG) */
+#define SPDIF_USE_FIFO_IF      (1<<19) /* 0:FIFO disabled ,APB accese FIFO; 1:FIFO enable, APB access to FIFO disable; */
 #define SPDIF_PARITY_MASK      (1<<21)
 #define SPDIF_UNDERR_MASK      (1<<22)
 #define SPDIF_OVRERR_MASK      (1<<23)
 #define SPDIF_BEGIN_MASK       (1<<30)
 #define SPDIF_INTEREQ_MAKS     (1<<31)
 
-#define SPDIF_MASK_ENABLE      (SPDIF_PARITY_MASK | SPDIF_UNDERR_MASK | SPDIF_OVRERR_MASK | SPDIF_EMPTY_MASK | \
-                                                        SPDIF_AEMPTY_MASK | SPDIF_FULL_MASK | SPDIF_AFULL_MASK | SPDIF_SYNCERR_MASK |  \
-                                                        SPDIF_LOCK_MASK | SPDIF_BEGIN_MASK | SPDIF_INTEREQ_MAKS)
-
-#define SPDIF_MASK_FIFO     (SPDIF_EMPTY_MASK | SPDIF_AEMPTY_MASK | SPDIF_FULL_MASK | SPDIF_AFULL_MASK)
-
-////INT_REG
-#define SPDIF_RSAMPLERATE      0               ///[SRATEW-1:0]
-#define SPDIF_PREAMBLEDEL      8               ///[PDELAYW+7:8]        first B delay
-#define SPDIF_PARITYO          (1<<21) ///0:clear parity error
-#define SPDIF_TDATA_UNDERR     (1<<22) ///tx data underrun error;0:clear
-#define SPDIF_RDATA_OVRERR     (1<<23) ///rx data overrun error; 0:clear
-#define SPDIF_FIFO_EMPTY       (1<<24) ///empty; 0:clear
-#define SPDIF_FIOF_AEMPTY      (1<<25) ///almost empty; 0:clear
-#define SPDIF_FIFO_FULL                (1<<26) ///FIFO full; 0:clear
-#define SPDIF_FIFO_AFULL       (1<<27) ///FIFO almost full; 0:clear
-#define SPDIF_SYNCERR          (1<<28) ///sync error; 0:clear
-#define SPDIF_LOCK                     (1<<29) ///sync; 0:clear
-#define SPDIF_BLOCK_BEGIN      (1<<30) ///new start block rx data
-
-#define SPDIF_INT_REG_BIT      (SPDIF_PARITYO | SPDIF_TDATA_UNDERR | SPDIF_RDATA_OVRERR | SPDIF_FIFO_EMPTY |   \
-                                                        SPDIF_FIOF_AEMPTY | SPDIF_FIFO_FULL | SPDIF_FIFO_AFULL | SPDIF_SYNCERR |       \
-                                                        SPDIF_LOCK | SPDIF_BLOCK_BEGIN)
+#define SPDIF_MASK_ENABLE      (SPDIF_PARITY_MASK | SPDIF_UNDERR_MASK | \
+                                SPDIF_OVRERR_MASK | SPDIF_EMPTY_MASK | \
+                                SPDIF_AEMPTY_MASK | SPDIF_FULL_MASK | \
+                                SPDIF_AFULL_MASK | SPDIF_SYNCERR_MASK | \
+                                SPDIF_LOCK_MASK | SPDIF_BEGIN_MASK | \
+                                SPDIF_INTEREQ_MAKS)
+
+#define SPDIF_MASK_FIFO     (SPDIF_EMPTY_MASK | SPDIF_AEMPTY_MASK | \
+                            SPDIF_FULL_MASK | SPDIF_AFULL_MASK)
+
+/* INT_REG */
+#define SPDIF_RSAMPLERATE      0       /* [SRATEW-1:0] */
+#define SPDIF_PREAMBLEDEL      8       /* [PDELAYW+7:8] first B delay */
+#define SPDIF_PARITYO          (1<<21) /* 0:clear parity error */
+#define SPDIF_TDATA_UNDERR     (1<<22) /* tx data underrun error;0:clear */
+#define SPDIF_RDATA_OVRERR     (1<<23) /* rx data overrun error; 0:clear */
+#define SPDIF_FIFO_EMPTY       (1<<24) /* empty; 0:clear */
+#define SPDIF_FIOF_AEMPTY      (1<<25) /* almost empty; 0:clear */
+#define SPDIF_FIFO_FULL                (1<<26) /* FIFO full; 0:clear */
+#define SPDIF_FIFO_AFULL       (1<<27) /* FIFO almost full; 0:clear */
+#define SPDIF_SYNCERR          (1<<28) /* sync error; 0:clear */
+#define SPDIF_LOCK             (1<<29) /* sync; 0:clear */
+#define SPDIF_BLOCK_BEGIN      (1<<30) /* new start block rx data */
+
+#define SPDIF_INT_REG_BIT      (SPDIF_PARITYO | SPDIF_TDATA_UNDERR | \
+                                SPDIF_RDATA_OVRERR | SPDIF_FIFO_EMPTY | \
+                                SPDIF_FIOF_AEMPTY | SPDIF_FIFO_FULL | \
+                                SPDIF_FIFO_AFULL | SPDIF_SYNCERR | \
+                                SPDIF_LOCK | SPDIF_BLOCK_BEGIN)
                                                 
-#define SPDIF_ERROR_INT_STATUS (SPDIF_PARITYO | SPDIF_TDATA_UNDERR | SPDIF_RDATA_OVRERR)
-#define SPDIF_FIFO_INT_STATUS  (SPDIF_FIFO_EMPTY | SPDIF_FIOF_AEMPTY | SPDIF_FIFO_FULL | SPDIF_FIFO_AFULL)
+#define SPDIF_ERROR_INT_STATUS (SPDIF_PARITYO | \
+                                SPDIF_TDATA_UNDERR | SPDIF_RDATA_OVRERR)
+#define SPDIF_FIFO_INT_STATUS  (SPDIF_FIFO_EMPTY | SPDIF_FIOF_AEMPTY | \
+                                SPDIF_FIFO_FULL | SPDIF_FIFO_AFULL)
 
 #define SPDIF_INT_PARITY_ERROR (-1)
 #define SPDIF_INT_TDATA_UNDERR (-2)
 #define SPDIF_INT_RDATA_OVRERR (-3)
 #define SPDIF_INT_FIFO_EMPTY   1
 #define SPDIF_INT_FIFO_AEMPTY  2
-#define SPDIF_INT_FIFO_FULL            3
+#define SPDIF_INT_FIFO_FULL    3
 #define SPDIF_INT_FIFO_AFULL   4
-#define SPDIF_INT_SYNCERR              (-4)
-#define SPDIF_INT_LOCK                 5       ///reciever has become synchronized with input data stream
-#define SPDIF_INT_BLOCK_BEGIN  6       ///start a new block in recieve data, written into FIFO
+#define SPDIF_INT_SYNCERR      (-4)
+#define SPDIF_INT_LOCK         5       /* reciever has become synchronized with input data stream */
+#define SPDIF_INT_BLOCK_BEGIN  6       /* start a new block in recieve data, written into FIFO */
 
-///FIFO_CTRL
-#define SPDIF_AEMPTY_THRESHOLD 0///[depth-1:0] 
-#define SPDIF_AFULL_THRESHOLD  16///[depth+15:16]
+/* FIFO_CTRL */
+#define SPDIF_AEMPTY_THRESHOLD 0       /* [depth-1:0] */
+#define SPDIF_AFULL_THRESHOLD  16      /* [depth+15:16] */
 
-///STAT_REG
+/* STAT_REG */
 #define SPDIF_FIFO_LEVEL       (1<<0)
-#define SPDIF_PARITY_FLAG      (1<<21) ///1:error; 0:repeated
-#define SPDIF_UNDERR_FLAG      (1<<22) ///1:error
-#define SPDIF_OVRERR_FLAG      (1<<23) ///1:error
-#define SPDIF_EMPTY_FLAG       (1<<24) ///1:fifo empty
-#define SPDIF_AEMPTY_FLAG      (1<<25) ///1:fifo almost empty
-#define SPDIF_FULL_FLAG                (1<<26) ///1:fifo full
-#define SPDIF_AFULL_FLAG       (1<<27) ///1:fifo almost full
-#define SPDIF_SYNCERR_FLAG     (1<<28) ///1:rx sync error
-#define SPDIF_LOCK_FLAG                (1<<29) ///1:RX sync
-#define SPDIF_BEGIN_FLAG       (1<<30) ///1:start a new block
-#define SPDIF_RIGHT_LEFT       (1<<31) ///1:left channel received and tx into FIFO; 0:right channel received and tx into FIFO
-
-#define SPDIF_STAT             (SPDIF_PARITY_FLAG | SPDIF_UNDERR_FLAG | SPDIF_OVRERR_FLAG | SPDIF_EMPTY_FLAG |         \
-                                                SPDIF_AEMPTY_FLAG | SPDIF_FULL_FLAG | SPDIF_AFULL_FLAG | SPDIF_SYNCERR_FLAG |          \
-                                                SPDIF_LOCK_FLAG | SPDIF_BEGIN_FLAG | SPDIF_RIGHT_LEFT)
+#define SPDIF_PARITY_FLAG      (1<<21) /* 1:error; 0:repeated */
+#define SPDIF_UNDERR_FLAG      (1<<22) /* 1:error */
+#define SPDIF_OVRERR_FLAG      (1<<23) /* 1:error */
+#define SPDIF_EMPTY_FLAG       (1<<24) /* 1:fifo empty */
+#define SPDIF_AEMPTY_FLAG      (1<<25) /* 1:fifo almost empty */
+#define SPDIF_FULL_FLAG                (1<<26) /* 1:fifo full */
+#define SPDIF_AFULL_FLAG       (1<<27) /* 1:fifo almost full */
+#define SPDIF_SYNCERR_FLAG     (1<<28) /* 1:rx sync error */
+#define SPDIF_LOCK_FLAG                (1<<29) /* 1:RX sync */
+#define SPDIF_BEGIN_FLAG       (1<<30) /* 1:start a new block */
+#define SPDIF_RIGHT_LEFT       (1<<31) /* 1:left channel received and tx into FIFO; 0:right channel received and tx into FIFO */
+
+#define BIT8TO20MASK   0x1FFF
+#define ALLBITMASK             0xFFFFFFFF
+
+#define SPDIF_STAT             (SPDIF_PARITY_FLAG | SPDIF_UNDERR_FLAG | \
+                                SPDIF_OVRERR_FLAG | SPDIF_EMPTY_FLAG | \
+                                SPDIF_AEMPTY_FLAG | SPDIF_FULL_FLAG | \
+                                SPDIF_AFULL_FLAG | SPDIF_SYNCERR_FLAG | \
+                                SPDIF_LOCK_FLAG | SPDIF_BEGIN_FLAG | \
+                                SPDIF_RIGHT_LEFT)
 struct sf_spdif_dev {
        void __iomem *spdif_base;
        struct regmap *regmap;
@@ -146,12 +146,13 @@ struct sf_spdif_dev {
                        bool *period_elapsed, snd_pcm_format_t format);
 
        snd_pcm_format_t format;
-       //unsigned int sample_bits;
        unsigned int tx_ptr;
        unsigned int rx_ptr;
        struct clk* spdif_apb;
        struct clk* spdif_core;
-       struct clk* audioclk;
+       struct clk* apb0_clk;
+       struct clk* audio_root;
+       struct clk* mclk_inner;
        struct reset_control *rst_apb;
 
        struct snd_dmaengine_dai_dma_data dma_data;
old mode 100644 (file)
new mode 100755 (executable)
index 44ecc48..ba5cd04
@@ -196,7 +196,6 @@ static int sf_pcm_hw_params(struct snd_soc_component *component,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct sf_spdif_dev *dev = runtime->private_data;
-       int ret;
 
        switch (params_channels(hw_params)) {
        case 2: