ASoC: rockchip: spdif: caculate sclk according BMC(bitphase mark coding).
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_aic3111.c
1 /*
2  * rk29_tlv320dac3100.c  --  SoC audio for rockchip
3  *
4  * Driver for rockchip tlv320aic3100 audio
5  *
6  *  This program is free software; you can redistribute  it and/or modify it
7  *  under  the terms of  the GNU General  Public License as published by the
8  *  Free Software Foundation;  either version 2 of the  License, or (at your
9  *  option) any later version.
10  *
11  *
12  */
13
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/of.h>
17 #include <linux/of_gpio.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 "../codecs/tlv320aic3111.h"
24 #include "card_info.h"
25 #include "rk_pcm.h"
26 #include "rk_i2s.h"
27
28 #if 0
29 #define AIC_DBG(x...)   printk(KERN_INFO x)
30 #else
31 #define AIC_DBG(x...)   do { } while (0)
32 #endif
33
34 #ifdef CODECHPDET
35         #define HP_DET_PIN              RK29_PIN6_PA0
36 #endif
37
38
39
40 static int rk29_hw_params(struct snd_pcm_substream *substream,
41         struct snd_pcm_hw_params *params)
42 {
43         struct snd_soc_pcm_runtime *rtd = substream->private_data;
44         struct snd_soc_dai *codec_dai = rtd->codec_dai;
45         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
46         unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
47         int ret;
48
49         AIC_DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
50
51         /* set codec DAI configuration */
52         ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
53         if (ret < 0) {
54                 printk("%s():failed to set the format for codec side\n", __FUNCTION__);
55                 return ret;
56         }
57
58         /* set cpu DAI configuration */
59         ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
60         if (ret < 0) {
61                 printk("%s():failed to set the format for cpu side\n", __FUNCTION__);
62                 return ret;
63         }
64
65         switch(params_rate(params)) {
66         case 8000:
67         case 16000:
68         case 24000:
69         case 32000:
70         case 48000:
71                         pll_out = 12288000;
72                         break;
73         case 11025:
74         case 22050:
75         case 44100:
76                         pll_out = 11289600;
77                         break;
78         default:
79                         printk("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
80                         return -EINVAL;
81                         break;
82         }
83         AIC_DBG("Enter:%s, %d, rate=%d, pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params), pll_out);
84         //pll_out = 12000000;
85         snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
86         snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
87
88         return 0;
89 }
90
91 static const struct snd_soc_dapm_widget dac3100_dapm_widgets[] = {
92 /*      SND_SOC_DAPM_LINE("Audio Out", NULL),
93         SND_SOC_DAPM_LINE("Line in", NULL),
94         SND_SOC_DAPM_MIC("Micn", NULL),
95         SND_SOC_DAPM_MIC("Micp", NULL),*/
96 };
97
98 static const struct snd_soc_dapm_route audio_map[]= {
99 /*      {"Audio Out", NULL, "HPL"},
100         {"Audio Out", NULL, "HPR"},
101         {"Line in", NULL, "RINPUT1"},
102         {"Line in", NULL, "LINPUT1"},
103         {"Micn", NULL, "RINPUT2"},
104         {"Micp", NULL, "LINPUT2"},*/
105 };
106
107 /*
108  * Logic for a tlv320dac3100 as connected on a rockchip board.
109  */
110 static int rk29_aic3111_init(struct snd_soc_pcm_runtime *rtd)
111 {
112         struct snd_soc_codec *codec = rtd->codec;
113         struct snd_soc_dapm_context *dapm = &codec->dapm;
114
115         AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
116
117         /* Add specific widgets */
118         snd_soc_dapm_new_controls(dapm, dac3100_dapm_widgets,
119                                   ARRAY_SIZE(dac3100_dapm_widgets));
120
121         /* Set up specific audio path audio_mapnects */
122         snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
123                 AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
124         snd_soc_dapm_nc_pin(dapm, "HPL");
125                 AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
126         snd_soc_dapm_nc_pin(dapm, "HPR");
127                 AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
128         snd_soc_dapm_sync(dapm);
129                 AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
130         return 0;
131 }
132
133 static struct snd_soc_ops rk29_ops = {
134           .hw_params = rk29_hw_params,
135 };
136
137 static struct snd_soc_dai_link rk29_dai = {
138         .name = "AIC3111",
139         .stream_name = "AIC3111 PCM",
140         .codec_dai_name = "AIC3111 HiFi",
141         .init = rk29_aic3111_init,
142         .ops = &rk29_ops,
143 };
144
145 static struct snd_soc_card rockchip_aic3111_snd_card = {
146         .name = "RK_AIC3111",
147         .dai_link = &rk29_dai,
148         .num_links = 1,
149 };
150
151 static int rockchip_aic3111_audio_probe(struct platform_device *pdev)
152 {
153         int ret;
154         struct snd_soc_card *card = &rockchip_aic3111_snd_card;
155
156         card->dev = &pdev->dev;
157
158         ret = rockchip_of_get_sound_card_info(card);
159         if (ret) {
160                 printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
161                 return ret;
162         }
163
164         ret = snd_soc_register_card(card);
165         if (ret)
166                 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
167
168         return ret;
169 }
170
171 static int rockchip_aic3111_audio_remove(struct platform_device *pdev)
172 {
173         struct snd_soc_card *card = platform_get_drvdata(pdev);
174
175         snd_soc_unregister_card(card);
176
177         return 0;
178 }
179
180 #ifdef CONFIG_OF
181 static const struct of_device_id rockchip_aic3111_of_match[] = {
182         { .compatible = "rockchip-aic3111", },
183         {},
184 };
185 MODULE_DEVICE_TABLE(of, rockchip_aic3111_of_match);
186 #endif /* CONFIG_OF */
187
188 static struct platform_driver rockchip_aic3111_audio_driver = {
189         .driver         = {
190                 .name   = "rockchip-aic3111",
191                 .owner  = THIS_MODULE,
192                 .pm = &snd_soc_pm_ops,
193                 .of_match_table = of_match_ptr(rockchip_aic3111_of_match),
194         },
195         .probe          = rockchip_aic3111_audio_probe,
196         .remove         = rockchip_aic3111_audio_remove,
197 };
198
199 module_platform_driver(rockchip_aic3111_audio_driver);
200
201 /* Module information */
202 MODULE_AUTHOR("rockchip");
203 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
204 MODULE_LICENSE("GPL");