From: smj Date: Thu, 9 Apr 2015 03:22:23 +0000 (+0800) Subject: i2s:fix the hdmi no sound sometimes X-Git-Tag: firefly_0821_release~4158^2~226 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=12bac32cc204885975d661a6e11c3f0e86c450af;p=firefly-linux-kernel-4.4.55.git i2s:fix the hdmi no sound sometimes support for hdmi passthrough output Signed-off-by: smj --- diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c old mode 100644 new mode 100755 index b35c424c2d77..24b7934607f9 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c @@ -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); diff --git a/sound/soc/codecs/rk1000_codec.c b/sound/soc/codecs/rk1000_codec.c index bd979cd255a4..ffc0b98a9bee 100755 --- a/sound/soc/codecs/rk1000_codec.c +++ b/sound/soc/codecs/rk1000_codec.c @@ -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, }, diff --git a/sound/soc/rockchip/rk30_i2s.c b/sound/soc/rockchip/rk30_i2s.c index bb15f42b3250..d66d5ffd9ec1 100755 --- a/sound/soc/rockchip/rk30_i2s.c +++ b/sound/soc/rockchip/rk30_i2s.c @@ -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) diff --git a/sound/soc/rockchip/rk_hdmi_i2s.c b/sound/soc/rockchip/rk_hdmi_i2s.c index fe9c716861e0..2d4c63daae72 100755 --- a/sound/soc/rockchip/rk_hdmi_i2s.c +++ b/sound/soc/rockchip/rk_hdmi_i2s.c @@ -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); diff --git a/sound/soc/rockchip/rk_pcm.c b/sound/soc/rockchip/rk_pcm.c index dad8e63e34dd..426be3eda105 100755 --- a/sound/soc/rockchip/rk_pcm.c +++ b/sound/soc/rockchip/rk_pcm.c @@ -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) diff --git a/sound/soc/rockchip/rk_rk1000codec.c b/sound/soc/rockchip/rk_rk1000codec.c index 55610210238f..f2a2c1e1a14c 100755 --- a/sound/soc/rockchip/rk_rk1000codec.c +++ b/sound/soc/rockchip/rk_rk1000codec.c @@ -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; }