diff -Nur a/sound/soc/sunxi/audiocodec/sun8iw7_sndcodec.c b/sound/soc/sunxi/audiocodec/sun8iw7_sndcodec.c --- a/sound/soc/sunxi/audiocodec/sun8iw7_sndcodec.c 2016-04-24 18:52:22.000000000 +0200 +++ b/sound/soc/sunxi/audiocodec/sun8iw7_sndcodec.c 2016-05-12 18:28:34.295125768 +0200 @@ -627,6 +627,10 @@ /*enable dac digital*/ codec_wr_control(SUNXI_DAC_DPC, 0x1, DAC_EN, 0x1); codec_wr_prcm_control(LINEOUT_PA_GAT, 0x1, PA_CLK_GC, 0x0); + + /* This is workaround for loud poping anytime sound is opened */ + codec_wr_prcm_control(ROMIXSC, 0x1, RMIXMUTEDACR, 0); + codec_wr_prcm_control(LOMIXSC, 0x1, LMIXMUTEDACL, 0); /*set TX FIFO send drq level*/ codec_wr_control(SUNXI_DAC_FIFOC ,0x7f, TX_TRI_LEVEL, 0xf); diff -Nur a/sound/soc/sunxi/audiohub/sun8iw7-hubaudio.c b/sound/soc/sunxi/audiohub/sun8iw7-hubaudio.c --- a/sound/soc/sunxi/audiohub/sun8iw7-hubaudio.c 2016-04-24 18:52:22.000000000 +0200 +++ b/sound/soc/sunxi/audiohub/sun8iw7-hubaudio.c 2016-05-08 21:01:09.586643642 +0200 @@ -42,12 +42,10 @@ static hdmi_audio_t hdmi_para; atomic_t pcm_count_num_muti; static int sample_resolution = 0; -static int hub_used = 0; -static bool spdif_used = 0; -static bool hdmi_used = 0; -static bool hub_codec_en = true; -static bool hub_hdmi_en = false; -static bool hub_spdif_en = false; +static int hub_used = 0; +static bool spdif_used = 0; +static bool hdmi_used = 0; +static bool codec_used = 0; static bool hdmiaudio_reset_en = false; static struct sunxi_dma_params sunxi_daudio_pcm_stereo_out = { .name = "daudio2_play", @@ -75,17 +73,17 @@ case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (hub_codec_en) { + if (codec_used) { #ifdef CONFIG_SND_SUN8IW7_SNDCODEC audiocodec_hub_enable(1); #endif } - if (hdmi_used && hub_hdmi_en){ + if (hdmi_used){ #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_tx_enable(1, 1); #endif } - if (spdif_used && hub_spdif_en) { + if (spdif_used) { #ifdef CONFIG_SND_SUNXI_SOC_SPDIF spdif_txctrl_enable(1, substream->runtime->channels, 1); #endif @@ -98,17 +96,17 @@ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { } else { - if (hub_codec_en) { + if (codec_used) { #ifdef CONFIG_SND_SUN8IW7_SNDCODEC audiocodec_hub_enable(0); #endif } - if (hdmi_used && hub_hdmi_en){ + if (hdmi_used){ #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_tx_enable(0, 0); #endif } - if (spdif_used && hub_spdif_en) { + if (spdif_used) { #ifdef CONFIG_SND_SUNXI_SOC_SPDIF spdif_txctrl_enable(0, substream->runtime->channels, 0); #endif @@ -127,7 +125,7 @@ { u32 reg_val; /* play or record */ - if (hdmi_used && hub_hdmi_en) { + if (hdmi_used) { #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_prepare(substream); #endif @@ -191,7 +189,7 @@ default: return -EINVAL; } - if (hdmi_used && hub_hdmi_en) { + if (hdmi_used) { #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_hw_params(sample_resolution); #endif @@ -227,13 +225,13 @@ } } - if (spdif_used && hub_spdif_en) { + if (spdif_used) { #ifdef CONFIG_SND_SUNXI_SOC_SPDIF spdif_hw_params(sample_resolution); #endif } - if (hub_hdmi_en) { + if (hdmi_used) { /* play or record */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_data = &sunxi_daudio_pcm_stereo_out; @@ -246,12 +244,12 @@ static int sunxi_audiohub_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - if (hdmi_used && hub_hdmi_en) { + if (hdmi_used) { #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_set_fmt(fmt); #endif } - if (spdif_used && hub_spdif_en) { + if (spdif_used) { #ifdef CONFIG_SND_SUNXI_SOC_SPDIF spdif_set_fmt(0); #endif @@ -275,13 +273,13 @@ u32 spdif_mpll=0, spdif_bclk_div=0, spdif_mult_fs=0; #endif - if (hdmi_used && hub_hdmi_en) { + if (hdmi_used) { #ifdef CONFIG_SND_SUN8IW7_HDMIPCM tdm2_set_clkdiv(sample_rate); #endif } - if (spdif_used && hub_spdif_en) { + if (spdif_used) { #ifdef CONFIG_SND_SUNXI_SOC_SPDIF get_clock_divder(sample_rate, 32, &spdif_mclk_div, &spdif_mpll, &spdif_bclk_div, &spdif_mult_fs); spdif_set_clkdiv(SUNXI_DIV_MCLK, spdif_mclk_div); @@ -321,7 +319,7 @@ struct snd_soc_dai *dai) { /*hdmi*/ - if (hdmi_used && hub_hdmi_en && g_hdmi_func.hdmi_audio_enable) { + if (hdmi_used && g_hdmi_func.hdmi_audio_enable) { g_hdmi_func.hdmi_audio_enable(0, 1); } } @@ -369,14 +367,23 @@ type = script_get_item("audiohub", "spdif_used", &val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { pr_err("[audiohub] spdif_used type err!\n"); - } - spdif_used = val.val; + spdif_used = 0; + } else + spdif_used = val.val; type = script_get_item("audiohub", "hdmi_used", &val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { pr_err("[audiohub] hdmi_used type err!\n"); - } - hdmi_used = val.val; + hdmi_used = 0; + } else + hdmi_used = val.val; + + type = script_get_item("audiohub", "codec_used", &val); + if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { + pr_err("[audiohub] codec_used type err!\n"); + codec_used = 0; + } else + codec_used = val.val; ret = snd_soc_register_dais(&pdev->dev,sunxi_audiohub_dai, ARRAY_SIZE(sunxi_audiohub_dai)); if (ret) { @@ -441,9 +448,6 @@ } module_init(sunxi_audiohub_init); -module_param_named(hub_codec_en, hub_codec_en, bool, S_IRUGO | S_IWUSR); -module_param_named(hub_hdmi_en, hub_hdmi_en, bool, S_IRUGO | S_IWUSR); -module_param_named(hub_spdif_en, hub_spdif_en, bool, S_IRUGO | S_IWUSR); module_param_named(hdmiaudio_reset_en, hdmiaudio_reset_en, bool, S_IRUGO | S_IWUSR); static void __exit sunxi_audiohub_exit(void) diff -Nur a/drivers/char/sunxi-di/sunxi-di.c b/drivers/char/sunxi-di/sunxi-di.c --- a/drivers/char/sunxi-di/sunxi-di.c 2016-04-12 12:21:19.000000000 +0200 +++ b/drivers/char/sunxi-di/sunxi-di.c 2016-05-06 20:14:28.846445168 +0200 @@ -137,7 +137,6 @@ printk(KERN_ERR "di_clk handle is invalid, just return!\n"); return; } else { - clk_disable_unprepare(di_clk); clk_put(di_clk); di_clk = NULL; } @@ -202,36 +201,72 @@ static void sunxi_di_params_exit(void) { - di_clk_uncfg(); - free_irq(SW_INT_IRQNO_DI, di_device); - return ; + di_clk_uncfg(); + free_irq(SW_INT_IRQNO_DI, di_device); } +static void sunxi_di_disabledrv(void) +{ + di_irq_enable(0); + di_reset(); + di_internal_clk_disable(); + di_clk_disable(); + if (NULL != di_data.in_flag) + sunxi_buf_free(di_data.in_flag, di_data.in_flag_phy, di_data.flag_size); + if (NULL != di_data.out_flag) + sunxi_buf_free(di_data.out_flag, di_data.out_flag_phy, di_data.flag_size); +} + +static int sunxi_di_enabledrv(void) +{ + int ret; + + di_data.flag_size = (FLAG_WIDTH*FLAG_HIGH)/4; + + di_data.in_flag = sunxi_buf_alloc(di_data.flag_size, &(di_data.in_flag_phy)); + if (!di_data.in_flag) { + printk(KERN_ERR "%s: request in_flag mem failed\n", __func__); + return -1; + } + + di_data.out_flag = sunxi_buf_alloc(di_data.flag_size, &(di_data.out_flag_phy)); + if (!di_data.out_flag) { + printk(KERN_ERR "%s: request out_flag mem failed\n", __func__); + sunxi_buf_free(di_data.in_flag, di_data.in_flag_phy, di_data.flag_size); + return -1; + } + + ret = di_clk_enable(); + if (ret) { + printk(KERN_ERR "%s: enable clk failed.\n", __func__); + return ret; + } + + di_internal_clk_enable(); + di_set_init(di_data.mode); + + return 0; +} #ifdef CONFIG_PM static int sunxi_di_suspend(struct device *dev) { - dprintk(DEBUG_SUSPEND, "enter: sunxi_di_suspend. \n"); + dprintk(DEBUG_SUSPEND, "enter: sunxi_di_suspend. \n"); - if (atomic_read(&di_data.enable)) { - di_irq_enable(0); - di_reset(); - di_internal_clk_disable(); - di_clk_disable(); - if (NULL != di_data.in_flag) - sunxi_buf_free(di_data.in_flag, di_data.in_flag_phy, di_data.flag_size); - if (NULL != di_data.out_flag) - sunxi_buf_free(di_data.out_flag, di_data.out_flag_phy, di_data.flag_size); - } + if (atomic_read(&di_data.enable)) + sunxi_di_disabledrv(); - return 0; + return 0; } static int sunxi_di_resume(struct device *dev) { - dprintk(DEBUG_SUSPEND, "enter: sunxi_di_resume. \n"); + dprintk(DEBUG_SUSPEND, "enter: sunxi_di_resume. \n"); + + if (atomic_read(&di_data.enable)) + return sunxi_di_enabledrv(); - return 0; + return 0; } #endif @@ -315,54 +350,27 @@ static int sunxi_di_open(struct inode *inode, struct file *file) { - int ret = 0; - - dprintk(DEBUG_DATA_INFO, "%s: enter!!\n", __func__); - - atomic_set(&di_data.enable, 1); - - di_data.flag_size = (FLAG_WIDTH*FLAG_HIGH)/4; + int ret; + dprintk(DEBUG_DATA_INFO, "%s: enter!!\n", __func__); - di_data.in_flag = sunxi_buf_alloc(di_data.flag_size, &(di_data.in_flag_phy)); - if (!(di_data.in_flag)) { - printk(KERN_ERR "%s: request in_flag mem failed\n", __func__); - return -1; - } - - di_data.out_flag = sunxi_buf_alloc(di_data.flag_size, &(di_data.out_flag_phy)); - if (!(di_data.out_flag)) { - printk(KERN_ERR "%s: request out_flag mem failed\n", __func__); - sunxi_buf_free(di_data.in_flag, di_data.in_flag_phy, di_data.flag_size); - return -1; - } + //FIXME: This variable should be counter! + atomic_set(&di_data.enable, 1); - ret = di_clk_enable(); - if (ret) { - printk(KERN_ERR "%s: enable clk failed.\n", __func__); - return ret; - } - di_internal_clk_enable(); - di_set_init(di_data.mode); - - return 0; + ret = sunxi_di_enabledrv(); + if(ret) + return ret; + + return 0; } static int sunxi_di_release(struct inode *inode, struct file *file) { - dprintk(DEBUG_DATA_INFO, "%s: enter!!\n", __func__); + dprintk(DEBUG_DATA_INFO, "%s: enter!!\n", __func__); - atomic_set(&di_data.enable, 0); + atomic_set(&di_data.enable, 0); + sunxi_di_disabledrv(); - di_irq_enable(0); - di_reset(); - di_internal_clk_disable(); - di_clk_disable(); - if (NULL != di_data.in_flag) - sunxi_buf_free(di_data.in_flag, di_data.in_flag_phy, di_data.flag_size); - if (NULL != di_data.out_flag) - sunxi_buf_free(di_data.out_flag, di_data.out_flag_phy, di_data.flag_size); - - return 0; + return 0; } static const struct file_operations sunxi_di_fops = {