static int mtk_pcm_fm_i2s_close(struct snd_pcm_substream *substream)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    printk("%s rate = %d\n", __func__, runtime->rate);

    //mtk_wcn_cmb_stub_audio_ctrl((CMB_STUB_AIF_X)CMB_STUB_AIF_0);//temp mark for early porting

    SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, false);
    if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false)
    {
        SetI2SASRCEnable(false);
        SetI2SASRCConfig(false, 0); // Setting to bypass ASRC
        Set2ndI2SInEnable(false);
    }

    SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC, false);
    if (GetI2SDacEnable() == false)
    {
        SetI2SDacEnable(false);
    }

    // interconnection setting
    SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I00, Soc_Aud_InterConnectionOutput_O13);
    SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I01, Soc_Aud_InterConnectionOutput_O14);
    SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I10, Soc_Aud_InterConnectionOutput_O03);
    SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I11, Soc_Aud_InterConnectionOutput_O04);


    EnableAfe(false);

    AudDrv_I2S_Clk_Off();
    AudDrv_Clk_Off();
    mPrepareDone = false;
    return 0;
}
static int mtk_mrgrx_awb_alsa_stop(struct snd_pcm_substream *substream)
{
    AFE_BLOCK_T *Awb_Block = &(Mrgrx_AWB_Control_context->rBlock);
    printk("mtk_mrgrx_awb_alsa_stop \n");
    StopAudioAWBHardware(substream);
    RemoveMemifSubStream(Soc_Aud_Digital_Block_MEM_AWB);

#if 0 // TODO(Harvey)
    SetMemoryPathEnable(Soc_Aud_Digital_Block_MRG_I2S_OUT, false);
    if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MRG_I2S_OUT) == false)
    {
        SetMrgI2SEnable(false, substream->runtime->rate);
    }
#else
    SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, false);
    if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false)
    {
        SetI2SASRCEnable(false);
        SetI2SASRCConfig(false, 0); // Setting to bypass ASRC
        Set2ndI2SInEnable(false);
    }
#endif

    return 0;
}
static void StartAudioFMI2SAWBHardware(struct snd_pcm_substream *substream)
{
	AudioDigtalI2S m2ndI2SInAttribute;

	pr_warn("StartAudioFMI2SAWBHardware\n");

	/* here to set interrupt */
	SetIrqMcuCounter(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE,
			 substream->runtime->period_size >> 1);
	SetIrqMcuSampleRate(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE,
			    substream->runtime->rate);
	SetIrqEnable(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE, true);

	SetSampleRate(Soc_Aud_Digital_Block_MEM_AWB, substream->runtime->rate);
	SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_AWB, true);

	/* here to turn off digital part */
	SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I00,
		      Soc_Aud_InterConnectionOutput_O05);
	SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I01,
		      Soc_Aud_InterConnectionOutput_O06);


	if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false) {
		/* set merge interface */
		SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);

		/* Config 2nd I2S IN */
		memset_io((void *)&m2ndI2SInAttribute, 0, sizeof(m2ndI2SInAttribute));

		m2ndI2SInAttribute.mLR_SWAP = Soc_Aud_LR_SWAP_NO_SWAP;
		m2ndI2SInAttribute.mI2S_IN_PAD_SEL = false; /* I2S_IN_FROM_CONNSYS */
		m2ndI2SInAttribute.mI2S_SLAVE = Soc_Aud_I2S_SRC_SLAVE_MODE;
		m2ndI2SInAttribute.mI2S_SAMPLERATE = 32000;
		m2ndI2SInAttribute.mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
		m2ndI2SInAttribute.mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
		m2ndI2SInAttribute.mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
		Set2ndI2SIn(&m2ndI2SInAttribute);

		if (substream->runtime->rate == 48000)
			SetI2SASRCConfig(true, 48000);	/* Covert from 32000 Hz to 48000 Hz */
		else
			SetI2SASRCConfig(true, 44100);	/* Covert from 32000 Hz to 44100 Hz */

		SetI2SASRCEnable(true);

		Set2ndI2SInEnable(true);
	} else
		SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);

	EnableAfe(true);
}
static int mtk_fm_i2s_awb_alsa_stop(struct snd_pcm_substream *substream)
{
	pr_warn("mtk_fm_i2s_awb_alsa_stop\n");
	StopAudioFMI2SAWBHardware(substream);
	RemoveMemifSubStream(Soc_Aud_Digital_Block_MEM_AWB, substream);

	SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, false);
	if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false) {
		SetI2SASRCEnable(false);
		SetI2SASRCConfig(false, 0);	/* Setting to bypass ASRC */
		Set2ndI2SInEnable(false);
	}

	return 0;
}
static int mtk_pcm_fm_i2s_prepare(struct snd_pcm_substream *substream)
{
    AudioDigtalI2S m2ndI2SInAttribute;

    struct snd_pcm_runtime *runtime = substream->runtime;
    printk("%s rate = %d\n", __func__, runtime->rate);

    if (mPrepareDone == false)
    {
        //mtk_wcn_cmb_stub_audio_ctrl((CMB_STUB_AIF_X)CMB_STUB_AIF_3);//temp mark for early porting

        // interconnection setting
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I00, Soc_Aud_InterConnectionOutput_O13);
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I01, Soc_Aud_InterConnectionOutput_O14);
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I10, Soc_Aud_InterConnectionOutput_O03);
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I11, Soc_Aud_InterConnectionOutput_O04);

        ///<<<lenovo-sw, fangzf1 @2015-06-11 for fm
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I10, Soc_Aud_InterConnectionOutput_O00);
        SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I11, Soc_Aud_InterConnectionOutput_O01);
        ///lenovo-sw, fangzf1 @2015-06-11 for fm>>>

        // Set HW_GAIN
        SetHwDigitalGainMode(Soc_Aud_Hw_Digital_Gain_HW_DIGITAL_GAIN1, runtime->rate, 0x40);
        SetHwDigitalGainEnable(Soc_Aud_Hw_Digital_Gain_HW_DIGITAL_GAIN1, true);
        SetHwDigitalGain(mfm_i2s_Volume, Soc_Aud_Hw_Digital_Gain_HW_DIGITAL_GAIN1);

        // start I2S DAC out
        if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC) == false)
        {
            SetI2SDacOut(runtime->rate,false,Soc_Aud_I2S_WLEN_WLEN_16BITS);
            SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC, true);
            SetI2SDacEnable(true);
        }
        else
        {
            SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC, true);
        }
        if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false)
        {
            //set merge interface
            SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);

            // Config 2nd I2S IN
            memset((void *)&m2ndI2SInAttribute, 0, sizeof(m2ndI2SInAttribute));

            m2ndI2SInAttribute.mLR_SWAP = Soc_Aud_LR_SWAP_NO_SWAP;
            m2ndI2SInAttribute.mI2S_IN_PAD_SEL = false; // I2S_IN_FROM_CONNSYS
            m2ndI2SInAttribute.mI2S_SLAVE = Soc_Aud_I2S_SRC_SLAVE_MODE;
            m2ndI2SInAttribute.mI2S_SAMPLERATE = 32000;
            m2ndI2SInAttribute.mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
            m2ndI2SInAttribute.mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
            m2ndI2SInAttribute.mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
            Set2ndI2SIn(&m2ndI2SInAttribute);

	    if (runtime->rate == 48000)
		    SetI2SASRCConfig(true, 48000);  /* Covert from 32000 Hz to 48000 Hz */
	    else
		    SetI2SASRCConfig(true, 44100);  /* Covert from 32000 Hz to 44100 Hz */
            SetI2SASRCEnable(true);

            Set2ndI2SInEnable(true);
        }
        else
        {
            SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);
        }

        EnableAfe(true);
        mPrepareDone = true;
    }
    return 0;
}
static void StartAudioMrgrxAWBHardware(struct snd_pcm_substream *substream)
{
    printk("StartAudioMrgrxAWBHardware \n");

    // here to set interrupt
    SetIrqMcuCounter(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE, substream->runtime->period_size >> 1);
    SetIrqMcuSampleRate(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE, substream->runtime->rate);
    SetIrqEnable(Soc_Aud_IRQ_MCU_MODE_IRQ2_MCU_MODE, true);

    SetSampleRate(Soc_Aud_Digital_Block_MEM_AWB, substream->runtime->rate);
    SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_AWB, true);

    // here to turn off digital part
#if 0 // TODO(Harvey)
    SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I15, Soc_Aud_InterConnectionOutput_O05);
    SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I16, Soc_Aud_InterConnectionOutput_O06);
#else
    SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I00, Soc_Aud_InterConnectionOutput_O05);
    SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I01, Soc_Aud_InterConnectionOutput_O06);
#endif


#if 0 // TODO(Harvey)
    if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MRG_I2S_OUT) == false)
    {
        //set merge interface
        SetMemoryPathEnable(Soc_Aud_Digital_Block_MRG_I2S_OUT, true);
        SetMrgI2SEnable(true, substream->runtime->rate);
    }
    else
    {
        SetMemoryPathEnable(Soc_Aud_Digital_Block_MRG_I2S_OUT, true);
    }
#else
    if (GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2) == false)
    {
        //set merge interface
        SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);
    
        // Config 2nd I2S IN
        AudioDigtalI2S m2ndI2SInAttribute;
        memset((void *)&m2ndI2SInAttribute, 0, sizeof(m2ndI2SInAttribute));
    
        m2ndI2SInAttribute.mLR_SWAP = Soc_Aud_LR_SWAP_NO_SWAP;
        m2ndI2SInAttribute.mI2S_IN_PAD_SEL = false; // I2S_IN_FROM_CONNSYS
        m2ndI2SInAttribute.mI2S_SLAVE = Soc_Aud_I2S_SRC_SLAVE_MODE;
        m2ndI2SInAttribute.mI2S_SAMPLERATE = 32000;
        m2ndI2SInAttribute.mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
        m2ndI2SInAttribute.mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
        m2ndI2SInAttribute.mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
        Set2ndI2SIn(&m2ndI2SInAttribute);
    
        SetI2SASRCConfig(true, 44100);  // Covert from 32000 Hz to 44100 Hz
        SetI2SASRCEnable(true);
    
        Set2ndI2SInEnable(true);
    }
    else
    {
        SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, true);
    }
#endif

    EnableAfe(true);
}