Audio: update dai_fmt setting, fix i2s unlock error, rename codec-of-node and cpu...
[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 "card_info.h"
24 #include "rk_pcm.h"
25 #include "rk_i2s.h"
26 #ifdef CONFIG_MACH_RK_FAC
27 #include <plat/config.h>
28 extern int codec_type;
29 #endif
30
31 #if 0
32 #define DBG(x...)       printk(KERN_ERR x)
33 #else
34 #define DBG(x...)
35 #endif
36
37 static int rk29_hw_params(struct snd_pcm_substream *substream,
38         struct snd_pcm_hw_params *params)
39 {
40         struct snd_soc_pcm_runtime *rtd = substream->private_data;
41         struct snd_soc_dai *codec_dai = rtd->codec_dai;
42         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
43         int ret;
44         unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
45         int div_bclk,div_mclk;
46 //      struct clk      *general_pll;
47         
48         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
49
50         /* set codec DAI configuration */
51         ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
52         if (ret < 0) {
53                 printk("%s():failed to set the format for codec side\n", __func__);
54                 return ret;
55         }
56
57         /* set cpu DAI configuration */
58         ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
59         if (ret < 0) {
60                 printk("%s():failed to set the format for cpu side\n", __func__);
61                 return ret;
62         }
63
64         switch(params_rate(params)) {
65         case 8000:
66         case 16000:
67         case 24000:
68         case 32000:
69         case 48000:
70         case 96000:
71             pll_out = 12288000;
72             break;
73         case 11025:
74         case 22050:
75         case 44100:
76         case 88200:
77             pll_out = 11289600;
78             break;
79         case 176400:
80                         pll_out = 11289600*2;
81                 break;
82         case 192000:
83                 pll_out = 12288000*2;
84                 break;
85         default:
86             DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
87             return -EINVAL;
88             break;
89         }
90         DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
91         snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
92         
93         if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS) {
94                 div_bclk = 63;
95                 div_mclk = pll_out/(params_rate(params)*64) - 1;
96                 
97                 DBG("func is%s,pll_out=%d,div_mclk=%d div_bclk\n",
98                                 __FUNCTION__,pll_out,div_mclk, div_bclk);
99                 snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
100                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
101                 snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
102 //              DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));           
103         }
104     return 0;
105 }
106
107 static struct snd_soc_ops rk29_ops = {
108         .hw_params = rk29_hw_params,
109 };
110
111 static struct snd_soc_dai_link rk29_dai = {
112         .name = "RK610_CODEC",
113         .stream_name = "RK610 CODEC PCM",
114         .codec_dai_name = "rk610_codec",
115         .ops = &rk29_ops,
116 };
117 static struct snd_soc_card rockchip_rk610_snd_card = {
118         .name = "RK_RK610",
119         .dai_link = &rk29_dai,
120         .num_links = 1,
121 };
122
123 static int rockchip_rk610_audio_probe(struct platform_device *pdev)
124 {
125         int ret;
126         struct snd_soc_card *card = &rockchip_rk610_snd_card;
127
128         card->dev = &pdev->dev;
129
130         ret = rockchip_of_get_sound_card_info(card);
131         if (ret) {
132                 printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
133                 return ret;
134         }
135
136         ret = snd_soc_register_card(card);
137         if (ret)
138                 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
139
140         return ret;
141 }
142
143 static int rockchip_rk610_audio_remove(struct platform_device *pdev)
144 {
145         struct snd_soc_card *card = platform_get_drvdata(pdev);
146
147         snd_soc_unregister_card(card);
148
149         return 0;
150 }
151
152 #ifdef CONFIG_OF
153 static const struct of_device_id rockchip_rk610_of_match[] = {
154         { .compatible = "rockchip-rk610", },
155         {},
156 };
157 MODULE_DEVICE_TABLE(of, rockchip_rk610_of_match);
158 #endif /* CONFIG_OF */
159
160 static struct platform_driver rockchip_rk610_audio_driver = {
161         .driver         = {
162                 .name   = "rockchip-rk610",
163                 .owner  = THIS_MODULE,
164                 .of_match_table = of_match_ptr(rockchip_rk610_of_match),
165         },
166         .probe          = rockchip_rk610_audio_probe,
167         .remove         = rockchip_rk610_audio_remove,
168 };
169
170 module_platform_driver(rockchip_rk610_audio_driver);
171
172 /* Module information */
173 MODULE_AUTHOR("rockchip");
174 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
175 MODULE_LICENSE("GPL");