Merge remote-tracking branch 'origin/upstream/linux-linaro-lsk-v3.10-android' into...
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_jetta_codec.c
1 /*
2  * rk29_wm8988.c  --  SoC audio for rockchip
3  *
4  * Driver for rockchip wm8988 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 #include "../codecs/rk610_codec.h"
23 #include "rk_pcm.h"
24 #include "rk29_i2s.h"
25 #ifdef CONFIG_MACH_RK_FAC
26 #include <plat/config.h>
27 extern int codec_type;
28 #endif
29
30 #if 0
31 #define DBG(x...)       printk(KERN_ERR x)
32 #else
33 #define DBG(x...)
34 #endif
35
36 static int rk29_hw_params(struct snd_pcm_substream *substream,
37         struct snd_pcm_hw_params *params)
38 {
39         struct snd_soc_pcm_runtime *rtd = substream->private_data;
40         struct snd_soc_dai *codec_dai = rtd->codec_dai;
41         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42         int ret;
43         unsigned int pll_out = 0; 
44         int div_bclk,div_mclk;
45 //      struct clk      *general_pll;
46         
47         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
48         /*by Vincent Hsiung for EQ Vol Change*/
49         #define HW_PARAMS_FLAG_EQVOL_ON 0x21
50         #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
51         if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
52         {
53                 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
54         }
55         else
56         {
57                 /* set codec DAI configuration */
58                 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
59                 #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) 
60                 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
61                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 
62                 #elif defined (CONFIG_SND_RK_CODEC_SOC_MASTER) 
63                 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
64                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
65                 #endif
66                 if (ret < 0)
67                         return ret; 
68                 /* set cpu DAI configuration */
69                 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
70                 #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) 
71                 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
72                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
73                 #elif defined (CONFIG_SND_RK_CODEC_SOC_MASTER) 
74                 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
75                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 
76                 #endif          
77                 if (ret < 0)
78                         return ret;
79         }
80
81         switch(params_rate(params)) {
82         case 8000:
83         case 16000:
84         case 24000:
85         case 32000:
86         case 48000:
87         case 96000:
88             pll_out = 12288000;
89             break;
90         case 11025:
91         case 22050:
92         case 44100:
93         case 88200:
94             pll_out = 11289600;
95             break;
96         case 176400:
97                         pll_out = 11289600*2;
98                 break;
99         case 192000:
100                 pll_out = 12288000*2;
101                 break;
102         default:
103             DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
104             return -EINVAL;
105             break;
106         }
107         DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
108         snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
109         
110 //      #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER)    
111 //              snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
112 //      #endif  
113         #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE)
114                 div_bclk = 63;
115                 div_mclk = pll_out/(params_rate(params)*64) - 1;
116                 
117                 DBG("func is%s,pll_out=%d,div_mclk=%d div_bclk\n",
118                                 __FUNCTION__,pll_out,div_mclk, div_bclk);
119                 snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
120                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
121                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
122 //              DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));           
123         #endif
124     return 0;
125 }
126
127 static struct snd_soc_ops rk29_ops = {
128         .hw_params = rk29_hw_params,
129 };
130
131 static struct snd_soc_dai_link rk29_dai = {
132         .name = "RK610_CODEC",
133         .stream_name = "RK610 CODEC PCM",
134 #if defined(CONFIG_MACH_RK3168_DS1006H)|| defined(CONFIG_MACH_RK3168_LR097)
135         .codec_name = "RK610_CODEC.4-0060",
136 #else
137         .codec_name = "RK610_CODEC.0-0060",
138 #endif
139         .platform_name = "rockchip-pcm",
140 #if defined(CONFIG_SND_RK_SOC_I2S_8CH)  
141         .cpu_dai_name = "rockchip-i2s.0",
142 #elif defined(CONFIG_SND_RK_SOC_I2S_2CH)
143         .cpu_dai_name = "rockchip-i2s.1",
144 #else   
145         .cpu_dai_name = "rockchip-i2s.2",       
146 #endif
147         .codec_dai_name = "rk610_codec",
148         .ops = &rk29_ops,
149 };
150 static struct snd_soc_card rockchip_rk610_snd_card = {
151         .name = "RK_RK610",
152         .dai_link = &rk29_dai,
153         .num_links = 1,
154 };
155
156 static int rockchip_rk610_audio_probe(struct platform_device *pdev)
157 {
158         int ret;
159         struct snd_soc_card *card = &rockchip_rk610_snd_card;
160
161         card->dev = &pdev->dev;
162
163         ret = snd_soc_register_card(card);
164
165         if (ret)
166                 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
167
168         return ret;
169 }
170
171 static int rockchip_rk610_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_rk610_of_match[] = {
182         { .compatible = "rockchip-rk610", },
183         {},
184 };
185 MODULE_DEVICE_TABLE(of, rockchip_rk610_of_match);
186 #endif /* CONFIG_OF */
187
188 static struct platform_driver rockchip_rk610_audio_driver = {
189         .driver         = {
190                 .name   = "rockchip-rk610",
191                 .owner  = THIS_MODULE,
192                 .of_match_table = of_match_ptr(rockchip_rk610_of_match),
193         },
194         .probe          = rockchip_rk610_audio_probe,
195         .remove         = rockchip_rk610_audio_remove,
196 };
197
198 module_platform_driver(rockchip_rk610_audio_driver);
199
200 /* Module information */
201 MODULE_AUTHOR("rockchip");
202 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
203 MODULE_LICENSE("GPL");