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