Audio: add dts property(i2s format) and delete them from menuconfig, add sound card...
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_rt3261.c
1 /*
2  * rk29_rt3261.c  --  SoC audio for rockchip
3  *
4  * Driver for rockchip rt3261 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 <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/soc.h>
19 #include <sound/soc-dapm.h>
20 #include <asm/io.h>
21 #include <linux/of.h>
22 #include <linux/of_gpio.h>
23
24 #include "../codecs/rt3261.h"
25 #include "card_info.h"
26 #include "rk_pcm.h"
27 #include "rk_i2s.h"
28
29 #if 0
30 #define DBG(x...)       printk(KERN_INFO x)
31 #else
32 #define DBG(x...)
33 #endif
34
35 static int rockchip_rt3261_hifi_hw_params(struct snd_pcm_substream *substream,
36         struct snd_pcm_hw_params *params)
37 {
38         struct snd_soc_pcm_runtime *rtd = substream->private_data;
39         struct snd_soc_dai *codec_dai = rtd->codec_dai;
40         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
41         unsigned int pll_out = 0;
42         int ret;
43
44         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
45
46         switch(params_rate(params)) {
47                 case 8000:
48                 case 16000:
49                 case 24000:
50                 case 32000:
51                 case 48000:
52                         pll_out = 12288000;
53                         break;
54                 case 11025:
55                 case 22050:
56                 case 44100:
57                         pll_out = 11289600;
58                         break;
59                 default:
60                         DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
61                         return -EINVAL;
62                         break;
63         }
64
65         DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
66
67         /*Set the system clk for codec*/
68         snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29
69         ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29
70         if (ret < 0)
71         {
72                 DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); 
73                 return ret;
74         }
75
76         snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
77         snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
78         snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);// 256k = 48-1  3M=3
79
80         DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));
81  
82         return 0;
83 }
84
85 static int rockchip_rt3261_voice_hw_params(struct snd_pcm_substream *substream,
86         struct snd_pcm_hw_params *params)
87 {
88         struct snd_soc_pcm_runtime *rtd = substream->private_data;
89         struct snd_soc_dai *codec_dai = rtd->codec_dai;
90         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
91         unsigned int pll_out = 0;
92         int ret;
93
94         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
95        
96         ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
97                 SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); 
98
99         switch(params_rate(params)) {
100                 case 8000:
101                 case 16000:
102                 case 24000:
103                 case 32000:
104                 case 48000:
105                         pll_out = 12288000;
106                         break;
107                 case 11025:
108                 case 22050:
109                 case 44100:
110                         pll_out = 11289600;
111                         break;
112                 default:
113                         DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
114                         return -EINVAL;
115                         break;
116         }
117
118         DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
119
120         /*Set the system clk for codec*/
121         snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29
122         ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29
123
124
125         if (ret < 0) {
126                 printk("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); 
127                 return ret;
128         }
129
130         snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
131         //snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
132         //snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
133
134         DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));
135  
136         return 0;
137 }
138
139 static const struct snd_soc_dapm_widget rockchip_rt3261_dapm_widgets[] = {
140         SND_SOC_DAPM_MIC("Mic Jack", NULL),
141         SND_SOC_DAPM_MIC("Headset Jack", NULL), 
142         SND_SOC_DAPM_SPK("Ext Spk", NULL),
143         SND_SOC_DAPM_HP("Headphone Jack", NULL),
144 };
145
146 static const struct snd_soc_dapm_route audio_map[]={
147
148         /* Mic Jack --> MIC_IN*/
149         {"micbias1", NULL, "Mic Jack"},
150         {"MIC1", NULL, "micbias1"},
151         
152         // HP MIC
153         {"micbias1", NULL, "Headset Jack"},
154         {"MIC3", NULL, "micbias1"},
155
156         {"Ext Spk", NULL, "SPOLP"},
157         {"Ext Spk", NULL, "SPOLN"},
158         {"Ext Spk", NULL, "SPORP"},
159         {"Ext Spk", NULL, "SPORN"},
160
161         {"Headphone Jack", NULL, "HPOL"},
162         {"Headphone Jack", NULL, "HPOR"},
163 } ;
164
165 static const struct snd_kcontrol_new rockchip_rt3261_controls[] = {
166         SOC_DAPM_PIN_SWITCH("Mic Jack"),
167         SOC_DAPM_PIN_SWITCH("Headset Jack"),
168         SOC_DAPM_PIN_SWITCH("Ext Spk"),
169         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
170 };
171
172 /*
173  * Logic for a rt3261 as connected on a rockchip board.
174  */
175 static int rockchip_rt3261_init(struct snd_soc_pcm_runtime *rtd)
176 {
177         struct snd_soc_codec *codec = rtd->codec;
178         struct snd_soc_dapm_context *dapm = &codec->dapm;
179
180         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
181
182         snd_soc_add_codec_controls(codec, rockchip_rt3261_controls,
183                         ARRAY_SIZE(rockchip_rt3261_controls));
184
185         /* Add specific widgets */
186         snd_soc_dapm_new_controls(dapm, rockchip_rt3261_dapm_widgets,
187                                   ARRAY_SIZE(rockchip_rt3261_dapm_widgets));
188         /* Set up specific audio path audio_mapnects */
189         snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
190
191         snd_soc_dapm_enable_pin(dapm, "Mic Jack");
192         snd_soc_dapm_enable_pin(dapm, "Headset Jack");
193         snd_soc_dapm_enable_pin(dapm, "Ext Spk");
194         snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
195 #ifdef CONFIG_HDMI
196         extern int hdmi_is_insert(void);
197         extern void codec_set_spk(bool on);         
198         if(hdmi_is_insert())                 
199                 rt3261_codec_set_spk(false);
200 #endif
201
202 #ifdef CONFIG_HDMI_RK30
203         extern int hdmi_get_hotplug(void);
204         if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/)
205                 rt3261_codec_set_spk(false);
206 #endif
207
208         snd_soc_dapm_sync(dapm);
209
210         return 0;
211 }
212
213 static struct snd_soc_ops rockchip_rt3261_hifi_ops = {
214         .hw_params = rockchip_rt3261_hifi_hw_params,
215 };
216
217 static struct snd_soc_ops rockchip_rt3261_voice_ops = {
218         .hw_params = rockchip_rt3261_voice_hw_params,
219 };
220
221 static struct snd_soc_dai_link rockchip_rt3261_dai[] = {
222         {
223                 .name = "RT3261 I2S1",
224                 .stream_name = "RT3261 PCM1",
225                 .codec_dai_name = "rt3261-aif1",
226                 .init = rockchip_rt3261_init,
227                 .ops = &rockchip_rt3261_hifi_ops,
228         },
229         {
230                 .name = "RT3261 I2S2",
231                 .stream_name = "RT3261 PCM2",
232                 .codec_dai_name = "rt3261-aif2",
233                 .ops = &rockchip_rt3261_voice_ops,
234                 .no_pcm = 1,
235         },
236 };
237
238 static struct snd_soc_card rockchip_rt3261_snd_card = {
239         #if defined (CONFIG_SND_SOC_RT3224)
240         .name = "RK_RT3224",
241         #else
242         .name = "RK_RT3261",
243         #endif
244         .owner = THIS_MODULE,
245         .dai_link = rockchip_rt3261_dai,
246         .num_links = ARRAY_SIZE(rockchip_rt3261_dai),
247 };
248
249 /*
250 dts:
251         rockchip-rt3261 {
252                 compatible = "rockchip-rt3261";
253                 dais {
254                         dai0 {
255                                 codec-name = "rt3261.0-001c";
256                                 cpu-dai-name = "rockchip-i2s.1";
257                                 format = "i2s";
258                         };
259
260                         dai1 {
261                                 codec-name = "rt3261.0-001c";
262                                 cpu-dai-name = "rockchip-i2s.1";
263                         };
264                 };
265         };
266 */
267 static int rockchip_rt3261_audio_probe(struct platform_device *pdev)
268 {
269         int ret;
270         struct snd_soc_card *card = &rockchip_rt3261_snd_card;
271
272         card->dev = &pdev->dev;
273
274         ret = rockchip_of_get_sound_card_info(card);
275         if (ret) {
276                 printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
277                 return ret;
278         }
279
280         ret = snd_soc_register_card(card);
281         if (ret)
282                 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
283
284         return ret;
285 }
286
287 static int rockchip_rt3261_audio_remove(struct platform_device *pdev)
288 {
289         struct snd_soc_card *card = platform_get_drvdata(pdev);
290
291         snd_soc_unregister_card(card);
292
293         return 0;
294 }
295
296 #ifdef CONFIG_OF
297 static const struct of_device_id rockchip_rt3261_of_match[] = {
298         { .compatible = "rockchip-rt3261", },
299         {},
300 };
301 MODULE_DEVICE_TABLE(of, rockchip_rt3261_of_match);
302 #endif /* CONFIG_OF */
303
304 static struct platform_driver rockchip_rt3261_audio_driver = {
305         .driver         = {
306                 .name   = "rockchip-rt3261",
307                 .owner  = THIS_MODULE,
308                 .of_match_table = of_match_ptr(rockchip_rt3261_of_match),
309         },
310         .probe          = rockchip_rt3261_audio_probe,
311         .remove         = rockchip_rt3261_audio_remove,
312 };
313
314 module_platform_driver(rockchip_rt3261_audio_driver);
315
316 /* Module information */
317 MODULE_AUTHOR("rockchip");
318 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
319 MODULE_LICENSE("GPL");