ASoC: rockchip: spdif: caculate sclk according BMC(bitphase mark coding).
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_spdif_card.c
1 /*
2  * rk_spdif_card.c  --  spdif card for rockchip
3  *
4  * Copyright 2014 rockchip Co. Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/device.h>
15 #include <linux/of.h>
16 #include <linux/of_gpio.h>
17 #include <linux/clk.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dapm.h>
22
23 #include "card_info.h"
24 #include "rk_pcm.h"
25
26 static int rk_hw_params(struct snd_pcm_substream *substream,
27                         struct snd_pcm_hw_params *params)
28 {
29         struct snd_soc_pcm_runtime *rtd = substream->private_data;
30         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
31         unsigned long sclk;
32         int ret, ratio;
33
34         /* bmc: 2*32*fs*2 = 128fs */
35         ratio = 128;
36
37         switch (params_rate(params)) {
38         case 44100:
39         case 32000:
40         case 48000:
41         case 96000:
42         case 192000:
43                 sclk = params_rate(params) * ratio;
44                 break;
45         default:
46                 pr_err("rk_spdif: params not support\n");
47                 return -EINVAL;
48         }
49
50         ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
51                                      sclk, SND_SOC_CLOCK_IN);
52         if (ret < 0)
53                 return ret;
54
55         return ret;
56 }
57
58 static struct snd_soc_ops rk_spdif_ops = {
59         .hw_params = rk_hw_params,
60 };
61
62 static struct snd_soc_dai_link rk_dai = {
63         .name = "SPDIF",
64         .stream_name = "SPDIF PCM Playback",
65         .codec_dai_name = "rk-hdmi-spdif-hifi",
66         .ops = &rk_spdif_ops,
67 };
68
69 static struct snd_soc_card rockchip_spdif_card = {
70         .name = "RK-SPDIF-CARD",
71         .dai_link = &rk_dai,
72         .num_links = 1,
73 };
74
75 static int rockchip_spdif_card_probe(struct platform_device *pdev)
76 {
77         int ret;
78         struct snd_soc_card *card = &rockchip_spdif_card;
79
80         card->dev = &pdev->dev;
81
82         ret = rockchip_of_get_sound_card_info_(card, false);
83         if (ret) {
84                 pr_err("%s() get sound card info failed:%d\n",
85                        __func__, ret);
86                 return ret;
87         }
88
89         ret = snd_soc_register_card(card);
90
91         if (ret)
92                 pr_err("%s() register card failed:%d\n",
93                        __func__, ret);
94
95         return ret;
96 }
97
98 static int rockchip_spdif_card_remove(struct platform_device *pdev)
99 {
100         struct snd_soc_card *card = platform_get_drvdata(pdev);
101
102         snd_soc_unregister_card(card);
103
104         return 0;
105 }
106
107 #ifdef CONFIG_OF
108 static const struct of_device_id rockchip_spdif_card_of_match[] = {
109         { .compatible = "rockchip-spdif-card"},
110         {},
111 };
112 MODULE_DEVICE_TABLE(of, rockchip_spdif_card_of_match);
113 #endif /* CONFIG_OF */
114
115 static struct platform_driver rockchip_spdif_card_driver = {
116         .driver         = {
117                 .name   = "rockchip-spdif-card",
118                 .owner  = THIS_MODULE,
119                 .pm = &snd_soc_pm_ops,
120                 .of_match_table = of_match_ptr(rockchip_spdif_card_of_match),
121         },
122         .probe          = rockchip_spdif_card_probe,
123         .remove         = rockchip_spdif_card_remove,
124 };
125
126 //module_platform_driver(rockchip_spdif_card_driver);
127
128
129 static int __init rockchip_spdif_init(void)
130 {
131         return platform_driver_register(&rockchip_spdif_card_driver);
132 };
133 late_initcall(rockchip_spdif_init);
134
135 static void __exit rockchip_spdif_exit(void)
136 {
137         platform_driver_unregister(&rockchip_spdif_card_driver);
138 }
139 module_exit(rockchip_spdif_exit);
140
141
142 MODULE_AUTHOR("hzb, <hzb@rock-chips.com>");
143 MODULE_DESCRIPTION("ALSA SoC RK S/PDIF");
144 MODULE_LICENSE("GPL");