/**
 * @file hv_drv_Audio.c
 * @brief audio driver c file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and de-initialization functions \n
 *          (2) Start and stop functions \n
 *          (3) Feed functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-18
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-23   <td>init
 * </table>
 */

#include "hv_drv_Audio.h"
#include "hv_cal_Audio.h"
#include "hv_chip_Config.h"
#include "hv_vos_Comm.h"
#include "hv_comm_Assert.h"
#include "hv_comm_Log.h"
#include "hv_drv_Gpio.h"
#include "hv_comm_MemoryConfig.h"
#include "hv_cal_PLL.h"

#define _AUDIO_STATE_WORK       1
#define _AUDIO_STATE_RESET      0

#define _AUDIO_PLL_PGO_0        0 //256fs
#define _AUDIO_PLL_PGO_1        1 //128fs
#define _AUDIO_PLL_PGO          2 //1024fs

#define _AUDIO_FLAG_LPF         1
#define _AUDIO_FLAG_HPF         0

#define _AUDIO_DM_BURST_LEN     15
#define _AUDIO_DM_BURST_RMD     0

#define _AUDIO_FS_NON_DETECT    0 //non detect
#define _AUDIO_FS_192K          1 //192k
#define _AUDIO_FS_176P4K        2 //176.4k
#define _AUDIO_FS_96K           3 //96k
#define _AUDIO_FS_88P2K         4 //88.2k
#define _AUDIO_FS_48K           5 //48k
#define _AUDIO_FS_44P1K         6 //44.1k
#define _AUDIO_FS_32K           7 //32K
#define _AUDIO_FS_16K           8 //16K
#define _AUDIO_FS_8K            9 //8K

#ifdef HV_PROJECT_CONFIG_AUDIO_EQ
const AudioLpfData   tAudioEqLpf0_rock    = {0, 0, 0xF0A5, 0x0, 0xFFE6};
const AudioLpfData   tAudioEqLpf0_pop     = {0, 0, 0x0, 0x0, 0x0};
const AudioLpfData   tAudioEqLpf0_live    = {0, 0, 0x0, 0x0, 0xFFD5};
const AudioLpfData   tAudioEqLpf0_dance   = {0, 0, 0x0, 0x0, 0x9F};
const AudioLpfData   tAudioEqLpf0_club    = {0, 0, 0xF1F8, 0x0, 0x0};
const AudioLpfData   tAudioEqLpf0_powerful= {0, 0, 0xF104, 0x0, 0xC2};

const AudioHpfData   tAudioEqHpf0_rock    = {0, 0, 0xF00B, 0x0, 0xFF8D};
const AudioHpfData   tAudioEqHpf0_pop     = {0, 0, 0x0, 0x0, 0x0};
const AudioHpfData   tAudioEqHpf0_live    = {0, 0, 0x0, 0x0, 0x0};
const AudioHpfData   tAudioEqHpf0_dance   = {0, 0, 0xF104, 0x0, 0x0};
const AudioHpfData   tAudioEqHpf0_club    = {0, 0, 0xF104, 0x0, 0xFF8D};
const AudioHpfData   tAudioEqHpf0_powerful= {0, 0, 0xF104, 0x0, 0xFF8D};

const AudioBpfData   tAudioEqBpf0_rock    = {0, 0, 0, 0xE038, 0xFCB, 0x2B};
const AudioBpfData   tAudioEqBpf0_pop     = {0, 0, 0, 0x0, 0x0, 0x21};
const AudioBpfData   tAudioEqBpf0_live    = {0, 0, 0, 0xE08B, 0xF87, 0x9F};
const AudioBpfData   tAudioEqBpf0_dance   = {0, 0, 0, 0x0, 0x0, 0x5E};
const AudioBpfData   tAudioEqBpf0_club    = {0, 0, 0, 0xE075, 0xF96, 0x21};
const AudioBpfData   tAudioEqBpf0_powerful= {0, 0, 0, 0xE05E, 0xFA6, 0x115};

const AudioBpfData   tAudioEqBpf1_rock    = {0, 0, 0, 0xE1EC, 0xE2B, 0xFFB7};
const AudioBpfData   tAudioEqBpf1_pop     = {0, 0, 0, 0x0, 0x0, 0xFE};
const AudioBpfData   tAudioEqBpf1_live    = {0, 0, 0, 0xE1DB, 0xE68, 0x7C};
const AudioBpfData   tAudioEqBpf1_dance   = {0, 0, 0, 0xE075, 0xF96, 0x16};
const AudioBpfData   tAudioEqBpf1_club    = {0, 0, 0, 0xE083, 0xF96, 0x21};
const AudioBpfData   tAudioEqBpf1_powerful= {0, 0, 0, 0xE498, 0xB7D, 0xFF9A};

const AudioBpfData   tAudioEqBpf2_rock    = {0, 0, 0, 0xE441, 0xE08, 0x2B};
const AudioBpfData   tAudioEqBpf2_pop     = {0, 0, 0, 0x0, 0x0, 0xFFE1};
const AudioBpfData   tAudioEqBpf2_live    = {0, 0, 0, 0x0, 0x0, 0x6C};
const AudioBpfData   tAudioEqBpf2_dance   = {0, 0, 0, 0x0, 0x0, 0xFFD4};
const AudioBpfData   tAudioEqBpf2_club    = {0, 0, 0, 0xE1DB, 0xE68, 0x64};
const AudioBpfData   tAudioEqBpf2_powerful= {0, 0, 0, 0xE53F, 0xCF5, 0x21};

const AudioBpfData   tAudioEqBpf3_rock    = {0, 0, 0, 0xED20, 0xAB1, 0x4B};
const AudioBpfData   tAudioEqBpf3_pop     = {0, 0, 0, 0x0, 0XAFB, 0XFFDB};
const AudioBpfData   tAudioEqBpf3_live    = {0, 0, 0, 0x0, 0x0, 0x2B};
const AudioBpfData   tAudioEqBpf3_dance   = {0, 0, 0, 0x0, 0x0, 0xFFC6};
const AudioBpfData   tAudioEqBpf3_club    = {0, 0, 0, 0xE441, 0xE08, 0x64};
const AudioBpfData   tAudioEqBpf3_powerful= {0, 0, 0, 0xEC01, 0xC47, 0x40};

const AudioBpfData   tAudioEqBpf4_rock    = {0, 0, 0, 0x6B7, 0x9F3, 0x202};
const AudioBpfData   tAudioEqBpf4_pop     = {0, 0, 0, 0X10000, 0X36A, 0XFFC0};
const AudioBpfData   tAudioEqBpf4_live    = {0, 0, 0, 0x0, 0x6A1, 0x2B};
const AudioBpfData   tAudioEqBpf4_dance   = {0, 0, 0, 0x10000, 0x76C, 0xFFC6};
const AudioBpfData   tAudioEqBpf4_club    = {0, 0, 0, 0xED20, 0xAB1, 0x21};
const AudioBpfData   tAudioEqBpf4_powerful= {0, 0, 0, 0x6E8, 0xAB1, 0x480};
#endif

static UINT32           s_uiHeadsetVolumeValue;         /*记录耳机音量，0-100*/
static UINT32           s_uiSpeakerVolumeValue;         /*记录扬声器音量，0-100*/
static UINT32           s_uiAudioCkRef = CLK_27M;
static UINT32           s_uiFsValue = _AUDIO_FS_48K;
static AudioEqData      s_tAudioEqData[MODE_MAX];
static ChannelType      s_uienChannelType;
static UINT32           s_uiRxOutIndex;
static UINT32           s_uiDmWriteReady = 0;

/**
 * @brief Audio PLL reset.
 */
VOID Hv_Drv_Audio_PllReset(VOID)
{
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_rstn, 0x0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_rstn, 0x1);
}

/**
 * @brief set reset.
 */
VOID Hv_Drv_Audio_SetReset(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetReset.");

    HV_W32_FIELD(SYS_SH06_TOP_04, reg_audio_rst_n,                      _AUDIO_STATE_RESET);
    HV_W32_FIELD(SYS_SH06_TOP_04, reg_audio_axi_rst_n,                  _AUDIO_STATE_RESET);

    HV_W32_FIELD(SYS_SH06_TOP_04, reg_audio_rst_n,                      _AUDIO_STATE_WORK);
    HV_W32_FIELD(SYS_SH06_TOP_04, reg_audio_axi_rst_n,                  _AUDIO_STATE_WORK);
}

/**
 * @brief Calculate HDMI Frequency.
 */
static VOID Hv_Drv_Audio_CalculateHDMIFrequency(VOID)
{
    HV_R32_DECL_VAR();
    static UINT32 uiLastFsValue = _AUDIO_FS_48K;
    //uiFsValue = HV_R32_FIELD(RX_AUDIO_TOP0_F4, regr_audio_i2s_rx_fs_0);
    //HV_LOG_INFO(AUDIO, "Detect Audio fs is %d.", uiFsValue);
    UINT32 uiAddrOffset = (s_uiRxOutIndex == _AUDIO_HDMI_0) ? 0x0 : 0x1000;
    UINT32 uiLaneFreq = HV_R32_FIELD_EX(RX_HDMI21_RX20_PRE_PROC_REG_00_BC, uiAddrOffset, regr_00_hd21rx_lane_clk_frq_1);
    UINT32 uiCTS = HV_R32_FIELD_EX(RX_HDMI21_RX_PKDEC_00_90, uiAddrOffset, regr_00_CTS_DECODED);
    UINT32 uiN= HV_R32_FIELD_EX(RX_HDMI21_RX_PKDEC_00_94, uiAddrOffset, regr_00_N_DECODED);
    UINT64 uiFs = 0;

    if(uiCTS == 0 || uiN == 0)
    {
        //HV_LOG_ERROR(AUDIO, "Get HDMI CTS And N Error.");
        //uiFs = 196;
        s_uiFsValue = uiLastFsValue;
        HV_LOG_INFO(AUDIO, "Detect cts or n is 0,fs set as last value");
        return;
    }
    else
    {
        uiFs = ((UINT64)((UINT64)((UINT64)((UINT64)uiLaneFreq * uiN) * 25) >> 5) / uiCTS);
        HV_LOG_DEBUG(AUDIO, "HDMI LaneFre:%d CTS:%d And N:%d get the Fs:%d.", uiLaneFreq, uiCTS, uiN, (UINT32)uiFs);
    }

    HV_LOG_DEBUG(AUDIO, "FS div N is %ld.", uiFs);
    if ((uiFs >= 46) && (uiFs < 68))
    {
        s_uiFsValue = _AUDIO_FS_48K;
    }
    else if (uiFs > 193)
    {
        s_uiFsValue = _AUDIO_FS_NON_DETECT;
    }
    else if ((uiFs > 12) && (uiFs < 30))
    {
        s_uiFsValue = _AUDIO_FS_16K;
    }
    else if ((uiFs >= 30) && (uiFs < 38))
    {
        s_uiFsValue = _AUDIO_FS_32K;
    }
    else if ((uiFs >= 38) && (uiFs < 46))
    {
        s_uiFsValue = _AUDIO_FS_44P1K;
    }
    else if ((uiFs >= 68) && (uiFs < 92))
    {
        s_uiFsValue = _AUDIO_FS_88P2K;
    }
    else if ((uiFs >= 92) && (uiFs < 136))
    {
        s_uiFsValue = _AUDIO_FS_96K;
    }
    else if ((uiFs >= 136) && (uiFs < 184))
    {
        s_uiFsValue = _AUDIO_FS_176P4K;
    }
    else if (uiFs >= 184)
    {
        s_uiFsValue = _AUDIO_FS_192K;
    }
    else
    {
        s_uiFsValue = _AUDIO_FS_8K;
    }
    uiLastFsValue = s_uiFsValue;

    HV_LOG_INFO(AUDIO, "Audio fs is %d.", s_uiFsValue);
    return;
}

/**
 * @brief Calculate DP Frequency.
 */
static VOID Hv_Drv_Audio_CalculateDPFrequency(VOID)
{
    HV_R32_DECL_VAR();
    static UINT32 uiLastFsValue = _AUDIO_FS_48K;
    UINT32 uiAddrOffset = (s_uiRxOutIndex == _AUDIO_DP_0) ? 0x0 : 0x2000;
    UINT32 uiBw = HV_R32_FIELD_EX(RX_EDP_RX_MAC_RO_REG_00_54, uiAddrOffset, regr_00_dprx_mac_clkdet_freq_cnt);
    UINT32 uiMaud = HV_R32_FIELD_EX(RX_EDP_RX_MAC_BP_REG_00_80, uiAddrOffset, regr_00_dprx_sdp_maud);
    UINT32 uiNaud= HV_R32_FIELD_EX(RX_EDP_RX_MAC_BP_REG_00_84, uiAddrOffset, regr_00_dprx_sdp_naud);
    UINT64 uiFs = 0;

    if ((0 == uiMaud) || (uiNaud == 0))
    {
        //uiNaud = 1;
        s_uiFsValue = uiLastFsValue;
        HV_LOG_INFO(AUDIO, "Detect maud or naud is 0,fs set as last value");
        return;
    }
    HV_LOG_INFO(AUDIO, "lane clock is %d,uiMaud %d ,uiNaud %d", uiBw,uiMaud,uiNaud);
    /* use symbol clk */
    uiFs = ((UINT64)uiBw * 20000) / 512;
    HV_LOG_DEBUG(AUDIO, "FS is %lu.", uiFs);
    uiFs = uiFs * uiMaud;
    HV_LOG_DEBUG(AUDIO, "FS mul M is %lu.", uiFs);
    uiFs = uiFs / uiNaud;
    HV_LOG_DEBUG(AUDIO, "FS div N is %lu.", uiFs);
    if ((uiFs >= 46000) && (uiFs < 68000))
    {
        s_uiFsValue = _AUDIO_FS_48K;
    }
    else if (uiFs > 195000)
    {
        s_uiFsValue = _AUDIO_FS_NON_DETECT;
    }
    else if ((uiFs > 12000) && (uiFs < 24000))
    {
        s_uiFsValue = _AUDIO_FS_16K;
    }
    else if ((uiFs >= 24000) && (uiFs < 38000))
    {
        s_uiFsValue = _AUDIO_FS_32K;
    }
    else if ((uiFs >= 38000) && (uiFs < 46000))
    {
        s_uiFsValue = _AUDIO_FS_44P1K;
    }
    else if ((uiFs >= 68000) && (uiFs < 92000))
    {
        s_uiFsValue = _AUDIO_FS_88P2K;
    }
    else if ((uiFs >= 92000) && (uiFs < 136000))
    {
        s_uiFsValue = _AUDIO_FS_96K;
    }
    else if ((uiFs >= 136000) && (uiFs < 184000))
    {
        s_uiFsValue = _AUDIO_FS_176P4K;
    }
    else if (uiFs >= 184000)
    {
        s_uiFsValue = _AUDIO_FS_192K;
    }
    else
    {
        s_uiFsValue = _AUDIO_FS_8K;
    }
    
    uiLastFsValue = s_uiFsValue;
    HV_LOG_INFO(AUDIO, "Audio fs is %d.", s_uiFsValue);
    return;
}

/**
 * @brief set VCO to 27M and fs to 48K.
 */
VOID Hv_Drv_Audio_ManualDefaultClock(VOID)
{
    //set CLK_27M
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,      0);

    //set fbdiv
    HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_sel,               0); //register config
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_div_mode,       0); //integer mode
    HV_W32_FIELD(RX_AUDIO_TOP2_10, reg_audio_pll_0_fbdiv_int,               82);

    //set prediv
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,         1);

    /* PG0 & PG0_0 & PG0_1*/
    //set postdiv for PG0
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,       45);
    //set postdiv0_0 for PG0_0 & PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0,     0x1a);

    /* PG1 & PG1_0 & PG1_1*/
    //set postdiv for PG1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,       180);
    //set postdiv0_0 for PG0_0 & PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1,     0x8);

    return;
}

/**
 * @brief Check Lock PLL State.
 */
Status Hv_Drv_Audio_GetClockLockState(VOID)
{
    UINT32 uiPllLock;
    HV_R32_DECL_VAR();
    uiPllLock = HV_R32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_DET_2,regr_audio_pll_lockdet_pll_lock);
    return uiPllLock;
}

/**
 * @brief Lock PLL.
 */
VOID Hv_Drv_Audio_ClockLock(VOID)
{
    UINT32 uiPllLock;
    UINT32 uiCount;

    /* relock */
    HV_R32_DECL_VAR();
    for(uiCount=0; uiCount<10; uiCount++)
    {
        HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_rstn, _AUDIO_STATE_RESET);
        Hv_Vos_Delayus(200);
        HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_rstn, _AUDIO_STATE_WORK);
        Hv_Vos_Delayus(2000);
        uiPllLock = HV_R32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_DET_2,regr_audio_pll_lockdet_pll_lock);
        if (uiPllLock)
        {
            break;
        }
    }

    return;
}

/**
 * @brief change new FS's PLL configures.
 */
VOID Hv_Drv_Audio_ChangeClock(VOID)
{
    HV_R32_DECL_VAR();
    UINT32 uiAddrOffset = (s_uiRxOutIndex == _AUDIO_HDMI_0) ? 0x0 : 0x1000;
    UINT32 uiN= HV_R32_FIELD_EX(RX_HDMI21_RX_PKDEC_00_94, uiAddrOffset, regr_00_N_DECODED);
    HV_LOG_DEBUG(AUDIO, "uiN = %d", uiN);

    switch (s_uiAudioCkRef)
    {
        case CLK_27M:
        {
            //set fbdiv
            HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_sel,               0); //register config
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_div_mode,       0); //integer mode
            HV_W32_FIELD(RX_AUDIO_TOP2_10, reg_audio_pll_0_fbdiv_int,               82);

            //set prediv
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,         1);

            /* PG0 & PG0_0 & PG0_1*/
            //set postdiv for PG0
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,       45);
            //set postdiv0_0 for PG0_0 & PG0_1
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0,     0x1a);

            /* PG1 & PG1_0 & PG1_1*/
            //set postdiv for PG1
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,       180);
            //set postdiv0_0 for PG0_0 & PG0_1
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1,     0x8);

            break;
        }
        case CLK_HDMI:
        {
            //calculate the fs
            Hv_Drv_Audio_CalculateHDMIFrequency();

            //set fbdiv
            HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_sel,               2); //Auto cal the fbdiv int and frac
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_div_mode,       1); //fractional mode

            if (uiN > 4097)
            {
                HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_ratio,             10);

                if ((s_uiFsValue == _AUDIO_FS_NON_DETECT) || ((s_uiFsValue >= _AUDIO_FS_88P2K)&&(s_uiFsValue <= _AUDIO_FS_32K)))
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x16400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x4400);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     4);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   32);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   32);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
                else if(s_uiFsValue < _AUDIO_FS_88P2K)
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x44400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x16400);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     8);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   16);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   16);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
                else if(s_uiFsValue > _AUDIO_FS_32K)
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x4400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x0);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     1);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   128);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   128);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
            }
            else
            {
                HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_ratio,             11);

                if ((s_uiFsValue == _AUDIO_FS_NON_DETECT) || ((s_uiFsValue >= _AUDIO_FS_88P2K)&&(s_uiFsValue <= _AUDIO_FS_32K)))
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x16400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x4400);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     8);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   32);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   32);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
                else if(s_uiFsValue < _AUDIO_FS_88P2K)
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x44400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x16400);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     16);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   16);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   16);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
                else if(s_uiFsValue > _AUDIO_FS_32K)
                {
                    HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x4400);
                    HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x0);

                    //set prediv
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     2);

                    /* PG0 & PG0_0 & PG0_1*/
                    //set postdiv for PG0
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   128);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                    /* PG1 & PG1_0 & PG1_1*/
                    //set postdiv for PG1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   128);
                    //set postdiv0_0 for PG0_0 & PG0_1
                    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
                }
            }
            break;
        }
        case CLK_DP:
        {
            //calculate the fs
            Hv_Drv_Audio_CalculateDPFrequency();

            //set fbdiv
            HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_sel,               2); //Auto cal the fbdiv int and frac
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_div_mode,       1); //fractional mode
            HV_W32_FIELD(RX_AUDIO_TOP2_90, reg_audio_pll_0_fbdiv_ratio,             10);

            if ((s_uiFsValue == _AUDIO_FS_NON_DETECT) || ((s_uiFsValue >= _AUDIO_FS_88P2K)&&(s_uiFsValue <= _AUDIO_FS_32K)))
            {
                HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x16400);
                HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x4400);

                //set prediv
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     8);

                /* PG0 & PG0_0 & PG0_1*/
                //set postdiv for PG0
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   32);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                /* PG1 & PG1_0 & PG1_1*/
                //set postdiv for PG1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   32);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
            }
            else if(s_uiFsValue < _AUDIO_FS_88P2K)
            {
                HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x44400);
                HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x16400);

                //set prediv
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     16);

                /* PG0 & PG0_0 & PG0_1*/
                //set postdiv for PG0
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   16);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                /* PG1 & PG1_0 & PG1_1*/
                //set postdiv for PG1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   16);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
            }
            else if(s_uiFsValue > _AUDIO_FS_32K)
            {
                HV_W32_FIELD(RX_AUDIO_TOP2_E8,          reg_audpll_pg0_det_high,    0x4400);
                HV_W32_FIELD(RX_AUDIO_TOP2_EC,          reg_audpll_pg0_det_low,     0x0);

                //set prediv
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_prediv,     2);

                /* PG0 & PG0_0 & PG0_1*/
                //set postdiv for PG0
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv0,   128);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_0, 0x1a);

                /* PG1 & PG1_0 & PG1_1*/
                //set postdiv for PG1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_3, reg_audio_pll_0_postdiv1,   128);
                //set postdiv0_0 for PG0_0 & PG0_1
                HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_4, reg_audio_pll_0_postdiv0_1, 0x8);
            }

            break;
        }
        default:
        {
            //HV_LOG_ASSERT(AUDIO, "Hv_Drv_Audio_SetAllClock error!");
            return;
        }
    }

    return;
}

//PG0:      1024fs
//PG0_0     256fs
//PG0_1     128fs
//PG1       256fs
//PG1_0     256fs
//PG1_1     128fs
/**
 * @brief set PLL configures.
 */
VOID Hv_Drv_Audio_SetAudioClock(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetAudioClock.");
    Hv_Drv_Audio_ChangeClock();
    Hv_Drv_Audio_ClockLock();

    return;
}

/**
 * @brief initialize audio PLL.
 */
VOID Hv_Drv_Audio_PllInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_PllInit.");

    //enable PLL0
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_en,         _AUDIO_FLAG_ENABLE);

    /*configure CK_REF = 27MHz*/
    s_uiAudioCkRef = CLK_27M;
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  0);

    //set fbdiv & prediv & postdiv
    Hv_Drv_Audio_ManualDefaultClock();

    return;
}

/**
 * @brief initialize audio GPIO.
 */
VOID Hv_Drv_Audio_GpioInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_GpioInit.");

#ifdef HV_BOARD_CONFIG_SPEAKER
    Hv_Cal_Audio_GpioInit();
    Hv_Cal_Audio_HeadsetDetectInit();
#endif

    return;
}

/**
 * @brief initialize audio RX IP.
 */
VOID Hv_Drv_Audio_RxInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_RxInit.");

    //default channel: HDMI_0
    Hv_Cal_Audio_SetRxOut(_AUDIO_HDMI_0, CHANNEL_TYPE_MAIN);

    //configure i2s
    HV_W32_FIELD(RX_AUDIO_TOP0_08, reg_audio_i2s_rx_en,                 1);
    HV_W32_FIELD(RX_AUDIO_TOP0_00, reg_audio_i2s_rx_bit_width_sel,      0);
    HV_W32_FIELD(RX_AUDIO_TOP0_00, reg_audio_i2s_rx_bit_width,          32);
    HV_W32_FIELD(RX_AUDIO_TOP0_00, reg_audio_i2s_rx_ws_mode,            0);
    HV_W32_FIELD(RX_AUDIO_TOP0_08, reg_audio_i2s_rx_src_sel_0,          0);
    HV_W32_FIELD(RX_AUDIO_TOP0_08, reg_audio_i2s_rx_src_sel_1,          0);
    HV_W32_FIELD(RX_AUDIO_TOP0_0C, reg_audio_i2s_rx_src_sel_2,          0);
    HV_W32_FIELD(RX_AUDIO_TOP0_0C, reg_audio_i2s_rx_src_sel_3,          0);
    //configure spdif
    HV_W32_FIELD(RX_AUDIO_TOP0_04, reg_audio_spdif_rx_en,               1);
    HV_W32_FIELD(RX_AUDIO_TOP0_04, reg_audio_spdif_rx_src_sel_0,        0);
    HV_W32_FIELD(RX_AUDIO_TOP0_04, reg_audio_spdif_rx_src_sel_1,        0);
    HV_W32_FIELD(RX_AUDIO_TOP0_04, reg_audio_spdif_rx_src_sel_2,        0);
    HV_W32_FIELD(RX_AUDIO_TOP0_04, reg_audio_spdif_rx_src_sel_3,        0);

    //rx:1024fs--PG0
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_rx_clk_sel,     0);
    //dp:128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_clk_to_dp_sel,  _AUDIO_PLL_PGO_1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_clk_dp_en,      _AUDIO_PLL_PGO_1);
    //hdmi:128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP0_0C, reg_hdmi_audclk_sel,                 _AUDIO_PLL_PGO_1);
    HV_W32_FIELD(RX_AUDIO_TOP0_0C, reg_hdmi_audclk_en,                  _AUDIO_PLL_PGO_1);

    return;
}

/**
 * @brief initialize audio TX IP.
 */
VOID Hv_Drv_Audio_TxInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_TxInit.");

    //configure i2s
    HV_W32_FIELD(RX_AUDIO_TOP1_DC, reg_audio_i2s_tx_en,                 1);
    HV_W32_FIELD(RX_AUDIO_TOP1_DC, reg_audio_i2s_tx_ws_mode,            0);

    //configure spdif
    HV_W32_FIELD(RX_AUDIO_TOP1_04, reg_audio_spdif_tx_en,               1);

    //tx:128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_tx_clk_sel,     _AUDIO_PLL_PGO_1);
    //tx_mclk:256fs--PG0_0
    HV_W32_FIELD(RX_AUDIO_TOP1_DC, reg_audio_tx_i2s_mclk_sel,           _AUDIO_PLL_PGO_0);

    return;
}

/**
 * @brief initialize audio DAC IP.
 */
VOID Hv_Drv_Audio_DacInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_DacInit.");

    //enable clock
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_1, reg_audio_pll_0_dac_en,     1);

    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_0C, reg_PDBIAS,                1);
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_0C, reg_VROI,                  0);
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_0C, reg_RVMID,                 1);

    //min Volume
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,                0x1f);
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,                0x1f);

    //mute DAC
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_SCMUTE,                1);

    //Turn on Channel Analog Filter
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_PDSCL,                 0);
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_PDSCR,                 0);

    //enable DAC Digital Part Interface
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_10, reg_DACEN,                 1);

    //enable DAC Analog
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_1C, reg_DAFRSTN,               _AUDIO_STATE_WORK);

    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_0C, reg_PDBIAS,                0);

    //Turn on Channel Headphone
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_PDLBUF,                0);
    HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_PDRBUF,                0);

    return;
}

/**
 * @brief initialize audio HW IP.
 */
VOID Hv_Drv_Audio_HwInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_HwInit.");

    //mute mode: hw_mute|reg_audio_vlc_mute_en
    HV_W32_FIELD(RX_AUDIO_TOP3_14, reg_audio_vlc_mute_en_sel_ch01,      1);

    //disable avc
    HV_W32_FIELD(RX_AUDIO_TOP3_04, reg_audio_avc_en_ch01,               0);

    //enable vlc
    HV_W32_FIELD(RX_AUDIO_TOP3_10, reg_audio_vlc_en_ch01,               1);
    HV_W32_FIELD(RX_AUDIO_TOP3_10, reg_audio_vlc_fade_en_ch01,          1);
    HV_W32_FIELD(RX_AUDIO_TOP3_10, reg_audio_vlc_update_en_ch01,        1);
    HV_W32_FIELD(RX_AUDIO_TOP3_14, reg_audio_vlc_update_latch_en_ch01,  1);
    HV_W32_FIELD(RX_AUDIO_TOP4_68, reg_audio_vlc_zero_cross_x_thro_ch01,0);
    HV_W32_FIELD(RX_AUDIO_TOP4_78, reg_audio_vlc_zero_cross_y_thro_ch01,0xFFFFFF);

    //set VOL
    HV_W32_FIELD(RX_AUDIO_TOP4_48, reg_audio_vlc_gain_l_ch01,           HV_PROJECT_CONFIG_DIGITAL_MAX_VOLUME);
    HV_W32_FIELD(RX_AUDIO_TOP4_58, reg_audio_vlc_gain_r_ch01,           HV_PROJECT_CONFIG_DIGITAL_MAX_VOLUME);

#ifdef HV_PROJECT_CONFIG_AUDIO_EQ
    //configure hlpf
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf0_en_ch01,          _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf0_sel_ch01,         _AUDIO_FLAG_LPF);    //set LPF0
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf1_en_ch01,          _AUDIO_FLAG_DISABLE);//DISABLE!
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf1_sel_ch01,         _AUDIO_FLAG_HPF);    //set HPF0
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf2_en_ch01,          _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_hlpf2_sel_ch01,         _AUDIO_FLAG_HPF);    //set HPF1

    //configure bpf
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf0_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf1_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf2_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf3_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf4_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf5_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf6_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf7_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
    HV_W32_FIELD(RX_AUDIO_TOP3_08, reg_audio_eq_bpf8_en_ch01,           _AUDIO_FLAG_ENABLE); //enable
#endif

    //128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0, reg_audio_hw_clk_sel,        _AUDIO_PLL_PGO_1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_clk_hw_en,      _AUDIO_PLL_PGO_1);

    return;
}

/**
 * @brief initialize audio DM IP.
 */
VOID Hv_Drv_Audio_DmInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_DmInit.");

    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_db_en,             1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_db_en,             1);

    //clear
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_clr,               0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_clr,               1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               1);

    //dm_pre:128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0, reg_audio_dm_pre_clk_sel,    _AUDIO_PLL_PGO_1);
    //dm_post:128fs--PG0_1
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_CLK_SEL, reg_audio_dm_post_clk_sel,_AUDIO_PLL_PGO_1);

    return;
}

/**
 * @brief initialize audio interrupt.
 */
VOID Hv_Drv_Audio_InterruptInit(VOID)
{
    Hv_Cal_Audio_DataPathMuteModuleInit();
    Hv_Cal_Audio_DetectFsModuleInit();

    return;
}

/**
 * @brief initialize audio path:RX->HW->TX.
 */
VOID Hv_Drv_Audio_PathInit(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_PathInit.");

    Hv_Drv_Audio_InterruptInit();

#if defined(HV_PROJECT_CONFIG_AUDIO_EQ) || (HV_PROJECT_CONFIG_DIGITAL_AUDIO_PATH) || (HV_PROJECT_CONFIG_ADJUST_DIGITAL_VOLUME)
    //RX->HW
    HV_W32_FIELD(RX_AUDIO_TOP3_00, reg_audio_hw_pcm_sel,                0);
    //HW->TX
    HV_W32_FIELD(RX_AUDIO_TOP1_E8, reg_audio_tx_i2s_pcm_sel,            3);
    HV_W32_FIELD(RX_AUDIO_TOP1_EC, reg_audio_tx_spdif_pcm_sel,          3);
    HV_W32_FIELD(RX_AUDIO_TOP1_F0, reg_audio_tx_dac_pcm_sel,            3);
#else
    //RX->TX
    HV_W32_FIELD(RX_AUDIO_TOP1_E8, reg_audio_tx_i2s_pcm_sel,            0);
    HV_W32_FIELD(RX_AUDIO_TOP1_EC, reg_audio_tx_spdif_pcm_sel,          0);
    HV_W32_FIELD(RX_AUDIO_TOP1_F0, reg_audio_tx_dac_pcm_sel,            0);
#endif
}

/**
 * @brief set audio source.
 * @param[in] uiRxOutIndex: HDMI1/HDMI2/DP1/DP2.
 */
Status Hv_Drv_Audio_SetSource(UINT32 uiRxOutIndex, ChannelType enChannelType)
{
    s_uienChannelType = enChannelType;
    s_uiRxOutIndex = uiRxOutIndex;
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSource.");

    switch (uiRxOutIndex)
    {
        case _AUDIO_HDMI_0:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_HDMI;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  1);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_HDMI_0,    enChannelType);
            break;
        }
        case _AUDIO_HDMI_1:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_HDMI;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  1);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_HDMI_1,    enChannelType);
            break;
        }
        case _AUDIO_DP_0:
        case _AUDIO_TYPE_C_0:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_DP;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  2);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_DP_0,      enChannelType);
            break;
        }
        case _AUDIO_DP_1:
        case _AUDIO_TYPE_C_1:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_DP;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  2);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_DP_1,      enChannelType);
            break;
        }
        case _AUDIO_PATTERN:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_27M;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  0);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_PATTERN,   enChannelType);
            break;
        }
        case _AUDIO_I2S_PAD:
        {
            // configure audio_pll
            s_uiAudioCkRef = CLK_27M;
            HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_PLL_2, reg_audio_pll_0_ckref_sel,  0);

            //set RX output
            Hv_Cal_Audio_SetRxOut(_AUDIO_I2S_PAD,   enChannelType);
            break;
        }
        default:
        {
            HV_LOG_ASSERT(AUDIO, "Hv_Drv_Audio_SetSource error!");
            return HV_FAILURE;
        }
    }

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSource ,s_uiAudioCkRef= %u",s_uiAudioCkRef);

    Hv_Drv_Audio_SetAudioClock();

    return HV_SUCCESS;
}

/**
 * @brief get headset volume value from datebase.
 * @return 0-100 value.
 */
UINT32 Hv_Drv_Audio_GetHeadsetVolume(VOID)
{
    UINT32 uiDacVolumeValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_GetHeadsetVolume.");

    //read datebase
    uiDacVolumeValue = HV_COMMON_DATABASE_GET(UserData, uiHeadsetVolume);

    return uiDacVolumeValue;
}

/**
 * @brief get speaker volume value from datebase.
 * @return 0-100 value.
 */
UINT32 Hv_Drv_Audio_GetSpeakerVolume(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_GetSpeakerVolume.");

    UINT32 uiDacVolumeValue = 0;

    //read datebase
    uiDacVolumeValue = HV_COMMON_DATABASE_GET(UserData, uiSpeakerVolume);

    return uiDacVolumeValue;
}

/**
 * @brief set register's value in DAC VOL L/R.
 * @param[in] uiDacVolumeValue: 0-100.
 */
Status Hv_Drv_Audio_SetHeadsetVolume(UINT32 uiDacVolumeValue)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetHeadsetVolume.");

    if (uiDacVolumeValue > _AUDIO_MAX_VOLUME)
    {
        HV_LOG_ASSERT(AUDIO, "VolumeValue exceeds the MaxValue");
        return HV_FAILURE;
    }
    else
    {
    #ifdef HV_PROJECT_CONFIG_ADJUST_DIGITAL_VOLUME
        s_uiHeadsetVolumeValue = ((HV_PROJECT_CONFIG_DIGITAL_MAX_VOLUME * uiDacVolumeValue) / 100);
        HV_COMMON_DATABASE_SET(UserData, uiHeadsetVolume, uiDacVolumeValue);

        HV_W32_FIELD(RX_AUDIO_TOP4_48, reg_audio_vlc_gain_l_ch01, s_uiHeadsetVolumeValue);
        HV_W32_FIELD(RX_AUDIO_TOP4_58, reg_audio_vlc_gain_r_ch01, s_uiHeadsetVolumeValue);
    #else
        s_uiHeadsetVolumeValue = ((128 * uiDacVolumeValue) / 100);
        HV_COMMON_DATABASE_SET(UserData, uiHeadsetVolume, uiDacVolumeValue);

        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_14, reg_DACVOLL, s_uiHeadsetVolumeValue);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_18, reg_DACVOLR, s_uiHeadsetVolumeValue);
    #endif
    }

    return HV_SUCCESS;
}

/**
 * @brief set register's value in DAC VOL L/R.
 * @param[in] uiDacVolumeValue: 0-100.
 */
Status Hv_Drv_Audio_SetSpeakerVolume(UINT32 uiDacVolumeValue)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSpeakerVolume.");

    if (uiDacVolumeValue > _AUDIO_MAX_VOLUME)
    {
        HV_LOG_ASSERT(AUDIO, "VolumeValue exceeds the MaxValue");
        return HV_FAILURE;
    }
    else
    {
    #ifdef HV_PROJECT_CONFIG_ADJUST_DIGITAL_VOLUME
        s_uiSpeakerVolumeValue = ((HV_PROJECT_CONFIG_DIGITAL_MAX_VOLUME * uiDacVolumeValue) / 100);
        HV_COMMON_DATABASE_SET(UserData, uiSpeakerVolume, uiDacVolumeValue);

        HV_W32_FIELD(RX_AUDIO_TOP4_48, reg_audio_vlc_gain_l_ch01, s_uiSpeakerVolumeValue);
        HV_W32_FIELD(RX_AUDIO_TOP4_58, reg_audio_vlc_gain_r_ch01, s_uiSpeakerVolumeValue);
    #else
        s_uiSpeakerVolumeValue = ((128 * uiDacVolumeValue) / 100);
        HV_COMMON_DATABASE_SET(UserData, uiSpeakerVolume, uiDacVolumeValue);

        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_14, reg_DACVOLL, s_uiSpeakerVolumeValue);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_18, reg_DACVOLR, s_uiSpeakerVolumeValue);
    #endif
    }

    return HV_SUCCESS;
}

/**
 * @brief Set Mute Bit.
 */
void Hv_Drv_Audio_SetMuteBit(UINT32 uiBitMsk)
{
    g_uiMuteState |= uiBitMsk;
    //HV_LOG_INFO(AUDIO, "SetMuteBit: set 0x%x, MuteState = 0x%x.", uiBitMsk, g_uiMuteState);
}

/**
 * @brief Clear Mute Bit.
 */
void Hv_Drv_Audio_ClearMuteBit(UINT32 uiBitMsk)
{
    g_uiMuteState &= ~uiBitMsk;
    //HV_LOG_INFO(AUDIO, "ClearMuteBit: Clear 0x%x, MuteState = 0x%x.", uiBitMsk, g_uiMuteState);
}

/**
 * @brief mute audio DAC from UI.
 */
VOID Hv_Drv_Audio_DACMute(UINT32 uiBitMsk)
{
    Hv_Drv_Audio_SetMuteBit(uiBitMsk);

    if(g_uiMuteState)
    {
    #ifdef HV_BOARD_CONFIG_SPEAKER
        Hv_Cal_Audio_SpeakerMute();
    #endif

    #ifndef HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,                        0x3);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,                        0x3);
    #else
        if(g_bHeadsetInsertion)
        {
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_HEADSET);
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_HEADSET);
        }
        else
        {
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_SPEAKER);
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_SPEAKER);
        }
    #endif

        //Mute DAC
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_SCMUTE,                        HV_ON);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_10, reg_DACMUTEL,                      HV_ON);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_10, reg_DACMUTER,                      HV_ON);
    }

    return;
}

/**
 * @brief unmute audio DAC from UI.
 */
VOID Hv_Drv_Audio_DACUnMute(UINT32 uiBitMsk)
{
    if(g_uiMuteState == 0)
    {
        return;
    }

    Hv_Drv_Audio_ClearMuteBit(uiBitMsk);

    if(g_uiMuteState == 0)
    {
        //UnMute DAC
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_10, reg_DACMUTEL,                      HV_OFF);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_10, reg_DACMUTER,                      HV_OFF);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_08, reg_SCMUTE,                        HV_OFF);

    #ifndef HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,                        0x3);
        HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,                        0x3);
    #else
        if(g_bHeadsetInsertion)
        {
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_HEADSET);
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_HEADSET);
        }
        else
        {
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_00, reg_DACAVL,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_SPEAKER);
            HV_W32_FIELD(AUDIO_DAC_AUDIO_DAC_TOP_04, reg_DACAVR,    HV_PROJECT_CONFIG_ANALOG_MAX_VOLUME_SPEAKER);
        }
    #endif

        //Trigger Mute to prevent losing interrupt of edge_n
        Hv_Cal_Audio_SetMuteTrigger();

    #ifdef HV_BOARD_CONFIG_SPEAKER
        Hv_Cal_Audio_SpeakerUnMute();
    #endif
    }

    return;
}

/**
 * @brief mute audio path from channel manager.
 */
VOID Hv_Drv_Audio_TXMute(UINT32 uiBitMsk)
{
    //mute DAC first
    Hv_Drv_Audio_DACMute(uiBitMsk);

    //mute TX by software. At the same moment, Hardware has muted also.
    HV_W32_FIELD(RX_AUDIO_TOP0_04,          reg_audio_sw_mute_en,               0x1);

    return;
}

/**
 * @brief unmute audio path from channel manager.
 */
VOID Hv_Drv_Audio_TXUnMute(UINT32 uiBitMsk)
{
    BOOL bDpisPlay = HV_TRUE;
    if(s_uiRxOutIndex == _AUDIO_HDMI_0)
    {
        HV_W32_FIELD(RX_HDMI21_RX_POST_0_PROC_00_08, reg_00_audio_afif_init, 1);
        HV_W32_FIELD(RX_HDMI21_RX_POST_0_PROC_00_08, reg_00_audio_afif_init, 0);
        bDpisPlay = HV_FALSE;
    }

    if(s_uiRxOutIndex == _AUDIO_HDMI_1)
    {
        HV_W32_FIELD(RX_HDMI21_RX_POST_0_PROC_01_08, reg_01_audio_afif_init, 1);
        HV_W32_FIELD(RX_HDMI21_RX_POST_0_PROC_01_08, reg_01_audio_afif_init, 0);
        bDpisPlay = HV_FALSE;
    }

    //clear hardware mute and enable interrupts
    Hv_Cal_Audio_ClearTXMute_EnableAllInt(bDpisPlay);

    //unmute software mute
    HV_W32_FIELD(RX_AUDIO_TOP0_04,          reg_audio_sw_mute_en,               0x0);
    HV_W32_FIELD(RX_AUDIO_TOP0_04,          reg_audio_mute_clr,                 1);
    HV_W32_FIELD(RX_AUDIO_TOP0_04,          reg_audio_mute_clr,                 0);

    Hv_Drv_Audio_DACUnMute(uiBitMsk);

    return;
}

#ifdef HV_PROJECT_CONFIG_AUDIO_EQ
/**
 * @brief set default value to s_tAudioEqData.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetEQDefaultValue(UINT32 uiEQMode)
{
    switch (uiEQMode)
    {
        case ROCK_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_rock, tAudioEqHpf0_rock,      tAudioEqBpf0_rock,
                tAudioEqBpf1_rock,      tAudioEqBpf2_rock,      tAudioEqBpf3_rock,      tAudioEqBpf4_rock};
            s_tAudioEqData[ROCK_MODE] = stAudioEqDataTemp;
            break;
        }
        case POP_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_pop,  tAudioEqHpf0_pop,       tAudioEqBpf0_pop,
                tAudioEqBpf1_pop,       tAudioEqBpf2_pop,       tAudioEqBpf3_pop,       tAudioEqBpf4_pop};
            s_tAudioEqData[POP_MODE] = stAudioEqDataTemp;
            break;
        }
        case LIVE_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_live, tAudioEqHpf0_live,      tAudioEqBpf0_live,
                tAudioEqBpf1_live,      tAudioEqBpf2_live,      tAudioEqBpf3_live,      tAudioEqBpf4_live};

            s_tAudioEqData[LIVE_MODE] = stAudioEqDataTemp;
            break;
        }
        case DANCE_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_dance,tAudioEqHpf0_dance,     tAudioEqBpf0_dance,
                tAudioEqBpf1_dance,     tAudioEqBpf2_dance,     tAudioEqBpf3_dance,     tAudioEqBpf4_dance};
            s_tAudioEqData[DANCE_MODE] = stAudioEqDataTemp;
            break;
        }
        case CLUB_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_club, tAudioEqHpf0_club,      tAudioEqBpf0_club,
                tAudioEqBpf1_club,      tAudioEqBpf2_club,      tAudioEqBpf3_club,      tAudioEqBpf4_club};
            s_tAudioEqData[CLUB_MODE] = stAudioEqDataTemp;
            break;
        }
        case POWER_MODE:
        {
            AudioEqData stAudioEqDataTemp = {tAudioEqLpf0_powerful, tAudioEqHpf0_powerful,  tAudioEqBpf0_powerful,
                tAudioEqBpf1_powerful,  tAudioEqBpf2_powerful,      tAudioEqBpf3_powerful,  tAudioEqBpf4_powerful};
            s_tAudioEqData[POWER_MODE] = stAudioEqDataTemp;
            break;
        }
        default:
        {
            HV_LOG_ASSERT(AUDIO, "Hv_Drv_Audio_SetEQDefaultValue error!");
            return;
        }
    }

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] : uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetLpf0DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadLPF0.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqLpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_1C, reg_audio_eq_hlpf0_a_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqLpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_24, reg_audio_eq_hlpf0_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetHpf0DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadHPF0.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqHpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_2C, reg_audio_eq_hlpf1_a_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqHpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_30, reg_audio_eq_hlpf1_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetBpf0DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadBPF0.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_C4, reg_audio_eq_bpf0_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_CC, reg_audio_eq_bpf0_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_D4, reg_audio_eq_bpf0_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetBpf1DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadBPF1.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_DC, reg_audio_eq_bpf1_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_E4, reg_audio_eq_bpf1_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_EC, reg_audio_eq_bpf1_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetBpf2DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadBPF2.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F4, reg_audio_eq_bpf2_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F4, reg_audio_eq_bpf2_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F8, reg_audio_eq_bpf2_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetBpf3DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadBPF3.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F8, reg_audio_eq_bpf3_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_FC, reg_audio_eq_bpf3_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_FC, reg_audio_eq_bpf3_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_GetBpf4DataAndSetRegs(UINT32 uiEQMode)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_LoadBPF4.");

    s_tAudioEqData[uiEQMode] = HV_COMMON_DATABASE_GET(SystemData, stAudioEqDataBase[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_00, reg_audio_eq_bpf4_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_00, reg_audio_eq_bpf4_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_04, reg_audio_eq_bpf4_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
 VOID Hv_Drv_Audio_SetLpf0DataAndSetRegs(UINT32 uiEQMode, AudioLpfData stAudioLpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveLPF0.");

    s_tAudioEqData[uiEQMode].stAudioEqLpf0 = stAudioLpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqLpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_1C, reg_audio_eq_hlpf0_a_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqLpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_24, reg_audio_eq_hlpf0_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetHpf0DataAndSetRegs(UINT32 uiEQMode, AudioHpfData stAudioHpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveHPF0.");

    s_tAudioEqData[uiEQMode].stAudioEqHpf0 = stAudioHpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqHpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_2C, reg_audio_eq_hlpf1_a_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqHpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_30, reg_audio_eq_hlpf1_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetBpf0DataAndSetRegs(UINT32 uiEQMode, AudioBpfData stAudioBpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveBPF0.");

    s_tAudioEqData[uiEQMode].stAudioEqBpf0 = stAudioBpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_C4, reg_audio_eq_bpf0_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_CC, reg_audio_eq_bpf0_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf0.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_D4, reg_audio_eq_bpf0_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetBpf1DataAndSetRegs(UINT32 uiEQMode, AudioBpfData stAudioBpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveBPF1.");

    s_tAudioEqData[uiEQMode].stAudioEqBpf1 = stAudioBpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_DC, reg_audio_eq_bpf1_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_E4, reg_audio_eq_bpf1_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf1.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_EC, reg_audio_eq_bpf1_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetBpf2DataAndSetRegs(UINT32 uiEQMode, AudioBpfData stAudioBpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveBPF2.");

    s_tAudioEqData[uiEQMode].stAudioEqBpf2 = stAudioBpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F4, reg_audio_eq_bpf2_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F4, reg_audio_eq_bpf2_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf2.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F8, reg_audio_eq_bpf2_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetBpf3DataAndSetRegs(UINT32 uiEQMode, AudioBpfData stAudioBpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveBPF3.");

    s_tAudioEqData[uiEQMode].stAudioEqBpf3 = stAudioBpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_F8, reg_audio_eq_bpf3_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP3_FC, reg_audio_eq_bpf3_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf3.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP3_FC, reg_audio_eq_bpf3_h_ch01, uiValue);

    return;
}

/**
 * @brief set 0-100 value to driver.
 * @param[in] uiEQMode: Rock/Pop/Live/Dance/Club/Powerful MODE.
 */
VOID Hv_Drv_Audio_SetBpf4DataAndSetRegs(UINT32 uiEQMode, AudioBpfData stAudioBpfData)
{
    UINT32 uiValue = 0;

    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SaveBPF4.");

    s_tAudioEqData[uiEQMode].stAudioEqBpf4 = stAudioBpfData;
    HV_COMMON_DATABASE_SET(SystemData, stAudioEqDataBase[uiEQMode], s_tAudioEqData[uiEQMode]);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iA1Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_00, reg_audio_eq_bpf4_a1_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iA2Hex;
    HV_W32_FIELD(RX_AUDIO_TOP4_00, reg_audio_eq_bpf4_a2_ch01, uiValue);

    uiValue = s_tAudioEqData[uiEQMode].stAudioEqBpf4.iHHex;
    HV_W32_FIELD(RX_AUDIO_TOP4_04, reg_audio_eq_bpf4_h_ch01, uiValue);

    return;
}
#endif

/**
 * @brief set DDR size value in DM register.
 */
VOID Hv_Drv_Audio_SetSoundDelayDDRSize(UINT32 uiDelayTime)
{
    UINT32 uiDDRSize = 0;
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSoundDelayDDRSize.");
    uiDDRSize = (uiDelayTime/50) * 300; //burst_num:50ms=300num
    HV_LOG_DEBUG(AUDIO, "burst_num = %d.\n", uiDDRSize);

    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1,  reg_dm_rd_burst_len,        _AUDIO_DM_BURST_LEN);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_2,  reg_dm_rd_burst_num,        uiDDRSize);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_3,  reg_dm_rd_burst_rmd,        _AUDIO_DM_BURST_RMD);

    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9,  reg_dm_wr_burst_len,        _AUDIO_DM_BURST_LEN);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_10, reg_dm_wr_burst_num,        uiDDRSize);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9,  reg_dm_wr_burst_rmd,        _AUDIO_DM_BURST_RMD);

    uiDDRSize = (((_AUDIO_DM_BURST_LEN+1)/8 + _AUDIO_DM_BURST_RMD) * 128) * uiDDRSize;
    HV_LOG_DEBUG(AUDIO, "SoundDelayDDRSize = 0x%x.\n", uiDDRSize);

    return;
}

/**
 * @brief set DDR Address value in DM register.
 */
VOID Hv_Drv_Audio_SetSoundDelayDDRAddress(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSoundDelayDDRAddress.");
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_7,  reg_dm_rd_start_adr, HV_MEMORY_CONFIG_AUDIO_DMA_DDR_START);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_13, reg_dm_wr_start_adr, HV_MEMORY_CONFIG_AUDIO_DMA_DDR_START);
    HV_LOG_DEBUG(AUDIO, "SoundDelayDDRAddress = 0x%08x.\n", HV_MEMORY_CONFIG_AUDIO_DMA_DDR_START);
    return;
}

/**
 * @brief enalbe the DM write module.
 */
VOID Hv_Drv_Audio_DmWriteEnable(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_DmWriteEnable.");

    //init write-ddr
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0, reg_audio_dm_w_en,           1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_enable,            1);

    //clear
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               1);

    s_uiDmWriteReady = 1;
    return;
}

/**
 * @brief enalbe the DM read module.
 */
VOID Hv_Drv_Audio_DmReadEnable(VOID *pvArg, USHORT16 usTimerId)
{
    HV_LOG_DEBUG(AUDIO, "Audio timer delay time out Hv_Drv_Audio_DmReadEnable.");

    if (!s_uiDmWriteReady)
    {
        HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_DmReadEnable: Write disable.");
        return;
    }

    //init read-ddr
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0, reg_audio_dm_r_en,           1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_enable,            1);

    //RX->DM
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0, reg_audio_dm_pcm_sel,        0);
#if defined(HV_PROJECT_CONFIG_AUDIO_EQ) || (HV_PROJECT_CONFIG_DIGITAL_AUDIO_PATH) || (HV_PROJECT_CONFIG_ADJUST_DIGITAL_VOLUME)
    //DM->HW
    HV_W32_FIELD(RX_AUDIO_TOP3_00, reg_audio_hw_pcm_sel,                1);
#else
    //DM->TX
    HV_W32_FIELD(RX_AUDIO_TOP1_E8, reg_audio_tx_i2s_pcm_sel,            1);
    HV_W32_FIELD(RX_AUDIO_TOP1_EC, reg_audio_tx_spdif_pcm_sel,          1);
    HV_W32_FIELD(RX_AUDIO_TOP1_F0, reg_audio_tx_dac_pcm_sel,            1);
#endif

    //clear
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9, reg_dm_wr_clr,               1);

    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_clr,               0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1, reg_dm_rd_clr,               1);

    return;
}

/**
 * @brief disalbe the DM module.
 */
VOID Hv_Drv_Audio_DmDisable(VOID)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_DmDisable.");
    //clear
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1,  reg_dm_rd_clr,              0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1,  reg_dm_rd_clr,              1);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9,  reg_dm_wr_clr,              0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9,  reg_dm_wr_clr,              1);

    //disable
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0,  reg_audio_dm_r_en,          0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_1,  reg_dm_rd_enable,           0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_0,  reg_audio_dm_w_en,          0);
    HV_W32_FIELD(RX_AUDIO_TOP2_AUDIO_DM_9,  reg_dm_wr_enable,           0);

#if defined(HV_PROJECT_CONFIG_AUDIO_EQ) || (HV_PROJECT_CONFIG_DIGITAL_AUDIO_PATH) || (HV_PROJECT_CONFIG_ADJUST_DIGITAL_VOLUME)
    //RX->HW
    HV_W32_FIELD(RX_AUDIO_TOP3_00,          reg_audio_hw_pcm_sel,       0);
#else
    //RX->TX
    HV_W32_FIELD(RX_AUDIO_TOP1_E8, reg_audio_tx_i2s_pcm_sel,            0);
    HV_W32_FIELD(RX_AUDIO_TOP1_EC, reg_audio_tx_spdif_pcm_sel,          0);
    HV_W32_FIELD(RX_AUDIO_TOP1_F0, reg_audio_tx_dac_pcm_sel,            0);
#endif

    s_uiDmWriteReady = 0;
    return;
}

/**
 * @brief audio spdif out.
 */
VOID Hv_Drv_Audio_SetSpdifOutMode(BOOL bAudioSpdifOut)
{
    HV_LOG_DEBUG(AUDIO, "Hv_Drv_Audio_SetSpdifOutMode.");
    Hv_Cal_Audio_SetSpdifOutGpio(bAudioSpdifOut);
    return;
}

