static int mtk_pcm_dl1_open(struct snd_pcm_substream *substream)
{
    int ret = 0;
    struct snd_pcm_runtime *runtime = substream->runtime;
    PRINTK_AUDDRV("mtk_pcm_dl1_open\n");

    AfeControlSramLock();
    if (GetSramState() == SRAM_STATE_FREE)
    {
        mtk_pcm_dl1_hardware.buffer_bytes_max = GetPLaybackSramFullSize();
        mPlaybackSramState = SRAM_STATE_PLAYBACKFULL;
        SetSramState(mPlaybackSramState);
    }
    else
    {
        mtk_pcm_dl1_hardware.buffer_bytes_max = GetPLaybackDramSize();
        mPlaybackSramState = SRAM_STATE_PLAYBACKDRAM;
    }
    AfeControlSramUnLock();
    if (mPlaybackSramState == SRAM_STATE_PLAYBACKDRAM)
    {
        AudDrv_Emi_Clk_On();
    }

    printk("mtk_pcm_dl1_hardware.buffer_bytes_max = %zu mPlaybackSramState = %d\n", mtk_pcm_dl1_hardware.buffer_bytes_max, mPlaybackSramState);
    runtime->hw = mtk_pcm_dl1_hardware;

    AudDrv_ANA_Clk_On();
    AudDrv_Clk_On();
    memcpy((void *)(&(runtime->hw)), (void *)&mtk_pcm_dl1_hardware , sizeof(struct snd_pcm_hardware));
    pMemControl = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_DL1);

    ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                     &constraints_sample_rates);

    if (ret < 0)
    {
        printk("snd_pcm_hw_constraint_integer failed\n");
    }

    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    {
        printk("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_dl1playback_constraints\n");
    }
    else
    {
        printk("SNDRV_PCM_STREAM_CAPTURE mtkalsa_dl1playback_constraints\n");
    }

    if (ret < 0)
    {
        printk("ret < 0 mtk_soc_pcm_dl1_close\n");
        mtk_soc_pcm_dl1_close(substream);
        return ret;
    }

    //PRINTK_AUDDRV("mtk_pcm_dl1_open return\n");
    return 0;
}
static int mtk_capture_pcm_open(struct snd_pcm_substream *substream)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    int ret = 0;
    AudDrv_Clk_On();
    AudDrv_ADC_Clk_On();
    VUL_Control_context = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_VUL);

    // can allocate sram_dbg
    AfeControlSramLock();
    if (GetSramState() ==  SRAM_STATE_FREE )
    {
        printk("mtk_capture_pcm_open use sram \n");
        mtk_capture_hardware.buffer_bytes_max = GetCaptureSramSize();
        SetSramState(SRAM_STATE_CAPTURE);
        mCaptureUseSram = true;
    }
    else
    {
        printk("mtk_capture_pcm_open use dram \n");
        mtk_capture_hardware.buffer_bytes_max = UL1_MAX_BUFFER_SIZE;
    }
    AfeControlSramUnLock();

    runtime->hw = mtk_capture_hardware;
    memcpy((void *)(&(runtime->hw)), (void *)&mtk_capture_hardware , sizeof(struct snd_pcm_hardware));

    ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                     &constraints_sample_rates);
    ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
    if (ret < 0)
    {
        printk("snd_pcm_hw_constraint_integer failed\n");
    }

    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
    {

    }
    else
    {

    }

    if (ret < 0)
    {
        printk("mtk_capture_pcm_close\n");
        mtk_capture_pcm_close(substream);
        return ret;
    }
    if(mCaptureUseSram == false)
    {
        AudDrv_Emi_Clk_On();
    }
    printk("mtk_capture_pcm_open return\n");
    return 0;
}
static void GetAudioTrimOffset(int channels)
{
    int Buffer_on_value = 0 , Buffer_offl_value = 0, Buffer_offr_value = 0;
    const int off_counter = 20, on_counter  = 20 , Const_DC_OFFSET = 0;//2048;
    printk("%s channels = %d\n", __func__, channels);
    // open headphone and digital part
    AudDrv_Clk_On();
    AudDrv_Emi_Clk_On();
    OpenAfeDigitaldl1(true);

    setHpDcCalibration(AUDIO_ANALOG_DEVICE_OUT_HEADSETR, 0);
    setHpDcCalibration(AUDIO_ANALOG_DEVICE_OUT_HEADSETL, 0);
    //get DC value when off
//Sammodi Todo, need enable this on Rainier
#ifdef RAINIER_NEED_CHECK
    Buffer_offl_value = PMIC_IMM_GetOneChannelValue(AUXADC_HP_L_CHANNEL, off_counter, 0);
#endif    
    printk("%s, Buffer_offl_value = %d \n",__func__, Buffer_offl_value);

    
//Sammodi Todo, need enable this
#ifdef RAINIER_NEED_CHECK
    Buffer_offr_value = PMIC_IMM_GetOneChannelValue(AUXADC_HP_R_CHANNEL, off_counter, 0);
#endif
    printk("%s, Buffer_offr_value = %d \n",__func__, Buffer_offr_value);

    OpenAnalogHeadphone(true);
    setHpDcCalibrationGain(AUDIO_ANALOG_DEVICE_OUT_HEADSETR,10);    // -1dB, (9-(-1) = 10)
    setHpDcCalibrationGain(AUDIO_ANALOG_DEVICE_OUT_HEADSETL,10);

    msleep(10);
//Sammodi Todo, need enable this  
#ifdef RAINIER_NEED_CHECK
    Buffer_on_value = PMIC_IMM_GetOneChannelValue(AUXADC_HP_L_CHANNEL, on_counter, 0);
#endif
    mHplOffset = Buffer_on_value - Buffer_offl_value + Const_DC_OFFSET;
    printk("%s, Buffer_on_value = %d Buffer_offl_value = %d mHplOffset = %d \n", __func__,Buffer_on_value, Buffer_offl_value, mHplOffset);

//Sammodi Todo, need enable this 
#ifdef RAINIER_NEED_CHECK
    Buffer_on_value = PMIC_IMM_GetOneChannelValue(AUXADC_HP_R_CHANNEL, on_counter, 0);
#endif
    mHprOffset = Buffer_on_value - Buffer_offr_value + Const_DC_OFFSET;
    printk("%s, Buffer_on_value = %d Buffer_offr_value = %d mHprOffset = %d \n", __func__,Buffer_on_value, Buffer_offr_value, mHprOffset);

    
    OpenAnalogHeadphone(false);
    
    OpenAfeDigitaldl1(false);

    AudDrv_Emi_Clk_Off();
    AudDrv_Clk_Off();

}
static int mtk_dl1_awb_pcm_open(struct snd_pcm_substream *substream)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    int ret = 0;
    printk("mtk_dl1_awb_pcm_open\n");
    Dl1_AWB_Control_context = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_AWB);
    runtime->hw = mtk_dl1_awb_hardware;
    memcpy((void *)(&(runtime->hw)), (void *)&mtk_dl1_awb_hardware , sizeof(struct snd_pcm_hardware));

    ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                     &dl1_awb_constraints_sample_rates);
    ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);

    if (ret < 0)
    {
        printk("snd_pcm_hw_constraint_integer failed\n");
    }

    // here open audio clocks
    AudDrv_Clk_On();

    //print for hw pcm information
    printk("mtk_dl1_awb_pcm_open runtime rate = %d channels = %d \n", runtime->rate, runtime->channels);
    runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
    runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
    runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;

    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
    {
        printk("SNDRV_PCM_STREAM_CAPTURE \n");
    }
    else
    {
        return -1;
    }

    if (ret < 0)
    {
        printk("mtk_dl1_awb_pcm_close\n");
        mtk_dl1_awb_pcm_close(substream);
        return ret;
    }
    AudDrv_Emi_Clk_On();
    printk("mtk_dl1_awb_pcm_open return\n");
    return 0;
}
static int mtk_pcm_dl2_open(struct snd_pcm_substream *substream)
{
	int ret = 0;
	struct snd_pcm_runtime *runtime = substream->runtime;

	PRINTK_AUDDRV("mtk_pcm_dl2_open\n");

		mtk_pcm_dl2_hardware.buffer_bytes_max = GetPLaybackDramLowLatencySize();
		mPlaybackSramState = SRAM_STATE_PLAYBACKDRAM;
		mPlaybackUseSram = false;
	if (mPlaybackSramState == SRAM_STATE_PLAYBACKDRAM)
		AudDrv_Emi_Clk_On();

	pr_warn("mtk_pcm_dl2_hardware.buffer_bytes_max = %zu mPlaybackSramState = %d\n",
	       mtk_pcm_dl2_hardware.buffer_bytes_max, mPlaybackSramState);
	runtime->hw = mtk_pcm_dl2_hardware;

	AudDrv_Clk_On();
	memcpy((void *)(&(runtime->hw)), (void *)&mtk_pcm_dl2_hardware,
	       sizeof(struct snd_pcm_hardware));
	pMemControl = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_DL2);

	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
					 &constraints_sample_rates);

	if (ret < 0)
		pr_err("snd_pcm_hw_constraint_integer failed\n");

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		pr_warn("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_dl2playback_constraints\n");
	else
		pr_warn("SNDRV_PCM_STREAM_CAPTURE mtkalsa_dl2playback_constraints\n");

	if (ret < 0) {
		pr_err("ret < 0 mtk_soc_pcm_dl2_close\n");
		mtk_soc_pcm_dl2_close(substream);
		return ret;
	}
	/* PRINTK_AUDDRV("mtk_pcm_dl2_open return\n"); */
	return 0;
}
static int mtk_pcm_hdmi_open(struct snd_pcm_substream *substream)
{
	int ret = 0;
	struct snd_pcm_runtime *runtime = substream->runtime;

	pr_debug("%s\n", __func__);

	AudDrv_ANA_Clk_On();
	AudDrv_Emi_Clk_On();
	AudDrv_Clk_On();

	runtime->hw = mtk_hdmi_hardware;

	pMemControl = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_HDMI);

	memcpy((void *)(&(runtime->hw)), (void *)&mtk_hdmi_hardware,
	       sizeof(struct snd_pcm_hardware));


	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
					 &constraints_sample_rates);

	if (ret < 0) {
		PRINTK_AUD_HDMI("snd_pcm_hw_constraint_integer failed\n");
		return ret;
	}

	/* print for hw pcm information */
	pr_debug("%s, runtime->rate = %d, channels = %d, substream->pcm->device = %d\n",
		__func__, runtime->rate, runtime->channels, substream->pcm->device);

	runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
	runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
	runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;

	PRINTK_AUD_HDMI("mtk_pcm_hdmi_open return\n");

	return 0;
}
static int mtk_fm_i2s_awb_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int ret = 0;

	pr_warn("mtk_fm_i2s_awb_pcm_open\n");
	FM_I2S_AWB_Control_context = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_AWB);
	runtime->hw = mtk_mgrrx_awb_hardware;
	memcpy((void *)(&(runtime->hw)), (void *)&mtk_mgrrx_awb_hardware ,
	       sizeof(struct snd_pcm_hardware));

	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
					 &fm_i2s_awb_constraints_sample_rates);
	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);

	if (ret < 0)
		pr_warn("snd_pcm_hw_constraint_integer failed\n");

	pr_warn("mtk_fm_i2s_awb_pcm_open runtime rate = %d channels = %d\n",
	       runtime->rate, runtime->channels);

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		pr_warn("SNDRV_PCM_STREAM_CAPTURE\n");
	else
		return -1;
	/* here open audio clocks */
	AudDrv_Clk_On();
	AudDrv_I2S_Clk_On();
	AudDrv_Emi_Clk_On();

	if (ret < 0) {
		pr_err("mtk_fm_i2s_awb_pcm_close\n");
		mtk_fm_i2s_awb_pcm_close(substream);
		return ret;
	}
	pr_warn("mtk_fm_i2s_awb_pcm_open return\n");
	return 0;
}
static int Audio_hdmi_SideGen_Set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
    printk("%s()\n", __func__);
    if (ucontrol->value.enumerated.item[0] > ARRAY_SIZE(HDMI_SIDEGEN))
    {
        printk("return -EINVAL\n");
        return -EINVAL;
    }

#ifdef _TDM_8CH_SGEN_TEST
    mHdmi_sidegen_control = ucontrol->value.integer.value[0];

    if (mHdmi_sidegen_control)
    {
        uint32 samplerate = 44100;
        uint32 Channels = 2;
        uint32 HDMIchaanel = 8;
        uint32 Tdm_Lrck = 0;
        uint32 MclkDiv = 0;

        //Enable Audio Driver Clock
        AudDrv_Clk_On();
        AudDrv_Emi_Clk_On();

        //Enable APLL
        EnableApll(samplerate, true);
        EnableApllTuner(samplerate, true);
        //HDMI I2S clock setting
        MclkDiv = SetCLkMclk(Soc_Aud_HDMI_MCK, samplerate);
        SetCLkHdmiBclk(MclkDiv, samplerate, 2 , 32);

        //enable mclk divider
        EnableSpdifDivPower(AUDIO_APLL_SPDIF_DIV,  true);
        //enable bck divider
        EnableHDMIDivPower(AUDIO_APLL_HDMI_BCK_DIV,  true);
        //turn on hdmi clk
        SetHdmiClkOn();

        //Set Mem buffer
        SetHDMIAddress();
        copysinewavetohdmi(8);

        //config hdmi irq
        SetIrqMcuCounter(Soc_Aud_IRQ_MCU_MODE_IRQ5_MCU_MODE, 44100);

        //config hdmi interface
        SetMemIfFetchFormatPerSample(Soc_Aud_Digital_Block_MEM_HDMI, AFE_WLEN_16_BIT); //now fix 16bit
        SetHdmiTdm1Config(44100, AFE_DATA_WLEN_32BIT);
        SetHdmiTdm2Config(44100);
        SetHDMIChannels(HDMIchaanel);

        //config hdmi connection
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I30, Soc_Aud_InterConnectionOutput_O30);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I31, Soc_Aud_InterConnectionOutput_O31);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I30, Soc_Aud_InterConnectionOutput_O32);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I31, Soc_Aud_InterConnectionOutput_O33);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I30, Soc_Aud_InterConnectionOutput_O34);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I31, Soc_Aud_InterConnectionOutput_O35);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I30, Soc_Aud_InterConnectionOutput_O36);
        SetHDMIConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I31, Soc_Aud_InterConnectionOutput_O37);

        //Enable hdmi Memory Path
        SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_HDMI, true);
        //enable irq
        SetIrqEnable(Soc_Aud_IRQ_MCU_MODE_IRQ5_MCU_MODE, true);
        //enable hdmi out
        SetHDMIEnable(true);
        //enable afe
        EnableAfe(true);
        //enable TDM
        SetTDMEnable(HDMIchaanel);

    }
    else
    {
        uint32 samplerate = 44100;
        uint32 Channels = 2;
        uint32 HDMIchaanel = 8;
        uint32 Tdm_Lrck = 0;
        uint32 MclkDiv = 0;

        SetTDMEnable(false);

        SetHDMIEnable(false);

        SetIrqEnable(Soc_Aud_IRQ_MCU_MODE_IRQ5_MCU_MODE, false);

        SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_HDMI, false);

        EnableAfe(false);

        SetHdmiPcmInterConnection(Soc_Aud_InterCon_DisConnect, HDMIchaanel);

        SetHdmiClkOff();
        EnableSpdifDivPower(AUDIO_APLL_SPDIF_DIV,  false);
        EnableHDMIDivPower(AUDIO_APLL_HDMI_BCK_DIV,  false);

        AudDrv_Emi_Clk_Off();
        AudDrv_Clk_Off();

    }
#endif
    return 0;
}
static void GetAudioTrimOffset(int channels)
{
    int Buffer_on_value = 0 , Buffer_offl_value = 0, Buffer_offr_value = 0;
    const int off_counter = 20, on_counter  = 20 , Const_DC_OFFSET = 2048;
    printk("%s channels = %d\n", __func__, channels);
    // open headphone and digital part
    AudDrv_Clk_On();
    AudDrv_Emi_Clk_On();
    OpenAfeDigitaldl1(true);
    switch (channels)
    {
        case AUDIO_OFFSET_TRIM_MUX_HPL:
        case AUDIO_OFFSET_TRIM_MUX_HPR:
        {
            OpenTrimBufferHardware(true);
            setHpGainZero();
            break;
        }
        default:
            break;
    }

    // Get HPL off offset
    SetSdmLevel(AUDIO_SDM_LEVEL_MUTE);
    msleep(1);
    setOffsetTrimMux(AUDIO_OFFSET_TRIM_MUX_HPL);
    setOffsetTrimBufferGain(3);
    EnableTrimbuffer(true);
    msleep(1);
    #if MTK_FPGA
    Buffer_offl_value = PMIC_IMM_GetOneChannelValue(MT6328_AUX_CH9, off_counter, 0);
    #else
    Buffer_offl_value = 0;
    #endif
    printk("Buffer_offl_value = %d \n", Buffer_offl_value);
    EnableTrimbuffer(false);

    // Get HPR off offset
    SetSdmLevel(AUDIO_SDM_LEVEL_MUTE);
    setOffsetTrimMux(AUDIO_OFFSET_TRIM_MUX_HPR);
    setOffsetTrimBufferGain(3);
    EnableTrimbuffer(true);
    msleep(5);
    #if MTK_FPGA
    Buffer_offr_value = PMIC_IMM_GetOneChannelValue(MT6328_AUX_CH9, off_counter, 0);
    #else
    Buffer_offr_value = 0;
    #endif
    printk("Buffer_offr_value = %d \n", Buffer_offr_value);
    EnableTrimbuffer(false);

    switch (channels)
    {
        case AUDIO_OFFSET_TRIM_MUX_HPL:
        case AUDIO_OFFSET_TRIM_MUX_HPR:
        {
            OpenTrimBufferHardware(false);
            break;
        }
        default:
            break;
    }


    // calibrate HPL offset trim
    setOffsetTrimMux(AUDIO_OFFSET_TRIM_MUX_HPL);
    setOffsetTrimBufferGain(3);
//    EnableTrimbuffer(true);
//    msleep(5);

    switch (channels)
    {
        case AUDIO_OFFSET_TRIM_MUX_HPL:
        case AUDIO_OFFSET_TRIM_MUX_HPR:
        {
            OpenAnalogHeadphone(true);
            setHpGainZero();
            break;
        }
        default:
            break;
    }
    EnableTrimbuffer(true);

    msleep(10);
    #ifdef CONFIG_MTK_FPGA
    Buffer_on_value = PMIC_IMM_GetOneChannelValue(MT6328_AUX_CH9, on_counter, 0);
    #else
    Buffer_on_value = 0;
    #endif

    mHplOffset = Buffer_on_value - Buffer_offl_value + Const_DC_OFFSET;
    printk("Buffer_on_value = %d Buffer_offl_value = %d mHplOffset = %d \n", Buffer_on_value, Buffer_offl_value, mHplOffset);

    EnableTrimbuffer(false);

    // calibrate HPL offset trim
    setOffsetTrimMux(AUDIO_OFFSET_TRIM_MUX_HPR);
    setOffsetTrimBufferGain(3);
    EnableTrimbuffer(true);
    msleep(10);
    #ifdef CONFIG_MTK_FPGA
    Buffer_on_value = PMIC_IMM_GetOneChannelValue(MT6328_AUX_CH9, on_counter, 0);
    #else
    Buffer_on_value = 0;
    #endif
    mHprOffset = Buffer_on_value - Buffer_offr_value + Const_DC_OFFSET;
    printk("Buffer_on_value = %d Buffer_offr_value = %d mHprOffset = %d \n", Buffer_on_value, Buffer_offr_value, mHprOffset);

    switch (channels)
    {
        case AUDIO_OFFSET_TRIM_MUX_HPL:
        case AUDIO_OFFSET_TRIM_MUX_HPR:
            OpenAnalogHeadphone(false);
            break;
    }

    setOffsetTrimMux(AUDIO_OFFSET_TRIM_MUX_GROUND);
    EnableTrimbuffer(false);
    OpenAfeDigitaldl1(false);

    SetSdmLevel(AUDIO_SDM_LEVEL_NORMAL);
    AudDrv_Emi_Clk_Off();
    AudDrv_Clk_Off();

}