i2s:fix the hdmi no sound sometimes
authorsmj <smj@rock-chips.com>
Thu, 9 Apr 2015 03:22:23 +0000 (11:22 +0800)
committersmj <smj@rock-chips.com>
Thu, 9 Apr 2015 03:35:12 +0000 (11:35 +0800)
    support for hdmi passthrough output

Signed-off-by: smj <smj@rock-chips.com>
drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c [changed mode: 0644->0755]
sound/soc/codecs/rk1000_codec.c
sound/soc/rockchip/rk30_i2s.c
sound/soc/rockchip/rk_hdmi_i2s.c
sound/soc/rockchip/rk_pcm.c
sound/soc/rockchip/rk_rk1000codec.c

old mode 100644 (file)
new mode 100755 (executable)
index b35c424..24b7934
@@ -1372,7 +1372,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
 
        switch (audio->rate) {
        case HDMI_AUDIO_FS_32000:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_32K;
                if (hdmi_dev->tmdsclk >= 594000000)
                        N = N_32K_HIGHCLK;
@@ -1384,7 +1384,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 32);
                break;
        case HDMI_AUDIO_FS_44100:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_441K;
                if (hdmi_dev->tmdsclk >= 594000000)
                        N = N_441K_HIGHCLK;
@@ -1396,7 +1396,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 441);
                break;
        case HDMI_AUDIO_FS_48000:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_48K;
                if (hdmi_dev->tmdsclk >= 594000000)     /*FS_153.6*/
                        N = N_48K_HIGHCLK;
@@ -1408,7 +1408,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 48);
                break;
        case HDMI_AUDIO_FS_88200:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_882K;
                if (hdmi_dev->tmdsclk >= 594000000)
                        N = N_882K_HIGHCLK;
@@ -1420,7 +1420,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 882);
                break;
        case HDMI_AUDIO_FS_96000:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_96K;
                if (hdmi_dev->tmdsclk >= 594000000)     /*FS_153.6*/
                        N = N_96K_HIGHCLK;
@@ -1432,7 +1432,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 96);
                break;
        case HDMI_AUDIO_FS_176400:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_1764K;
                if (hdmi_dev->tmdsclk >= 594000000)
                        N = N_1764K_HIGHCLK;
@@ -1444,7 +1444,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 1764);
                break;
        case HDMI_AUDIO_FS_192000:
-               mclk_fs = FS_64;
+               mclk_fs = FS_128;
                rate = AUDIO_192K;
                if (hdmi_dev->tmdsclk >= 594000000)     /*FS_153.6*/
                        N = N_192K_HIGHCLK;
@@ -1535,8 +1535,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
        /* set channel status register */
        hdmi_msk_reg(hdmi_dev, FC_AUDSCHNLS7,
                     m_AUDIO_SAMPLE_RATE, v_AUDIO_SAMPLE_RATE(rate));
-       /* hdmi_writel(hdmi_dev, FC_AUDSCHNLS2, 0x1); */
-       /* hdmi_writel(hdmi_dev, FC_AUDSCHNLS8, ((~rate) << 4) | 0x2); */
+       hdmi_writel(hdmi_dev, FC_AUDSCHNLS8, ((~rate) << 4) | 0x2);
 
        hdmi_dev_config_aai(hdmi_dev, audio);
 
index bd979cd255a48e522e8eefa6d7e3a72c7dd86fda..ffc0b98a9beea4076b094fc57f2ebc03f210bf3b 100755 (executable)
@@ -613,7 +613,7 @@ static struct snd_soc_dai_ops rk1000_codec_ops = {
        .digital_mute = rk1000_codec_mute,
 };
 
-#define RK1000_CODEC_RATES SNDRV_PCM_RATE_8000_96000
+#define RK1000_CODEC_RATES SNDRV_PCM_RATE_8000_192000
 #define RK1000_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
                                SNDRV_PCM_FMTBIT_S20_3LE |\
                                SNDRV_PCM_FMTBIT_S24_LE)
@@ -623,7 +623,7 @@ static struct snd_soc_dai_driver rk1000_codec_dai[] = {
                .playback = {
                        .stream_name = "Playback",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 8,
                        .rates = RK1000_CODEC_RATES,
                        .formats = RK1000_CODEC_FORMATS,
                },
index bb15f42b3250ef3a476288db195e07dcac976fe3..d66d5ffd9ec17e7adee8dcf0c23dc12bcf059902 100755 (executable)
@@ -44,6 +44,7 @@
 
 #include "rk_pcm.h"
 #include "rk_i2s.h"
+#include "../../../drivers/video/rockchip/hdmi/rockchip-hdmi.h"
 
 #if 0
 #define I2S_DBG(x...) printk(KERN_INFO x)
@@ -82,6 +83,8 @@ extern int hdmi_get_hotplug(void);
 #define hdmi_get_hotplug() 0
 #endif
 
+
+
 static inline struct rk30_i2s_info *to_info(struct snd_soc_dai *dai)
 {
        return snd_soc_dai_get_drvdata(dai);
@@ -283,6 +286,29 @@ out_:
        return ret;
 }
 
+static int SR2FS(int samplerate)
+{
+       switch (samplerate) {
+       case 32000:
+               return HDMI_AUDIO_FS_32000;
+       case 44100:
+               return HDMI_AUDIO_FS_44100;
+       case 48000:
+               return HDMI_AUDIO_FS_48000;
+       case 88200:
+               return HDMI_AUDIO_FS_88200;
+       case 96000:
+               return HDMI_AUDIO_FS_96000;
+       case 176400:
+               return HDMI_AUDIO_FS_176400;
+       case 192000:
+               return HDMI_AUDIO_FS_192000;
+       default:
+               I2S_DBG("SR2FS %d unsupport.", samplerate);
+               return HDMI_AUDIO_FS_44100;
+       }
+}
+
 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
@@ -290,9 +316,9 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
        u32 iismod;
        u32 dmarc;
        unsigned long flags;
+       struct hdmi_audio hdmi_audio_cfg;
 
        I2S_DBG("Enter %s, %d \n", __func__, __LINE__);
-
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                dai->playback_dma_data = &i2s->playback_dma_data;
        else
@@ -315,14 +341,42 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
                iismod |= I2S_DATA_WIDTH(19);
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
                iismod |= I2S_DATA_WIDTH(23);
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                iismod |= I2S_DATA_WIDTH(31);
                break;
        }
+       iismod &= ~CHANNLE_4_EN;
+       switch (params_channels(params)) {
+       case 8:
+               iismod |= CHANNLE_4_EN;
+               break;
+       case 6:
+               iismod |= CHANNEL_3_EN;
+               break;
+       case 4:
+               iismod |= CHANNEL_2_EN;
+               break;
+       case 2:
+               iismod |= CHANNEL_1_EN;
+               break;
+       default:
+               I2S_DBG("%d channels not supported\n",
+                       params_channels(params));
+               return -EINVAL;
+       }
+       /* set  hdmi codec params */
+       if (HW_PARAMS_FLAG_NLPCM == params->flags)
+               hdmi_audio_cfg.type = HDMI_AUDIO_NLPCM;
+       else
+               hdmi_audio_cfg.type = HDMI_AUDIO_LPCM;
+       hdmi_audio_cfg.channel = params_channels(params);
+       hdmi_audio_cfg.rate = SR2FS(params_rate(params));
+       hdmi_audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit;
+       hdmi_config_audio(&hdmi_audio_cfg);
 
-//     writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
        dmarc = readl(&(pheadi2s->I2S_DMACR));
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -445,7 +499,7 @@ static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
        .set_sysclk = rockchip_i2s_set_sysclk,
 };
 
-#define ROCKCHIP_I2S_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define ROCKCHIP_I2S_STEREO_RATES SNDRV_PCM_RATE_8000_192000
 #define ROCKCHIP_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
 
index fe9c716861e05ef1bbf9bcc95d273399613ed3db..2d4c63daae7266c0b284e29db4d767b901e246b8 100755 (executable)
@@ -75,7 +75,7 @@ static int hdmi_i2s_hifi_hw_params(struct snd_pcm_substream *substream,
                __func__, __LINE__,
                params_rate(params));
 
-       div_bclk = 63;
+       div_bclk = 127;
        div_mclk = pll_out/(params_rate(params)*(div_bclk+1))-1;
 
        snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
index dad8e63e34dd1c7ee6a86daa4c6350248a4e1d88..426be3eda1054ab434597ba443e89b13023b8ee3 100755 (executable)
@@ -34,9 +34,9 @@ static const struct snd_pcm_hardware rockchip_pcm_hardware = {
                                    SNDRV_PCM_FMTBIT_S16_LE,
        .channels_min           = 2,
        .channels_max           = 8,
-       .buffer_bytes_max       = 128*1024,
+       .buffer_bytes_max       = 2*1024*1024,/*128*1024,*/
        .period_bytes_min       = 64,
-       .period_bytes_max       = 32*1024,//2048*4,///PAGE_SIZE*2,
+       .period_bytes_max       = 512*1024,/*32*1024,//2048*4,///PAGE_SIZE*2,*/
        .periods_min            = 3,
        .periods_max            = 128,
        .fifo_size              = 16,
@@ -46,7 +46,7 @@ static const struct snd_dmaengine_pcm_config rockchip_dmaengine_pcm_config = {
        .pcm_hardware = &rockchip_pcm_hardware,
        .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
        .compat_filter_fn = NULL,
-       .prealloc_buffer_size = PAGE_SIZE * 32,
+       .prealloc_buffer_size = PAGE_SIZE * 512,
 };
 
 int rockchip_pcm_platform_register(struct device *dev)
index 55610210238f0227d22c743b9ab76cca40ab4eaa..f2a2c1e1a14c793404f9448ce217c76f7fc6f2e5 100755 (executable)
@@ -39,6 +39,8 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int dai_fmt = rtd->dai_link->dai_fmt;
        int ret;
+       unsigned int pll_out = 0;
+       int div_bclk, div_mclk;
 
        DBG("Enter::%s----%d\n",  __func__, __LINE__);
        /* set codec DAI configuration */
@@ -55,6 +57,43 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
                       __func__);
                return ret;
        }
+
+       switch (params_rate(params)) {
+       case 8000:
+       case 16000:
+       case 24000:
+       case 32000:
+       case 48000:
+       case 96000:
+               pll_out = 12288000;
+               break;
+       case 11025:
+       case 22050:
+       case 44100:
+       case 88200:
+               pll_out = 11289600;
+               break;
+       case 176400:
+               pll_out = 11289600*2;
+               break;
+       case 192000:
+               pll_out = 12288000*2;
+               break;
+       default:
+               DBG("Enter:%s, %d, Error rate=%d\n", __func__,
+                   __LINE__, params_rate(params));
+               return -EINVAL;
+               break;
+       }
+       DBG("Enter:%s, %d, rate=%d\n", __func__, __LINE__, params_rate(params));
+       snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
+
+       div_bclk = 127;
+       div_mclk = pll_out/(params_rate(params)*128) - 1;
+
+       snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk);
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
        return 0;
 }