2 * rk29_wm8988.c -- SoC audio for rockchip
4 * Driver for rockchip wm8988 audio
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.
14 #include <linux/module.h>
15 #include <linux/device.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"
25 #ifdef CONFIG_MACH_RK_FAC
26 #include <plat/config.h>
27 extern int codec_type;
31 #define DBG(x...) printk(KERN_ERR x)
36 static int rk29_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params)
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;
43 unsigned int pll_out = 0;
44 int div_bclk,div_mclk;
45 // struct clk *general_pll;
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))
53 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
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 );
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);
81 switch(params_rate(params)) {
100 pll_out = 12288000*2;
103 DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
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);
110 // #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER)
111 // snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
113 #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE)
115 div_mclk = pll_out/(params_rate(params)*64) - 1;
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));
127 static struct snd_soc_ops rk29_ops = {
128 .hw_params = rk29_hw_params,
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",
137 .codec_name = "RK610_CODEC.0-0060",
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",
145 .cpu_dai_name = "rockchip-i2s.2",
147 .codec_dai_name = "rk610_codec",
150 static struct snd_soc_card rockchip_rk610_snd_card = {
152 .dai_link = &rk29_dai,
156 static int rockchip_rk610_audio_probe(struct platform_device *pdev)
159 struct snd_soc_card *card = &rockchip_rk610_snd_card;
161 card->dev = &pdev->dev;
163 ret = snd_soc_register_card(card);
166 printk("%s() register card failed:%d\n", __FUNCTION__, ret);
171 static int rockchip_rk610_audio_remove(struct platform_device *pdev)
173 struct snd_soc_card *card = platform_get_drvdata(pdev);
175 snd_soc_unregister_card(card);
181 static const struct of_device_id rockchip_rk610_of_match[] = {
182 { .compatible = "rockchip-rk610", },
185 MODULE_DEVICE_TABLE(of, rockchip_rk610_of_match);
186 #endif /* CONFIG_OF */
188 static struct platform_driver rockchip_rk610_audio_driver = {
190 .name = "rockchip-rk610",
191 .owner = THIS_MODULE,
192 .of_match_table = of_match_ptr(rockchip_rk610_of_match),
194 .probe = rockchip_rk610_audio_probe,
195 .remove = rockchip_rk610_audio_remove,
198 module_platform_driver(rockchip_rk610_audio_driver);
200 /* Module information */
201 MODULE_AUTHOR("rockchip");
202 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
203 MODULE_LICENSE("GPL");