20238edfda838cec61d72d00652b1d39cb79c3d8
[firefly-linux-kernel-4.4.55.git] / sound / soc / rk29 / rk29_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 <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 <mach/hardware.h>
22 #include "../codecs/rk610_codec.h"
23 #include "rk29_pcm.h"
24 #include "rk29_i2s.h"
25
26 #if 0
27 #define DBG(x...)       printk(KERN_ERR x)
28 #else
29 #define DBG(x...)
30 #endif
31
32 static int rk29_hw_params(struct snd_pcm_substream *substream,
33         struct snd_pcm_hw_params *params)
34 {
35         struct snd_soc_pcm_runtime *rtd = substream->private_data;
36         struct snd_soc_dai *codec_dai = rtd->codec_dai;
37         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
38         int ret;
39         unsigned int pll_out = 0; 
40         int div_bclk,div_mclk;
41 //      struct clk      *general_pll;
42         
43         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
44         /*by Vincent Hsiung for EQ Vol Change*/
45         #define HW_PARAMS_FLAG_EQVOL_ON 0x21
46         #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
47         if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
48         {
49                 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
50         }
51         else
52         {
53                 /* set codec DAI configuration */
54                 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
55                 #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
56                 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
57                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 
58                 #elif defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
59                 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
60                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
61                 #endif
62                 if (ret < 0)
63                         return ret; 
64                 /* set cpu DAI configuration */
65                 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
66                 #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
67                 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
68                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
69                 #elif defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
70                 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
71                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 
72                 #endif          
73                 if (ret < 0)
74                         return ret;
75         }
76
77         switch(params_rate(params)) {
78         case 8000:
79         case 16000:
80         case 24000:
81         case 32000:
82         case 48000:
83         case 96000:
84             pll_out = 12288000;
85             break;
86         case 11025:
87         case 22050:
88         case 44100:
89         case 88200:
90             pll_out = 11289600;
91             break;
92         case 176400:
93                         pll_out = 11289600*2;
94                 break;
95         case 192000:
96                 pll_out = 12288000*2;
97                 break;
98         default:
99             DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
100             return -EINVAL;
101             break;
102         }
103         DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
104         snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
105         
106 //      #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)  
107 //              snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
108 //      #endif  
109         #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
110                 div_bclk = 63;
111                 div_mclk = pll_out/(params_rate(params)*64) - 1;
112                 
113                 DBG("func is%s,pll_out=%d,div_mclk=%d div_bclk\n",
114                                 __FUNCTION__,pll_out,div_mclk, div_bclk);
115                 snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
116                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
117                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
118 //              DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));           
119         #endif
120     return 0;
121 }
122
123 static struct snd_soc_ops rk29_ops = {
124         .hw_params = rk29_hw_params,
125 };
126
127 static struct snd_soc_dai_link rk29_dai = {
128         .name = "RK610_CODEC",
129         .stream_name = "RK610 CODEC PCM",
130 #if defined(CONFIG_MACH_RK3168_DS1006H)|| defined(CONFIG_MACH_RK3168_LR097)
131         .codec_name = "RK610_CODEC.4-0060",
132 #else
133         .codec_name = "RK610_CODEC.0-0060",
134 #endif
135         .platform_name = "rockchip-audio",
136 #if defined(CONFIG_SND_RK29_SOC_I2S_8CH)        
137         .cpu_dai_name = "rk29_i2s.0",
138 #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
139         .cpu_dai_name = "rk29_i2s.1",
140 #else   
141         .cpu_dai_name = "rk29_i2s.2",   
142 #endif
143         .codec_dai_name = "rk610_codec",
144         .ops = &rk29_ops,
145 };
146 static struct snd_soc_card snd_soc_card_rk29 = {
147         .name = "RK29_RK610",
148         .dai_link = &rk29_dai,
149         .num_links = 1,
150 };
151
152
153 static struct platform_device *rk29_snd_device;
154
155 static int __init audio_card_init(void)
156 {
157         int ret =0;     
158         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
159         rk29_snd_device = platform_device_alloc("soc-audio", -1);
160         if (!rk29_snd_device) {
161                 printk("[%s] platform device allocation failed\n", __FUNCTION__);
162                 ret = -ENOMEM;
163                 return ret;
164         }
165         platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);
166
167         ret = platform_device_add(rk29_snd_device);
168         if (ret) {
169                 DBG("platform device add failed\n");
170                 platform_device_put(rk29_snd_device);
171         }
172         return ret;
173 }
174 static void __exit audio_card_exit(void)
175 {
176         platform_device_unregister(rk29_snd_device);
177 }
178
179 module_init(audio_card_init);
180 module_exit(audio_card_exit);
181 /* Module information */
182 MODULE_AUTHOR("rockchip");
183 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
184 MODULE_LICENSE("GPL");