ASoC: rockchip: spdif: caculate sclk according BMC(bitphase mark coding).
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_hdmi_spdif.c
index 039ea452a32cd66c7f68a196d4b1297294bf4528..12cdaecbcce0a95bebc0693e754e5c696c6b9eb6 100755 (executable)
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
+#include "card_info.h"
+#include "rk_pcm.h"
+
 #if 0
-#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_hdmi_spdif:"x)
+#define RK_SPDIF_DBG(x...) pr_info("rk_hdmi_spdif:"x)
 #else
 #define RK_SPDIF_DBG(x...) do { } while (0)
 #endif
 
-
-static int set_audio_clock_rate(unsigned long pll_rate,
-                               unsigned long audio_rate)
-{
-       struct clk *hclk_spdif, *sclk_spdif;
-
-#if defined (CONFIG_ARCH_RK30) || (CONFIG_ARCH_RK3188) 
-       hclk_spdif = clk_get(NULL, "hclk_spdif");
-       if (IS_ERR(hclk_spdif)) {
-               printk(KERN_ERR "spdif:failed to get hclk_spdif\n");
-               return -ENOENT;
-       }
-
-       clk_set_rate(hclk_spdif, pll_rate);
-       clk_put(hclk_spdif);
-#endif
-
-       sclk_spdif = clk_get(NULL, "spdif");
-       if (IS_ERR(sclk_spdif)) {
-               printk(KERN_ERR "spdif:failed to get sclk_spdif\n");
-               return -ENOENT;
-       }
-
-       clk_set_rate(sclk_spdif, audio_rate);
-       clk_put(sclk_spdif);
-
-       return 0;
-}
-
 static int rk_hw_params(struct snd_pcm_substream *substream,
-               struct snd_pcm_hw_params *params)
+                       struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       unsigned long pll_out, rclk_rate, dai_fmt = rtd->dai_link->dai_fmt;
+       unsigned long sclk;
        int ret, ratio;
 
        RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
 
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
-       if (ret < 0) {
-               printk("%s():failed to set the format for codec side\n", __func__);
-               return ret;
-       }
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
-       if (ret < 0) {
-               printk("%s():failed to set the format for cpu side\n", __func__);
-               return ret;
-       }
-  
+       /* bmc: 2*32*fs*2 = 128fs */
+       ratio = 128;
        switch (params_rate(params)) {
        case 44100:
-               pll_out = 11289600;
-               break;
        case 32000:
-               pll_out = 8192000;
-               break;
        case 48000:
-               pll_out = 12288000;
-               break;
        case 96000:
-               pll_out = 24576000;
+       case 192000:
+               sclk = params_rate(params) * ratio;
                break;
        default:
-               printk("rk_spdif: params not support\n");
+               pr_err("rk_spdif: params not support\n");
                return -EINVAL;
        }
 
-       ratio = 256;
-       rclk_rate = params_rate(params) * ratio;
-
-       /* Set audio source clock rates */
-       ret = set_audio_clock_rate(pll_out, rclk_rate);
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
+                                    sclk, SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
-       /* Set S/PDIF uses internal source clock */
-       //ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
-                                       //rclk_rate, SND_SOC_CLOCK_IN);
-       //if (ret < 0)
-               //return ret;
-
        return ret;
 }
 
@@ -125,9 +72,7 @@ static struct snd_soc_ops rk_spdif_ops = {
 static struct snd_soc_dai_link rk_dai = {
        .name = "SPDIF",
        .stream_name = "SPDIF PCM Playback",
-       .cpu_dai_name = "rockchip-spdif",
        .codec_dai_name = "rk-hdmi-spdif-hifi",
-       .codec_name = "hdmi-spdif",
        .ops = &rk_spdif_ops,
 };
 
@@ -144,10 +89,18 @@ static int rockchip_hdmi_spdif_audio_probe(struct platform_device *pdev)
 
        card->dev = &pdev->dev;
 
+       ret = rockchip_of_get_sound_card_info_(card, false);
+       if (ret) {
+               pr_err("%s() get sound card info failed:%d\n",
+                      __func__, ret);
+               return ret;
+       }
+
        ret = snd_soc_register_card(card);
 
        if (ret)
-               printk("%s() register card failed:%d\n", __FUNCTION__, ret);
+               pr_err("%s() register card failed:%d\n",
+                      __func__, ret);
 
        return ret;
 }
@@ -163,20 +116,21 @@ static int rockchip_hdmi_spdif_audio_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_OF
 static const struct of_device_id rockchip_hdmi_spdif_of_match[] = {
-        { .compatible = "rockchip-hdmi-spdif"},
-        {},
+       { .compatible = "rockchip-hdmi-spdif"},
+       {},
 };
 MODULE_DEVICE_TABLE(of, rockchip_hdmi_spdif_of_match);
 #endif /* CONFIG_OF */
 
 static struct platform_driver rockchip_hdmi_spdif_audio_driver = {
-        .driver         = {
-                .name   = "rockchip-hdmi-spdif",
-                .owner  = THIS_MODULE,
-                .of_match_table = of_match_ptr(rockchip_hdmi_spdif_of_match),
-        },
-        .probe          = rockchip_hdmi_spdif_audio_probe,
-        .remove         = rockchip_hdmi_spdif_audio_remove,
+       .driver         = {
+               .name   = "rockchip-hdmi-spdif",
+               .owner  = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+               .of_match_table = of_match_ptr(rockchip_hdmi_spdif_of_match),
+       },
+       .probe          = rockchip_hdmi_spdif_audio_probe,
+       .remove         = rockchip_hdmi_spdif_audio_remove,
 };
 
 module_platform_driver(rockchip_hdmi_spdif_audio_driver);