dt-bindings: add document for Rockchip RGA module
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_rt3261.c
index fd0f97f375ad41d99e254b18006472a92de661bd..9a2c2b048e7b97b2c9499f6c34fb871ce3e31b7c 100644 (file)
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <asm/io.h>
-#include <mach/hardware.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include "../codecs/rt3261.h"
+#include "card_info.h"
 #include "rk_pcm.h"
-#include "rk29_i2s.h"
-
+#include "rk_i2s.h"
 
 #if 0
 #define        DBG(x...)       printk(KERN_INFO x)
 #define        DBG(x...)
 #endif
 
-static int rk29_hw_params(struct snd_pcm_substream *substream,
+static int rockchip_rt3261_hifi_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       unsigned int pll_out = 0;
+       unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
        int ret;
 
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
-       /*by Vincent Hsiung for EQ Vol Change*/
-       #define HW_PARAMS_FLAG_EQVOL_ON 0x21
-       #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
-       if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))
-       {
-               ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
-               DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       } else {
-                
-               /* set codec DAI configuration */
-               #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) 
-
-               ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-               #endif  
-               #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) 
-
-               ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
-               #endif
-               if (ret < 0)
-                       return ret; 
-
-               /* set cpu DAI configuration */
-               #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) 
-               ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-               #endif  
-               #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) 
-               ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 
-               #endif          
-               if (ret < 0)
-                       return ret;
+       DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
+       if (ret < 0) {
+               printk("%s():failed to set the format for codec side\n", __FUNCTION__);
+               return ret;
+       }
+
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
+       if (ret < 0) {
+               printk("%s():failed to set the format for cpu side\n", __FUNCTION__);
+               return ret;
        }
 
        switch(params_rate(params)) {
@@ -116,19 +96,23 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int rt3261_voice_hw_params(struct snd_pcm_substream *substream,
+static int rockchip_rt3261_voice_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       unsigned int pll_out = 0;
+       unsigned int pll_out = 0, dai_fmt = rtd->dai_link->dai_fmt;
        int ret;
 
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
-       
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); 
+       DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
+       if (ret < 0) {
+               printk("%s():failed to set the format for codec side\n", __FUNCTION__);
+               return ret;
+       }
 
        switch(params_rate(params)) {
                case 8000:
@@ -170,7 +154,7 @@ static int rt3261_voice_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static const struct snd_soc_dapm_widget rt3261_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget rockchip_rt3261_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Mic Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Jack", NULL), 
        SND_SOC_DAPM_SPK("Ext Spk", NULL),
@@ -196,7 +180,7 @@ static const struct snd_soc_dapm_route audio_map[]={
        {"Headphone Jack", NULL, "HPOR"},
 } ;
 
-static const struct snd_kcontrol_new rk_controls[] = {
+static const struct snd_kcontrol_new rockchip_rt3261_controls[] = {
        SOC_DAPM_PIN_SWITCH("Mic Jack"),
        SOC_DAPM_PIN_SWITCH("Headset Jack"),
        SOC_DAPM_PIN_SWITCH("Ext Spk"),
@@ -206,121 +190,147 @@ static const struct snd_kcontrol_new rk_controls[] = {
 /*
  * Logic for a rt3261 as connected on a rockchip board.
  */
-static int rk29_rt3261_init(struct snd_soc_pcm_runtime *rtd)
+static int rockchip_rt3261_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
 
-       snd_soc_add_codec_controls(codec, rk_controls,
-                       ARRAY_SIZE(rk_controls));
-
-       /* Add specific widgets */
-       snd_soc_dapm_new_controls(dapm, rt3261_dapm_widgets,
-                                 ARRAY_SIZE(rt3261_dapm_widgets));
-       /* Set up specific audio path audio_mapnects */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+       mutex_lock(&dapm->card->dapm_mutex);
 
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
        snd_soc_dapm_enable_pin(dapm, "Headset Jack");
        snd_soc_dapm_enable_pin(dapm, "Ext Spk");
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
-#ifdef CONFIG_HDMI
-       extern int hdmi_is_insert(void);
-       extern void codec_set_spk(bool on);         
-       if(hdmi_is_insert())                 
-               codec_set_spk(false);
-#endif
 
-#ifdef CONFIG_HDMI_RK30
-       extern int hdmi_get_hotplug(void);
-       if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/)
-               codec_set_spk(false);
-#endif
+       mutex_unlock(&dapm->card->dapm_mutex);
 
        snd_soc_dapm_sync(dapm);
 
        return 0;
 }
 
-static struct snd_soc_ops rk29_ops = {
-       .hw_params = rk29_hw_params,
+static struct snd_soc_ops rockchip_rt3261_hifi_ops = {
+       .hw_params = rockchip_rt3261_hifi_hw_params,
 };
 
-static struct snd_soc_ops rt3261_voice_ops = {
-       .hw_params = rt3261_voice_hw_params,
+static struct snd_soc_ops rockchip_rt3261_voice_ops = {
+       .hw_params = rockchip_rt3261_voice_hw_params,
 };
 
-static struct snd_soc_dai_link rk29_dai[] = {
+static struct snd_soc_dai_link rockchip_rt3261_dai[] = {
        {
                .name = "RT3261 I2S1",
-               .stream_name = "RT3261 PCM",
-               .codec_name = "rt3261.0-001c",
-               .platform_name = "rockchip-audio",
-               #if defined(CONFIG_SND_RK_SOC_I2S_8CH)    
-                       .cpu_dai_name = "rk_i2s.0",
-               #elif defined(CONFIG_SND_RK_SOC_I2S_2CH)
-                       .cpu_dai_name = "rk_i2s.1",
-               #endif
+               .stream_name = "RT3261 PCM1",
                .codec_dai_name = "rt3261-aif1",
-               .init = rk29_rt3261_init,
-               .ops = &rk29_ops,
+               .init = rockchip_rt3261_init,
+               .ops = &rockchip_rt3261_hifi_ops,
        },
        {
                .name = "RT3261 I2S2",
-               .stream_name = "RT3261 PCM",
-               .codec_name = "rt3261.0-001c",
-               .platform_name = "rockchip-audio",
-               #if defined(CONFIG_SND_RK_SOC_I2S_8CH)    
-                       .cpu_dai_name = "rk_i2s.0",
-               #elif defined(CONFIG_SND_RK_SOC_I2S_2CH)
-                       .cpu_dai_name = "rk_i2s.1",
-               #endif 
+               .stream_name = "RT3261 PCM2",
                .codec_dai_name = "rt3261-aif2",
-               .ops = &rt3261_voice_ops,
+               .ops = &rockchip_rt3261_voice_ops,
        },
 };
 
-static struct snd_soc_card snd_soc_card_rk29 = {
+static struct snd_soc_card rockchip_rt3261_snd_card = {
+       #if defined (CONFIG_SND_SOC_RT3224)
+       .name = "RK_RT3224",
+       #else
        .name = "RK_RT3261",
-       .dai_link = rk29_dai,
-       .num_links = 2,
+       #endif
+       .owner = THIS_MODULE,
+       .dai_link = rockchip_rt3261_dai,
+       .num_links = ARRAY_SIZE(rockchip_rt3261_dai),
+       .controls = rockchip_rt3261_controls,
+       .num_controls = ARRAY_SIZE(rockchip_rt3261_controls),
+       .dapm_widgets    = rockchip_rt3261_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(rockchip_rt3261_dapm_widgets),
+       .dapm_routes    = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
-static struct platform_device *rk29_snd_device;
-
-static int __init audio_card_init(void)
+/*
+dts:
+       rockchip-rt3261 {
+               compatible = "rockchip-rt3261";
+               dais {
+                       dai0 {
+                               audio-codec = <&rt3261>;
+                               audio-controller = <&i2s0>;
+                               format = "i2s";
+                               //continuous-clock;
+                               //bitclock-inversion;
+                               //frame-inversion;
+                               //bitclock-master;
+                               //frame-master;
+                       };
+
+                       dai1 {
+                               audio-codec = <&rt3261>;
+                               audio-controller = <&i2s0>;
+                               format = "dsp_a";
+                               //continuous-clock;
+                               bitclock-inversion;
+                               //frame-inversion;
+                               //bitclock-master;
+                               //frame-master;
+                       };
+               };
+       };
+*/
+static int rockchip_rt3261_audio_probe(struct platform_device *pdev)
 {
-       int ret =0;
-
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+       int ret;
+       struct snd_soc_card *card = &rockchip_rt3261_snd_card;
 
-       rk29_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!rk29_snd_device) {
-                 printk("platform device allocation failed\n");
-                 return -ENOMEM;
-       }
+       card->dev = &pdev->dev;
 
-       platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);
-       ret = platform_device_add(rk29_snd_device);
+       ret = rockchip_of_get_sound_card_info(card);
        if (ret) {
-               printk("platform device add failed\n");
-
-               platform_device_put(rk29_snd_device);
+               printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
                return ret;
        }
-               
-        return ret;
+
+       ret = snd_soc_register_card(card);
+       if (ret)
+               printk("%s() register card failed:%d\n", __FUNCTION__, ret);
+
+       return ret;
 }
 
-static void __exit audio_card_exit(void)
+static int rockchip_rt3261_audio_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(rk29_snd_device);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
 }
 
-module_init(audio_card_init);
-module_exit(audio_card_exit);
+#ifdef CONFIG_OF
+static const struct of_device_id rockchip_rt3261_of_match[] = {
+       { .compatible = "rockchip-rt3261", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, rockchip_rt3261_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver rockchip_rt3261_audio_driver = {
+       .driver         = {
+               .name   = "rockchip-rt3261",
+               .owner  = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+               .of_match_table = of_match_ptr(rockchip_rt3261_of_match),
+       },
+       .probe          = rockchip_rt3261_audio_probe,
+       .remove         = rockchip_rt3261_audio_remove,
+};
+
+module_platform_driver(rockchip_rt3261_audio_driver);
+
 /* Module information */
 MODULE_AUTHOR("rockchip");
 MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");