rk2928 acodec:
authorZheng Yang <zhengyang@rock-chips.com>
Wed, 17 Oct 2012 10:03:35 +0000 (18:03 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Wed, 17 Oct 2012 10:03:35 +0000 (18:03 +0800)
1. fix sometimes only one channel autio output error.
2. fix pop sound when open PGA.

sound/soc/codecs/rk2928_codec.c
sound/soc/codecs/rk2928_codec.h

index 75347e6b421763f9278e57cbed4a2944e9f0973d..dc77d77416b5a82f964cca900fe4040280f55ab7 100755 (executable)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
+#include <asm/delay.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -58,8 +59,6 @@ static const struct snd_soc_dapm_widget rk2928_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("DACR", "HIFI Playback", CODEC_REG_POWER, 4, 1),
        SND_SOC_DAPM_PGA("DACL Amp", CODEC_REG_DAC_GAIN, 2, 0, NULL, 0),
        SND_SOC_DAPM_PGA("DACR Amp", CODEC_REG_DAC_GAIN, 0, 0, NULL, 0),
-//     SND_SOC_DAPM_OUT_DRV("DACL Drv", CODEC_REG_DAC_MUTE, 1, 1, NULL, 0),
-//     SND_SOC_DAPM_OUT_DRV("DACR Drv", CODEC_REG_DAC_MUTE, 0, 1, NULL, 0),
        SND_SOC_DAPM_OUTPUT("SPKL"),
        SND_SOC_DAPM_OUTPUT("SPKR"),
        SND_SOC_DAPM_ADC("ADCL", "HIFI Capture", CODEC_REG_POWER, 3, 1),
@@ -71,8 +70,6 @@ static const struct snd_soc_dapm_widget rk2928_dapm_widgets[] = {
 static const struct snd_soc_dapm_route rk2928_audio_map[] = {
        {"SPKL", "DACL Amp", "DACL"},
        {"SPKR", "DACR Amp", "DACR"},
-//     {"SPKL", NULL, "DACL Drv"},
-//     {"SPKR", NULL, "DACR Drv"},
        {"ADCL", NULL, "MICL"},
        {"ADCR", NULL, "MICR"},
 };
@@ -82,8 +79,6 @@ static const struct snd_soc_dapm_widget rk2926_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("DACR", "HIFI Playback", CODEC_REG_POWER, 4, 1),
        SND_SOC_DAPM_PGA("DACL Amp", CODEC_REG_DAC_GAIN, 2, 0, NULL, 0),
        SND_SOC_DAPM_PGA("DACR Amp", CODEC_REG_DAC_GAIN, 0, 0, NULL, 0),
-//     SND_SOC_DAPM_OUT_DRV("DACL Drv", CODEC_REG_DAC_MUTE, 1, 1, NULL, 0),
-//     SND_SOC_DAPM_OUT_DRV("DACR Drv", CODEC_REG_DAC_MUTE, 0, 1, NULL, 0),
        SND_SOC_DAPM_OUTPUT("SPKL"),
        SND_SOC_DAPM_OUTPUT("SPKR"),
        SND_SOC_DAPM_ADC("ADCR", "HIFI Capture", CODEC_REG_POWER, 2, 1),
@@ -93,8 +88,6 @@ static const struct snd_soc_dapm_widget rk2926_dapm_widgets[] = {
 static const struct snd_soc_dapm_route rk2926_audio_map[] = {
        {"SPKL", "DACL Amp", "DACL"},
        {"SPKR", "DACR Amp", "DACR"},
-//     {"SPKL", NULL, "DACL Drv"},
-//     {"SPKR", NULL, "DACR Drv"},
        {"ADCR", NULL, "MICR"},
 };
 
@@ -110,7 +103,7 @@ static int rk2928_write(struct snd_soc_codec *codec, unsigned int reg, unsigned
        DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, reg, value);
        writel(value, rk2928_data.regbase + reg*4);
        if( (reg == CODEC_REG_POWER) && ( (value & m_PD_DAC) == 0)) {
-               msleep(80);
+               msleep(100);
        }
        return 0;
 }
@@ -163,7 +156,7 @@ static int rk2928_audio_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_codec *codec = rtd->codec;
        struct rk2928_codec_data *priv = snd_soc_codec_get_drvdata(codec);
        int err = 0;
-
+       int data, pd_adc;
        DBG("%s cmd 0x%x", __FUNCTION__, cmd);
        
        switch (cmd) {
@@ -172,10 +165,52 @@ static int rk2928_audio_trigger(struct snd_pcm_substream *substream, int cmd,
                case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 //                             rk2928_write(codec, CODEC_REG_DAC_GAIN, v_GAIN_DAC(DAC_GAIN_3DB_P));
-                               if(!rk2928_data.hdmi_enable)
+                               if(!rk2928_data.hdmi_enable) {
+                                       data = rk2928_read(codec, CODEC_REG_POWER);
+                                       if(soc_is_rk2928g()){
+                                               if( (data & m_PD_ADC) == 0) {
+                                                       data &= ~m_PD_ADC;
+                                                       data |= v_PD_ADC(1);
+                                                       pd_adc = 1;
+                                               }
+                                               else
+                                                       pd_adc = 0;
+                                       }
+                                       else{
+                                               if( (data & m_PD_ADC_R) == 0) {
+                                                       data &= ~m_PD_ADC_R;
+                                                       data |= v_PD_ADC_R(1);
+                                                       pd_adc = 1;
+                                               }
+                                               else
+                                                       pd_adc = 0;
+                                       }
+                                       if(pd_adc == 1) {
+                                               DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
+                                               writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
+                                               udelay(100);                                            
+                                       }
+                                       rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
+                                       udelay(100);
+                                       rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
+                                       
+                                       if(pd_adc == 1) {
+                                               udelay(100);
+                                               data = rk2928_read(codec, CODEC_REG_POWER);
+                                               if( soc_is_rk2928g() ) {
+                                                       data &= ~m_PD_ADC;
+                                                       data |= v_PD_ADC(0);
+                                               }
+                                               else {
+                                                       data &= ~m_PD_ADC_R;
+                                                       data |= v_PD_ADC_R(0);
+                                               }
+                                               DBG("%s reg 0x%02x value 0x%02x", __FUNCTION__, CODEC_REG_POWER, data);
+                                               writel(data, rk2928_data.regbase + CODEC_REG_POWER*4);
+                                       }
+                                       
                                        rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(0));
-                               rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x03);
-                               rk2928_write(codec, CODEC_REG_ADC_SOURCE, 0x00);
+                               }
                                rk2928_data.mute = 0;
                                if(rk2928_data.spkctl != INVALID_GPIO) {
                                        gpio_direction_output(rk2928_data.spkctl, GPIO_HIGH);
@@ -307,15 +342,15 @@ static int rk2928_probe(struct snd_soc_codec *codec)
        // Mute and Power off codec
        rk2928_write(codec, CODEC_REG_DAC_MUTE, v_MUTE_DAC(1));
        rk2928_set_bias_level(codec, SND_SOC_BIAS_OFF);
-        if(soc_is_rk2928g()){  
-               snd_soc_dapm_new_controls(dapm, rk2928_dapm_widgets,
-                       ARRAY_SIZE(rk2928_dapm_widgets));
-               snd_soc_dapm_add_routes(dapm, rk2928_audio_map, ARRAY_SIZE(rk2928_audio_map));
-        }else{
-               snd_soc_dapm_new_controls(dapm, rk2926_dapm_widgets,
-                       ARRAY_SIZE(rk2926_dapm_widgets));
-               snd_soc_dapm_add_routes(dapm, rk2926_audio_map, ARRAY_SIZE(rk2926_audio_map));
-        }
+       if(soc_is_rk2928g()){   
+           snd_soc_dapm_new_controls(dapm, rk2928_dapm_widgets,
+               ARRAY_SIZE(rk2928_dapm_widgets));
+           snd_soc_dapm_add_routes(dapm, rk2928_audio_map, ARRAY_SIZE(rk2928_audio_map));
+       }else{
+           snd_soc_dapm_new_controls(dapm, rk2926_dapm_widgets,
+               ARRAY_SIZE(rk2926_dapm_widgets));
+           snd_soc_dapm_add_routes(dapm, rk2926_audio_map, ARRAY_SIZE(rk2926_audio_map));
+       }
 
        return 0;
        
index a2ca8ff14352122dd7c2fa95df3799b2ae657ba4..604bc6849b703ed24acea85043a0b2563046faf0 100755 (executable)
@@ -23,6 +23,8 @@
 #define CODEC_REG_POWER                        0x0c
        #define m_PD_CODEC                      (0x01)
        #define m_PD_MIC_BIAS           (0x01 << 1)
+       #define m_PD_ADC_R                      (0x01 << 2)
+       #define m_PD_ADC_L                      (0x01 << 3)
        #define m_PD_ADC                        (0x03 << 2)
        #define m_PD_DAC                        (0x03 << 4)
        #define v_PD_CODEC(n)           (n)