Merge branch android-common-3.10
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_rk3026.c
1 /*
2  * rk_rk3026.c  --  SoC audio for rockchip
3  *
4  * Driver for rockchip rk3026 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/rk3026_codec.h"
24 #include "card_info.h"
25 #include "rk_pcm.h"
26 #include "rk_i2s.h"
27
28 #if 0
29 #define DBG(x...)       printk(KERN_INFO x)
30 #else
31 #define DBG(x...)
32 #endif
33
34 static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
35         SND_SOC_DAPM_MIC("Mic Jack", NULL),
36         SND_SOC_DAPM_MIC("Headset Jack", NULL),
37         SND_SOC_DAPM_SPK("Ext Spk", NULL),
38         SND_SOC_DAPM_HP("Headphone Jack", NULL),
39 };
40
41 static const struct snd_soc_dapm_route rk_audio_map[]={
42
43         /* Mic Jack --> MIC_IN*/
44         {"Mic Bias", NULL, "Mic Jack"},
45         {"MICP", NULL, "Mic Bias"},
46         {"MICN", NULL, "Mic Bias"},
47
48         // HP MIC
49         {"Mic Bias", NULL, "Headset Jack"},
50
51         {"Ext Spk", NULL, "HPOUTR"},
52         {"Ext Spk", NULL, "HPOUTL"},
53
54         {"Headphone Jack", NULL, "HPOUTR"},
55         {"Headphone Jack", NULL, "HPOUTL"},
56 } ;
57
58 static const struct snd_kcontrol_new rk_controls[] = {
59         SOC_DAPM_PIN_SWITCH("Mic Jack"),
60         SOC_DAPM_PIN_SWITCH("Headset Jack"),
61         SOC_DAPM_PIN_SWITCH("Ext Spk"),
62         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
63 };
64
65 static int rk3026_init(struct snd_soc_pcm_runtime *rtd)
66 {
67         struct snd_soc_codec *codec = rtd->codec;
68         struct snd_soc_dapm_context *dapm = &codec->dapm;
69
70         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
71
72         mutex_lock(&dapm->card->dapm_mutex);
73
74         snd_soc_dapm_enable_pin(dapm, "Mic Jack");
75         snd_soc_dapm_enable_pin(dapm, "Headset Jack");
76         snd_soc_dapm_enable_pin(dapm, "Ext Spk");
77         snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
78
79         mutex_unlock(&dapm->card->dapm_mutex);
80
81         snd_soc_dapm_sync(dapm);
82
83         return 0;
84 }
85
86 static int rk_hifi_hw_params(struct snd_pcm_substream *substream,
87         struct snd_pcm_hw_params *params)
88 {
89         struct snd_soc_pcm_runtime *rtd = substream->private_data;
90         struct snd_soc_dai *codec_dai = rtd->codec_dai;
91         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
92         unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
93         int ret;
94
95         DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
96
97         /* set codec DAI configuration */
98         ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
99         if (ret < 0) {
100                 printk("%s():failed to set the format for codec side\n", __FUNCTION__);
101                 return ret;
102         }
103
104         /* set cpu DAI configuration */
105         ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
106         if (ret < 0) {
107                 printk("%s():failed to set the format for cpu side\n", __FUNCTION__);
108                 return ret;
109         }
110
111         switch(params_rate(params)) {
112                 case 8000:
113                 case 16000:
114                 case 24000:
115                 case 32000:
116                 case 48000:
117                         pll_out = 12288000;
118                         break;
119                 case 11025:
120                 case 22050:
121                 case 44100:
122                         pll_out = 11289600;
123                         break;
124                 default:
125                         DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
126                         return -EINVAL;
127                         break;
128         }
129
130         DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
131
132         /*Set the system clk for codec*/
133         ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
134         if (ret < 0) {
135                 DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n");
136                 return ret;
137         }
138
139         snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
140         snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
141         snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
142
143         DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));
144
145         return 0;
146 }
147
148 static int rk_voice_hw_params(struct snd_pcm_substream *substream,
149         struct snd_pcm_hw_params *params)
150 {
151         struct snd_soc_pcm_runtime *rtd = substream->private_data;
152         struct snd_soc_dai *codec_dai = rtd->codec_dai;
153         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
154         unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
155         int ret;
156
157         DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
158
159         /* set codec DAI configuration */
160         ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
161         if (ret < 0) {
162                 printk("%s():failed to set the format for codec side\n", __FUNCTION__);
163                 return ret;
164         }
165
166         /* set codec DAI configuration */
167         ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
168                                 SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);
169
170         switch(params_rate(params)) {
171                 case 8000:
172                 case 16000:
173                 case 24000:
174                 case 32000:
175                 case 48000:
176                         pll_out = 12288000;
177                         break;
178                 case 11025:
179                 case 22050:
180                 case 44100:
181                         pll_out = 11289600;
182                         break;
183                 default:
184                         DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
185                         return -EINVAL;
186                         break;
187         }
188
189         /*Set the system clk for codec*/
190         ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
191
192         if (ret < 0) {
193                 printk("rk_voice_hw_params:failed to set the sysclk for codec side\n");
194                 return ret;
195         }
196
197         ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
198
199         return 0;
200 }
201
202 static struct snd_soc_ops rk3026_hifi_ops = {
203         .hw_params = rk_hifi_hw_params,
204 };
205
206 static struct snd_soc_ops rk3026_voice_ops = {
207         .hw_params = rk_voice_hw_params,
208 };
209
210 static struct snd_soc_dai_link rk_dai[] = {
211         {
212                 .name = "RK3026 I2S1",
213                 .stream_name = "RK3026 PCM",
214                 .codec_dai_name = "rk3026-hifi",
215                 .init = rk3026_init,
216                 .ops = &rk3026_hifi_ops,
217         },
218         {
219                 .name = "RK3026 I2S2",
220                 .stream_name = "RK3026 PCM",
221                 .codec_dai_name = "rk3026-voice",
222                 .ops = &rk3026_voice_ops,
223         },
224 };
225
226 static struct snd_soc_card rockchip_rk3026_snd_card = {
227         .name = "RK_RK3026",
228         .dai_link = rk_dai,
229         .num_links = 2,
230         .controls = rk_controls,
231         .num_controls = ARRAY_SIZE(rk_controls),
232         .dapm_widgets    = rk_dapm_widgets,
233         .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets),
234         .dapm_routes    = rk_audio_map,
235         .num_dapm_routes = ARRAY_SIZE(rk_audio_map),
236 };
237
238 static int rockchip_rk3026_audio_probe(struct platform_device *pdev)
239 {
240         int ret;
241         struct snd_soc_card *card = &rockchip_rk3026_snd_card;
242
243         card->dev = &pdev->dev;
244
245         ret = rockchip_of_get_sound_card_info(card);
246         if (ret) {
247                 printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
248                 return ret;
249         }
250
251         ret = snd_soc_register_card(card);
252         if (ret)
253                 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
254
255         return ret;
256 }
257
258 static int rockchip_rk3026_audio_remove(struct platform_device *pdev)
259 {
260         struct snd_soc_card *card = platform_get_drvdata(pdev);
261
262         snd_soc_unregister_card(card);
263
264         return 0;
265 }
266
267 #ifdef CONFIG_OF
268 static const struct of_device_id rockchip_rk3026_of_match[] = {
269         { .compatible = "rockchip-rk3026", },
270         {},
271 };
272 MODULE_DEVICE_TABLE(of, rockchip_rk3026_of_match);
273 #endif /* CONFIG_OF */
274
275 static struct platform_driver rockchip_rk3026_audio_driver = {
276         .driver         = {
277                 .name   = "rockchip-rk3026",
278                 .owner  = THIS_MODULE,
279                 .pm = &snd_soc_pm_ops,
280                 .of_match_table = of_match_ptr(rockchip_rk3026_of_match),
281         },
282         .probe          = rockchip_rk3026_audio_probe,
283         .remove         = rockchip_rk3026_audio_remove,
284 };
285
286 module_platform_driver(rockchip_rk3026_audio_driver);
287
288 /* Module information */
289 MODULE_AUTHOR("rockchip");
290 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
291 MODULE_LICENSE("GPL");