/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author:
 * $Date:
 * $RCSfile:
 * $Revision:
 *
 *---------------------------------------------------------------------------*/

#define AUD_EXTERN_FILE

//=======================
// [**CAUTION**]
// Please exclude Loader
//=======================
#if ((!defined(CC_MTK_PRELOADER)) && (!defined(CC_MTK_LOADER)))

//---------------------------------------------------------------------------
// Include files
//---------------------------------------------------------------------------

#include <asm/io.h>
#include "linux/delay.h"
#include "sif_if.h"
#include "aud_amp_RT9119.h"
#include "sakura_aud_aq_data.h"

#define AUD_CUST_AMP_I2C_CTRL0_ADDRESS       (0x10029240)
#define AUD_CUST_AMP_I2C_CTRL1_ADDRESS       (0x10029244)
#define AUD_CUST_AMP_I2C_CTRL2_ADDRESS       (0x10029248)
#define AUD_CUST_AMP_I2C_CTRL3_ADDRESS       (0x100292FC)
#define AUD_CUST_AMP_I2C_CTRL_SIZE           (4)

extern const unsigned int db0p1ToLenear20000[];
extern const unsigned int db0p1ToDrc_T[];
extern const unsigned int db0p1ToDrc_O[];
extern const unsigned int ms0p1ToDrc_AaAe[];
extern const unsigned int s0p1ToDrc_Ad[];
extern const unsigned int s0p1ToDrc_1_AeAaAd[];
extern const unsigned char ms0p1ToDrc_Delay[];
static int RT9119_db_to_volume(int);
typedef struct {
    int    mixL;
    int    mixR;
} RT9119_ChannelMixer;

typedef struct {
    RT9119_ChannelMixer   ch1;
    RT9119_ChannelMixer   ch2;
} RT9119_OutputMixer;


static void RT9119_le32toDataBuf(UINT32 le32, unsigned char* dst, const unsigned int size);
static void RT9119_dataBufToLe32(unsigned char* src, UINT32* le32, const unsigned int size);


RT9119_HANDLE   sRT9119Handle[RT9119_AMP_ID_MAX] =
{
    {RT9119_FALSE, RT9119_AMP_ID_INVALID, 0, 0, RT9119_NULL},
    {RT9119_FALSE, RT9119_AMP_ID_INVALID, 0, 0, RT9119_NULL}
};

/** RT9119_CreateHandle
 *  Create Handle
 *  @param  AmpId
 *  @param  reg
 *  @retval Handle
 */
RT9119_HANDLE* RT9119_CreateHandle(RT9119_AmpId ampId, RT9119Reg* reg)
{
    if(!reg) {
        return RT9119_NULL;
    }
    if(RT9119_AMP_ID_MAX <= ampId) {
        return RT9119_NULL;
    }
    if(sRT9119Handle[ampId].IsUsed) {
        return RT9119_NULL;
    }
    sRT9119Handle[ampId].IsUsed = RT9119_TRUE;
    sRT9119Handle[ampId].Id = ampId;
    sRT9119Handle[ampId].u2ClkDiv = 0x0;
    sRT9119Handle[ampId].u1DevAddr = ((ampId == RT9119_AMP_ID_MAIN_SPEAKER) ? 0x34 : 0x36);
    sRT9119Handle[ampId].Reg = reg;
    LOG(0,"RT9119_CreateHandle ampId=0x%x u2ClkDiv=0x%x u1DevAddr=0x%x\n", ampId, sRT9119Handle[ampId].u2ClkDiv, sRT9119Handle[ampId].u1DevAddr);
    return &sRT9119Handle[ampId];
}

/** RT9119_DeleteHandle
 *  Delete Handle
 *  @param  handle
 *  @retval void
 */
void RT9119_DeleteHandle(RT9119_HANDLE* handle)
{
    LOG(0,"RT9119_DeleteHandle ampId=0x%x u2ClkDiv=0x%x u1DevAddr=0x%x\n", handle->Id, handle->u2ClkDiv, handle->u1DevAddr);
    handle->IsUsed = RT9119_FALSE;
    handle->Id = RT9119_AMP_ID_INVALID;
    handle->Reg = RT9119_NULL;
}

UINT16 RT9119_Reg_Write(UINT8 u1CHannelID,
                        UINT16 u2ClkDiv,
                        UINT8 u1DevAddr,
                        UINT8 u1WordAddrNum,
                        UINT32 u4WordAddr,
                        UINT8* pu1Buf,
                        UINT16 u2ByteCnt)
{
    UINT16 u2WriteNum;
    static BOOL isDetectedError = FALSE;

    u2WriteNum = SIF_X_Write(u1CHannelID, u2ClkDiv, u1DevAddr, u1WordAddrNum, u4WordAddr, pu1Buf, u2ByteCnt);
    if(!u2WriteNum)
    {
        if(!isDetectedError)
        {
            isDetectedError = TRUE;
            LOG(0,"RT9119_Reg_Write error argument(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, %p, 0x%x)\n",
                u1CHannelID, u2ClkDiv, u1DevAddr, u1WordAddrNum, u4WordAddr, pu1Buf, u2ByteCnt);
            {
                UINT32 reg = 0;
                void* mem = NULL;

                mem = ioremap(AUD_CUST_AMP_I2C_CTRL0_ADDRESS, AUD_CUST_AMP_I2C_CTRL_SIZE);
                reg = readl(mem);
                LOG(0, " =====> I2C_CTRL0:%08x\n", reg);
                iounmap(mem);
                mem = ioremap(AUD_CUST_AMP_I2C_CTRL1_ADDRESS, AUD_CUST_AMP_I2C_CTRL_SIZE);
                reg = readl(mem);
                LOG(0, " =====> I2C_CTRL1:%08x\n", reg);
                iounmap(mem);
                mem = ioremap(AUD_CUST_AMP_I2C_CTRL2_ADDRESS, AUD_CUST_AMP_I2C_CTRL_SIZE);
                reg = readl(mem);
                LOG(0, " =====> I2C_CTRL2:%08x\n", reg);
                iounmap(mem);
                mem = ioremap(AUD_CUST_AMP_I2C_CTRL3_ADDRESS, AUD_CUST_AMP_I2C_CTRL_SIZE);
                reg = readl(mem);
                LOG(0, " =====> I2C_CTRL3:%08x\n", reg);
                iounmap(mem);
            }
        }
    }
    else
    {
        isDetectedError = FALSE;
    }
    return u2WriteNum;
}

RT9119_Error RT9119_Init_General(RT9119_HANDLE* handle)
{
    UINT16  u2WriteNum = 0;
    RT9119_Error ret = RT9119_E_ACCESS;
    UINT32  u4RegValue;
    int i;

    // Wait PWDNN HI
    {
        UINT32 u4GpioAmp;
        AUD_AMP_GPIO_POLARITY_T eAmpPolariy;
        INT32 i4RegAoutSwitch = 0;

        u4GpioAmp = DRVCUST_OptGet(eAudioAmpEnableGpioNum);
        if (u4GpioAmp != 0xffffffff)
        {
            eAmpPolariy = (AUD_AMP_GPIO_POLARITY_T)DRVCUST_OptGet(eAudioAmpGpioPolarity);
            if (eAmpPolariy == AUD_AMP_GPIO_HIGH_ENALBE)
            {
                i4RegAoutSwitch = 1;
            }
            else {
                i4RegAoutSwitch = 0;
            }
        }
        while(GPIO_Output(u4GpioAmp, NULL) != i4RegAoutSwitch) {
            msleep(10);
        }
    }
    //I2C Signal Stable
    msleep(1);
    LOG(2,"SONY debug : Finished GPIO_AMP_ENABLE Checking\n");

    do {
        // 4. Master Volume
        u4RegValue = 0x7ff; // MUTE
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->masterVolume, RT9119_REG_MS_VOL_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_MS_VOL, handle->Reg->masterVolume, RT9119_REG_MS_VOL_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 5. SYS_CTL: Shutdown ON, Disable A_SEL and SCLK
        handle->Reg->sys_ctl[0] = (RT9119_SHUDOWN_ON | RT9119_D_SPK_VT_FREQ_800K| RT9119_DIS_A_SEL_PU_DISABLE | RT9119_DREF_SEL_SCLK);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SYS_CTL, handle->Reg->sys_ctl, RT9119_REG_SYS_CTL_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }

        // 6. FLTR_MISC
        handle->Reg->fltrMisc[0] = (RT9119_HPF_ENABLE | RT9119_HPF_POS_ENABLE | (RT9119_REG_COMP_DISABLE)| RT9119_FIR_DISABLE | RT9119_SRC_RES_SEL_32 | RT9119_PAGE_SEL_DEFAULT);
        //handle->Reg->fltrMisc[0] &= ~(RT9119_FIR_ENABLE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FLTR_MISC, handle->Reg->fltrMisc, RT9119_REG_FLTR_MISC_SIZE);
        if(!u2WriteNum) {
            break;
        }
        //FIR
        //Initialize FIR DRAM Backup
        {
            //u4RegValue = RT9119_FIR_CLEAR;
            for(i=0;i<RT9119_FIR_TAP_NO;i++){
                RT9119_le32toDataBuf(0, &handle->Reg->fir[i][0], RT9119_FIR_COEFF_SIZE);
            }
        }
        // 7. DC Protection Enable
        handle->Reg->dcProtect[0] = RT9119_DC_TH_18p75 | RT9119_DC_TIME_342 | RT9119_DC_FREQ_768K  | RT9119_DC_PROTECT_ENABLE; // 0x21
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DC_PROTECT, handle->Reg->dcProtect, RT9119_REG_DC_PROTECT_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 8. DRC_CTRL1
        handle->Reg->drcCtrl1[0] = (RT9119_DRCPeak | RT9119_DRC1_DISABLE|RT9119_DRC2_DISABLE |RT9119_DRC3_DISABLE|RT9119_DRC4_DISABLE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_CTRL1, handle->Reg->drcCtrl1, RT9119_REG_DRC_CTRL1_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 9. DRC_CTRL2
        handle->Reg->drcCtrl2[0] = (RT9119_DRCxNoiseGate(1, RT9119_DRC_NOISE_GATE_DISABLE) | RT9119_DRCxNoiseGate(2, RT9119_DRC_NOISE_GATE_DISABLE)
                                | RT9119_DRCxNoiseGate(3, RT9119_DRC_NOISE_GATE_DISABLE) | RT9119_DRCxNoiseGate(4, RT9119_DRC_NOISE_GATE_DISABLE)
                                | RT9119_REG_DRC2_BYPASS_ENABLE | RT9119_REG_DRC1_BYPASS_DISABLE| RT9119_REG_DRC3_BYPASS_ENABLE | RT9119_FREQ_DRC_MODE_ON   );
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_CTRL2, handle->Reg->drcCtrl2, RT9119_REG_DRC_CTRL2_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 10. Final Gain Output
        handle->Reg->gainOpt[0] = RT9119_FINAL_GAIN_0DB | RT9119_GAIN_PAIR_CTRL_0DB;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FINAL_GAIN_OPT, handle->Reg->gainOpt, RT9119_REG_FINAL_GAIN_OUT_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 11. Audio Interface mode
        handle->Reg->i2sFmt[0] = RT9119_AUD_MODE_32BIT_I2S;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_I2S_FMT, handle->Reg->i2sFmt, RT9119_REG_I2S_FMT_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 12. VOL_RAMP
        handle->Reg->volRamp[0] = RT9119_VOL_RAMP_STEP_512; //0x00
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_VOL_RAMP, handle->Reg->volRamp, RT9119_REG_VOL_RAMP_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 13. Power
        handle->Reg->autoRcvry[0] = RT9119_BKD_TIME_300MS;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_AUTO_RCVRY, handle->Reg->autoRcvry, RT9119_REG_AUTO_RCVRY_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 14. Error Type
        handle->Reg->errType[0] = RT9119_FAULT_TYPE(7, RT9119_FAULT_TYPE_RECV)|RT9119_FAULT_TYPE(6, RT9119_FAULT_TYPE_RECV)|RT9119_FAULT_TYPE(5, RT9119_FAULT_TYPE_RECV)\
                                    |RT9119_FAULT_TYPE(4, RT9119_FAULT_TYPE_LATCH)|RT9119_FAULT_TYPE(3, RT9119_FAULT_TYPE_LATCH)|RT9119_FAULT_TYPE(2, RT9119_FAULT_TYPE_LATCH)\
                                    |RT9119_FAULT_TYPE(1, RT9119_FAULT_TYPE_RECV);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_ERROR_TYPE, handle->Reg->errType, RT9119_REG_ERROR_TYPE_SIZE);
        if(!u2WriteNum) {
            break;
        }
        // 15. Error Mask
        handle->Reg->errMask[0] = RT9119_ERROR_MASK(7, RT9119_ERR_MASK_ENABLE)|RT9119_ERROR_MASK(6, RT9119_ERR_MASK_ENABLE)|RT9119_ERROR_MASK(5, RT9119_ERR_MASK_ENABLE)\
                                    |RT9119_ERROR_MASK(2, RT9119_ERR_MASK_DISABLE)|RT9119_ERROR_MASK(3, RT9119_ERR_MASK_DISABLE)|RT9119_ERROR_MASK(2, RT9119_ERR_MASK_DISABLE)\
                                    |RT9119_ERROR_MASK(1, RT9119_ERR_MASK_ENABLE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_ERROR_MASK, handle->Reg->errMask, RT9119_REG_ERROR_MASK_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 16. Input setting
        handle->Reg->sdIoSel[0] = RT9119_CH_NORMAL;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SDIO_SEL, handle->Reg->sdIoSel, RT9119_REG_SDIO_SEL_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 17. Channel Volume
        u4RegValue = 0x180; // 0dB
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->ch1Volume, RT9119_REG_CH1_VOL_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_VOL, handle->Reg->ch1Volume, RT9119_REG_CH1_VOL_SIZE);
        if(!u2WriteNum) {
            break;
        }
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->ch2Volume, RT9119_REG_CH2_VOL_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH2_VOL, handle->Reg->ch2Volume, RT9119_REG_CH2_VOL_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 18. POST IDF setting with HW Clipper
        u4RegValue = RT9119_HARD_CLIP_DISABLE | RT9119_DF_CLIP_ENABLE | (RT9119_HARD_CLIP_TH_24DB<<RT9119_REG_SHIFT_HARD_CLIP_TH) | RT9119_POST_IDF_0DB;
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->hardClip, RT9119_REG_HARD_CLIP_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_HARD_CLIP, handle->Reg->hardClip, RT9119_REG_HARD_CLIP_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // 19. PWM_SS_OPT
        handle->Reg->pwmSsOpt[0] = RT9119_REG_PWM_SS_OPT_DEFAULT;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_PWM_SS_OPT1, handle->Reg->pwmSsOpt, RT9119_REG_PWM_SS_OPT_SIZE);
        if(!u2WriteNum) {
            break;
        }
        ret = RT9119_E_OK;
    } while(0);
    return ret;
}

/** RT9119_SetOutputMode
 *  Set Output Mode
 *  @param  handle
 *  @param  mode : mono/stereo
 *  @retval OK/NG
 *  CAUTION : this shall be done before MUTEX H
 */
RT9119_Error RT9119_SetOutputMode(RT9119_HANDLE* handle, RT9119_OutputMode mode)
{
    UINT16 u2WriteNum;

    // Set Output Mode
    if(mode == RT9119_OUTPUT_MODE_STEREO) {
        handle->Reg->interPwrCtrl[0] =    RT9119_DAC_LPF_R_ENABLE
                                        | RT9119_DAC_LPF_L_ENABLE
                                        | RT9119_DAC_PWR_R_ENABLE
                                        | RT9119_DAC_PWR_L_ENABLE
                                        | RT9119_DAC_RCH_ENABLE
                                        | RT9119_DAC_LCH_ENABLE
                                        | RT9119_SPK_RCH_ENABLE
                                        | RT9119_SPK_LCH_ENABLE;    // Stereo setting
    }
    else {
        handle->Reg->interPwrCtrl[0] =    RT9119_DAC_LPF_R_DISABLE
                                        | RT9119_DAC_LPF_L_ENABLE
                                        | RT9119_DAC_PWR_R_DISABLE
                                        | RT9119_DAC_PWR_L_ENABLE
                                        | RT9119_DAC_RCH_DISABLE
                                        | RT9119_DAC_LCH_ENABLE
                                        | RT9119_SPK_RCH_DISABLE
                                        | RT9119_SPK_LCH_ENABLE;    // Mono setting
    }
    u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_INTER_PWR_CTRL, handle->Reg->interPwrCtrl, RT9119_REG_INTER_PWR_CTRL_SIZE);
    if(!u2WriteNum) {
        return RT9119_E_ACCESS;
    }
    return RT9119_E_OK;
}

/** RT9119_SetOutputGain
 *  Set Output Gain
 *  @param  handle
 *  @retval OK/NG
 */
RT9119_Error RT9119_Init_DSP_Functions(RT9119_HANDLE* handle)
{
    UINT16 u2WriteNum;
    UINT32  u4RegValue;
    RT9119_BqCoeff  coeff;
    RT9119_Error ret = RT9119_E_ACCESS;
    int i;
    do {
        // Class D gain
        handle->Reg->spkGain[0] = RT9119_SPK_GAIN_8p00;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SPK_GAIN, handle->Reg->spkGain, RT9119_REG_SPK_GAIN_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // Depop Function
        handle->Reg->depopGlitch[0] = RT9119_DEPOP_GLITCH_DISABLE;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DEPOP_GLITCH, handle->Reg->depopGlitch, RT9119_REG_DEPOP_GLITCH_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // SST
        handle->Reg->servotimeOpt[0] = RT9119_SST_40MS;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SERVO_TIME_OPT, handle->Reg->servotimeOpt, RT9119_REG_SERVO_TIME_OPT_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // Clear Error Flags
        handle->Reg->errReport[0] = RT9119_ERR_RPT_CLEAR;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_ERR_RPT, handle->Reg->errReport, RT9119_REG_ERR_RPT_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }

        //BQs LINK
        handle->Reg->eqCtrl[0] = RT9119_EQ_LINK | RT9119_DRC_EQ_LINK;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_EQ_CTRL, handle->Reg->eqCtrl, RT9119_REG_EQ_CTRL_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }

        //BQs BOOST
        u4RegValue = 0x0;
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->eqBoostL, RT9119_REG_PEQ_L_GAIN_SIZE);
        //memcpy(handle->Reg->eqBoostL, &coeff, RT9119_REG_PEQ_L_GAIN_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_L_BQ_BOOST, handle->Reg->eqBoostL, RT9119_REG_PEQ_L_GAIN_SIZE);
        if(!u2WriteNum) {
            break;
        }
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->eqBoostR, RT9119_REG_PEQ_R_GAIN_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_R_BQ_BOOST, handle->Reg->eqBoostR, RT9119_REG_PEQ_R_GAIN_SIZE);
        if(!u2WriteNum) {
            break;
        }

        //Smooth_BQ_Alpha
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->sbqAlphaCoeff, RT9119_REG_SBQ_ALPHA_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SBQ_ALPHA, handle->Reg->sbqAlphaCoeff, RT9119_REG_SBQ_ALPHA_SIZE);
        if(!u2WriteNum) {
            break;
        }

        //Smooth_BQ_Ctrl
        u4RegValue = RT9119_SBQ_UPDATE_DELAY_1024 | RT9119_SBQ_CTRL_LINEAR_GAIN | RT9119_SBQ_DONE_BIT | RT9119_SBQ_NO_UPDATE;
        RT9119_le32toDataBuf(u4RegValue, handle->Reg->sbqBqctrl, RT9119_REG_SBQ_CTRL_SIZE);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SBQ_CTRL   , handle->Reg->sbqBqctrl, RT9119_REG_SBQ_CTRL_SIZE);
        if(!u2WriteNum) {
            break;
        }

        // BQ
        // may not necessary, just initialize backup dram is enough
        {
            u4RegValue = 0x00800000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b0, sizeof(coeff.b0));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b1, sizeof(coeff.b1));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b2, sizeof(coeff.b2));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.a1, sizeof(coeff.a1));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.a2, sizeof(coeff.a2));
            //1
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_01, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq01, &coeff, RT9119_REG_BQx_SIZE);
            //2
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_02, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq02, &coeff, RT9119_REG_BQx_SIZE);
            //3
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_03, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq03, &coeff, RT9119_REG_BQx_SIZE);
            //4
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_04, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq04, &coeff, RT9119_REG_BQx_SIZE);
            //5
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_05, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq05, &coeff, RT9119_REG_BQx_SIZE);
            //6
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_06, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq06, &coeff, RT9119_REG_BQx_SIZE);
            //7
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_07, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq07, &coeff, RT9119_REG_BQx_SIZE);
            //8
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_08, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq08, &coeff, RT9119_REG_BQx_SIZE);
            //9
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_09, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq09, &coeff, RT9119_REG_BQx_SIZE);
            //10
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_10, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq10, &coeff, RT9119_REG_BQx_SIZE);
            //11
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_11, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq11, &coeff, RT9119_REG_BQx_SIZE);
            //12
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_BQ_12, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1Bq12, &coeff, RT9119_REG_BQx_SIZE);
            //13
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_13, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq13, &coeff, RT9119_REG_BQx_SIZE);
            //14
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_14, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq14, &coeff, RT9119_REG_BQx_SIZE);
            //15
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_15, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq15, &coeff, RT9119_REG_BQx_SIZE);
            //16
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_16, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq16, &coeff, RT9119_REG_BQx_SIZE);
            //17
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_17, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq17, &coeff, RT9119_REG_BQx_SIZE);
            //18
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_18, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBq18, &coeff, RT9119_REG_BQx_SIZE);
            //BK1
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_BK_1, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBqBk1, &coeff, RT9119_REG_BQx_SIZE);
            //BK2
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_SBQ_BK_2, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1SBqBk2, &coeff, RT9119_REG_BQx_SIZE);
        }

        // DRC
        {
            u4RegValue = 0x00800000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b0, sizeof(coeff.b0));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b1, sizeof(coeff.b1));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.b2, sizeof(coeff.b2));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.a1, sizeof(coeff.a1));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, coeff.a2, sizeof(coeff.a2));
            //DRCLbq1
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_CH1_BQ_1, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->drc1Ch1Bq1, &coeff, RT9119_REG_BQx_SIZE);
            //DRCLbq2
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_CH1_BQ_2, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->drc1Ch1Bq2, &coeff, RT9119_REG_BQx_SIZE);
            //DRCMbq1
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_CH1_BQ_1, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->drc2Ch1Bq1, &coeff, RT9119_REG_BQx_SIZE);
            //DRCMbq2
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_CH1_BQ_2, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->drc2Ch1Bq2, &coeff, RT9119_REG_BQx_SIZE);
            //DRCHbq1
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_CH1_BQ_1, (UINT8*)&coeff, RT9119_REG_BQx_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->drc3Ch1Bq1, &coeff, RT9119_REG_BQx_SIZE);
            //DRC Parameters
            {
                RT9119_RmsAe rmsAE;
                RT9119_GainAa gainAA;
                RT9119_GainAd gainAD;
                RT9119_DrcMix drcMix;

                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, rmsAE.ae, sizeof(rmsAE.ae));
                u4RegValue = 0x00000000;
                RT9119_le32toDataBuf(u4RegValue, rmsAE.o_ae, sizeof(rmsAE.o_ae));
                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, gainAA.aa, sizeof(gainAA.aa));
                u4RegValue = 0x00000000;
                RT9119_le32toDataBuf(u4RegValue, gainAA.o_aa, sizeof(gainAA.o_aa));
                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, gainAD.ad, sizeof(gainAD.ad));
                u4RegValue = 0x00000000;
                RT9119_le32toDataBuf(u4RegValue, gainAD.o_ad, sizeof(gainAD.o_ad));

                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc1RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc1GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc1GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc2RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc2GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc2GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc3RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc3GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc3GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc4RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc4GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drc4GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
                u4RegValue = 0xFDA21490;    // T
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc1T, RT9119_REG_DRCx_T_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc2T, RT9119_REG_DRCx_T_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc3T, RT9119_REG_DRCx_T_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc4T, RT9119_REG_DRCx_T_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_T, handle->Reg->drc1T, RT9119_REG_DRCx_T_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                u4RegValue = 0x03842109;    // K
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc1K, RT9119_REG_DRCx_K_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc2K, RT9119_REG_DRCx_K_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc3K, RT9119_REG_DRCx_K_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc4K, RT9119_REG_DRCx_K_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_K, handle->Reg->drc1K, RT9119_REG_DRCx_K_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                u4RegValue = 0x00084210;    // O
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc1O, RT9119_REG_DRCx_O_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc2O, RT9119_REG_DRCx_O_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc3O, RT9119_REG_DRCx_O_SIZE);
                RT9119_le32toDataBuf(u4RegValue, handle->Reg->drc4O, RT9119_REG_DRCx_O_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_O, handle->Reg->drc1O, RT9119_REG_DRCx_O_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // T
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_T, handle->Reg->drc2T, RT9119_REG_DRCx_T_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // K
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_K, handle->Reg->drc2K, RT9119_REG_DRCx_K_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // O
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_O, handle->Reg->drc2O, RT9119_REG_DRCx_O_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // T
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_T, handle->Reg->drc3T, RT9119_REG_DRCx_T_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // K
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_K, handle->Reg->drc3K, RT9119_REG_DRCx_K_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // O
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_O, handle->Reg->drc3O, RT9119_REG_DRCx_O_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // T
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_T, handle->Reg->drc4T, RT9119_REG_DRCx_T_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // K
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_K, handle->Reg->drc4K, RT9119_REG_DRCx_K_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // O
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_O, handle->Reg->drc4O, RT9119_REG_DRCx_O_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                // DRC4Delay
                handle->Reg->drc4Delay[0] = 0xFF;
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_DELAY, handle->Reg->drc4Delay, RT9119_REG_DRC4_DELAY_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, drcMix.low, sizeof(drcMix.low));
                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, drcMix.mid, sizeof(drcMix.mid));
                u4RegValue = 0x00800000;
                RT9119_le32toDataBuf(u4RegValue, drcMix.hi, sizeof(drcMix.hi));
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_MIX_LEFT, (UINT8*)&drcMix, RT9119_REG_DRC_MIX_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drcMixLeft, &drcMix, RT9119_REG_DRC_MIX_SIZE);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_MIX_RIGHT, (UINT8*)&drcMix, RT9119_REG_DRC_MIX_SIZE);
                if(!u2WriteNum) {
                    break;
                }
                memcpy(handle->Reg->drcMixRight, &drcMix, RT9119_REG_DRC_MIX_SIZE);
            }
        }

        // Scaler
        {
            // Pre Scaler
            u4RegValue = 0x00020000;//0dB
            RT9119_le32toDataBuf(u4RegValue, handle->Reg->preScale, RT9119_REG_PRE_SCALE_SIZE);
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_PRE_SCALE, handle->Reg->preScale, RT9119_REG_PRE_SCALE_SIZE);
            if(!u2WriteNum) {
                break;
            }
            // Post Scaler
            u4RegValue = 0x00800000;//0dB
            RT9119_le32toDataBuf(u4RegValue, handle->Reg->postScale, RT9119_REG_POST_SCALE_SIZE);
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_POST_SCALE, handle->Reg->postScale, RT9119_REG_POST_SCALE_SIZE);
            if(!u2WriteNum) {
                break;
            }
        }
        //Prohibited Registers
        {
            u4RegValue = RT9119_VR_ANA_5_7V;
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_PWR_SEL, (UINT8*)&u4RegValue, RT9119_REG_PWR_SEL_SIZE);
            if(!u2WriteNum) {
                break;
            }
            u4RegValue = RT9119_VCM_0_5;
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_ANA_MODULTR2, (UINT8*)&u4RegValue, RT9119_REG_ANA_MODULTR2_SIZE);
            if(!u2WriteNum) {
                break;
            }
        }
        // Control: Shutdown OFF
        handle->Reg->sys_ctl[0] = (handle->Reg->sys_ctl[0] &~ RT9119_REG_MASK_SHUDOWN) | RT9119_SHUDOWN_OFF;
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SYS_CTL, handle->Reg->sys_ctl, RT9119_REG_SYS_CTL_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        ret = RT9119_E_OK;
    } while(0);
    return ret;
}

RT9119_Error RT9119_Init_IO_Mixer(RT9119_HANDLE* handle)
{
    RT9119_Error ret = RT9119_E_ACCESS;
    UINT16  u2WriteNum = 0;
    UINT32  u4RegValue;

    do {
        // Mixer
        {
            RT9119_ChMix chL;
            RT9119_ChMix chR;

            u4RegValue = 0x00800000;
            RT9119_le32toDataBuf(u4RegValue, chL.mix_1, sizeof(chL.mix_1));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, chL.mix_0, sizeof(chL.mix_0));
            u4RegValue = 0x00000000;
            RT9119_le32toDataBuf(u4RegValue, chR.mix_1, sizeof(chR.mix_1));
            u4RegValue = 0x00800000;
            RT9119_le32toDataBuf(u4RegValue, chR.mix_0, sizeof(chR.mix_0));

            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_OUT_MIX, (UINT8*)&chL, RT9119_REG_CHx_MIX_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1OutMix, &chL, RT9119_REG_CHx_MIX_SIZE);

            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH2_OUT_MIX, (UINT8*)&chR, RT9119_REG_CHx_MIX_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch2OutMix, &chR, RT9119_REG_CHx_MIX_SIZE);

            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_IN_MIX, (UINT8*)&chL, RT9119_REG_CHx_MIX_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch1InMix, &chL, RT9119_REG_CHx_MIX_SIZE);
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH2_IN_MIX, (UINT8*)&chR, RT9119_REG_CHx_MIX_SIZE);
            if(!u2WriteNum) {
                break;
            }
            memcpy(handle->Reg->ch2InMix, &chR, RT9119_REG_CHx_MIX_SIZE);
        }
        ret = RT9119_E_OK;
    } while(0);
    return ret;
}

/** RT9119_SetVolume
 *  Set Volume
 *  @param  handle
 *  @param  i4Volume : Volume Value(0.1dB/step)
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetVolume(RT9119_HANDLE* handle, int i4Volume)
{
    int i4MasterVolume;                 // For Calculation
    int i;
    unsigned char u1Command[RT9119_REG_MS_VOL_SIZE];
    UINT16 u2WriteNum;

    LOG(2,"SONY debug RT9119_SetVolume %d\n", i4Volume);
    i4MasterVolume = RT9119_db_to_volume(i4Volume);

    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(i4MasterVolume, u1Command, RT9119_REG_MS_VOL_SIZE);
    if( memcmp(handle->Reg->masterVolume, u1Command, RT9119_REG_MS_VOL_SIZE ) != 0 ) {
        LOG(2,"SONY debug:: set to AMP - i4MasterVolume = 0x%x\n", i4MasterVolume);
        // Volume update
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_MS_VOL, u1Command, RT9119_REG_MS_VOL_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        // Save value to DRAM
        memcpy(handle->Reg->masterVolume, u1Command, RT9119_REG_MS_VOL_SIZE);
    }
    return RT9119_E_OK;
}

/** RT9119_SetClipper
 *  Set Clipper
 *  @param  handle
 *  @param  u4ClipLevel : (0.1dB/step, 0dB ~ -22.5dB, 0 : 0dB, 225 : 22.5dB)
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetClipper(RT9119_HANDLE* handle, unsigned int u4ClipLevel)
{
    int i4Clip;
    UINT32 u4RegValue;
    unsigned char u1Command[RT9119_REG_HARD_CLIP_SIZE];
    UINT16 u2WriteNum;

    i4Clip = RT9119_db_to_volume(u4ClipLevel);
    RT9119_dataBufToLe32(handle->Reg->hardClip, &u4RegValue, RT9119_REG_HARD_CLIP_SIZE);
    u4RegValue &= ~RT9119_REG_MASK_HARD_CLIP_TH;
    u4RegValue |= (i4Clip << RT9119_REG_SHIFT_HARD_CLIP_TH);
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(u4RegValue, u1Command, RT9119_REG_HARD_CLIP_SIZE);
    if( memcmp(handle->Reg->hardClip, u1Command, RT9119_REG_HARD_CLIP_SIZE ) != 0 ) {
        // Clipper update
        LOG(2,"SONY debug:: set to AMP - RT9119_SetClipper = 0x%x\n", u4RegValue);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_HARD_CLIP, u1Command, RT9119_REG_HARD_CLIP_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        // Save value to DRAM
        memcpy(handle->Reg->hardClip, u1Command, RT9119_REG_HARD_CLIP_SIZE);
    }
    return RT9119_E_OK;
}


/** RT9119_SetPreScaler
 *  Set Pre Scaler
 *  @param  handle
 *  @param  i4Level : 0.1dB/step
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetPreScaler(RT9119_HANDLE* handle, int i4Level)
{
    unsigned int u4RegValue;
    unsigned char u1Command[RT9119_REG_PRE_SCALE_SIZE];
    UINT16 u2WriteNum;

    LOG(2,"SONY debug:: set to AMP - RT9119_SetPreScaler:  i4Level = %d \n", i4Level);
    if(i4Level < (-48 * 10)) {  // less than -48dB
        i4Level = -48 * 10;
    }
    else if((48 * 10) < i4Level) {  // more than +48dB
        i4Level = 48 * 10;
    }
    u4RegValue = db0p1ToLenear20000[480+i4Level];
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(u4RegValue, u1Command, RT9119_REG_PRE_SCALE_SIZE);
    if( memcmp(handle->Reg->preScale, u1Command, RT9119_REG_PRE_SCALE_SIZE ) != 0 ) {
        // Pre Scaler update
        LOG(2,"SONY debug:: set to AMP - RT9119_SetPreScaler = 0x%x\n", u4RegValue);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_PRE_SCALE, u1Command, RT9119_REG_PRE_SCALE_SIZE);
        if(u2WriteNum == 0) {
            LOG(0,"SONY debug:: SetPrescaler is failed\n");
            return RT9119_E_ACCESS;
        }
        // Save value to DRAM
        memcpy(handle->Reg->preScale, u1Command, RT9119_REG_PRE_SCALE_SIZE);
    }
    return RT9119_E_OK;
}

/** RT9119_SetBQ
 *  Set BQ coeff
 *  @param  handle
 *  @param  bqId : ID(0 ~ 11) + DRC BQ(12 ~ 15, 17, 18)
 *  @param  b0
 *  @param  b1
 *  @param  b2
 *  @param  a1
 *  @param  a2
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetBQ(RT9119_HANDLE* handle, unsigned int bqId, RT9119_Fix32Q29 b0, RT9119_Fix32Q29 b1, RT9119_Fix32Q29 b2, RT9119_Fix32Q29 a1, RT9119_Fix32Q29 a2)
{
    RT9119_BqCoeff bqCoeff;
    UINT16 u2WriteNum;
    unsigned char* bqRegPos;

    const unsigned char bqIdRegConv[RT9119_BQID_NUM] =
    {
        { RT9119_REG_CH1_BQ_01},            // 1RT9119_BQID_1(L/R dependent)
        { RT9119_REG_CH1_BQ_02},            // 2RT9119_BQID_2(L/R dependent)
        { RT9119_REG_CH1_BQ_03},            // 3RT9119_BQID_3(L/R dependent)
        { RT9119_REG_CH1_BQ_04},            // 4RT9119_BQID_4(L/R dependent)
        { RT9119_REG_CH1_BQ_05},            // 5RT9119_BQID_5(L/R dependent)
        { RT9119_REG_CH1_BQ_06},            // 6RT9119_BQID_6(L/R dependent)
        { RT9119_REG_CH1_BQ_07},            // 7RT9119_BQID_7(L/R dependent)
        { RT9119_REG_CH1_BQ_08},            // 8RT9119_BQID_8(L/R dependent)
        { RT9119_REG_CH1_BQ_09},            // 9RT9119_BQID_9(L/R dependent)
        { RT9119_REG_CH1_BQ_10},            // 10RT9119_BQID_10(L/R dependent)
        { RT9119_REG_CH1_BQ_11},            // 11RT9119_BQID_11(L/R dependent)
        { RT9119_REG_CH1_BQ_12},            // 12RT9119_BQID_12(L/R dependent)
        { RT9119_REG_CH1_SBQ_13},           // 13RT9119_BQID_13(L/R dependent)
        { RT9119_REG_CH1_SBQ_14},           // 14RT9119_BQID_14(L/R dependent)
        { RT9119_REG_CH1_SBQ_15},           // 15RT9119_BQID_15(L/R dependent)
        { RT9119_REG_CH1_SBQ_16},           // 16RT9119_BQID_16(L/R dependent)
        { RT9119_REG_CH1_SBQ_17},           // 17RT9119_BQID_17(L/R dependent)
        { RT9119_REG_CH1_SBQ_18},           // 18RT9119_BQID_18(L/R dependent)
        { RT9119_REG_DRC1_CH1_BQ_1},        // 19RT9119_BQID_DRC1_1
        { RT9119_REG_DRC1_CH1_BQ_2},        // 20RT9119_BQID_DRC1_2
        { RT9119_REG_DRC2_CH1_BQ_1},        // 21RT9119_BQID_DRC2_1
        { RT9119_REG_DRC2_CH1_BQ_2},        // 22RT9119_BQID_DRC2_2
        { RT9119_REG_DRC3_CH1_BQ_1}         // 23RT9119_BQID_DRC3_1
    };

    const unsigned int bqRegInfoOffset[RT9119_BQID_NUM] =
    {
        offsetof(RT9119Reg, ch1Bq01),       // RT9119_BQID_1
        offsetof(RT9119Reg, ch1Bq02),       // RT9119_BQID_2
        offsetof(RT9119Reg, ch1Bq03),       // RT9119_BQID_3
        offsetof(RT9119Reg, ch1Bq04),       // RT9119_BQID_4
        offsetof(RT9119Reg, ch1Bq05),       // RT9119_BQID_5
        offsetof(RT9119Reg, ch1Bq06),       // RT9119_BQID_6
        offsetof(RT9119Reg, ch1Bq07),       // RT9119_BQID_7
        offsetof(RT9119Reg, ch1Bq08),       // RT9119_BQID_8
        offsetof(RT9119Reg, ch1Bq09),       // RT9119_BQID_9
        offsetof(RT9119Reg, ch1Bq10),       // RT9119_BQID_10
        offsetof(RT9119Reg, ch1Bq11),       // RT9119_BQID_11
        offsetof(RT9119Reg, ch1Bq12),       // RT9119_BQID_12
        offsetof(RT9119Reg, ch1SBq13),      // RT9119_BQID_13
        offsetof(RT9119Reg, ch1SBq14),      // RT9119_BQID_14
        offsetof(RT9119Reg, ch1SBq15),      // RT9119_BQID_15
        offsetof(RT9119Reg, ch1SBq16),      // RT9119_BQID_16
        offsetof(RT9119Reg, ch1SBq17),      // RT9119_BQID_17
        offsetof(RT9119Reg, ch1SBq18),      // RT9119_BQID_18
        offsetof(RT9119Reg, drc1Ch1Bq1),    // RT9119_BQID_DRC1_1
        offsetof(RT9119Reg, drc1Ch1Bq2),    // RT9119_BQID_DRC1_2
        offsetof(RT9119Reg, drc2Ch1Bq1),    // RT9119_BQID_DRC2_1
        offsetof(RT9119Reg, drc2Ch1Bq2),    // RT9119_BQID_DRC2_2
        offsetof(RT9119Reg, drc3Ch1Bq1)     // RT9119_BQID_DRC3_1
    };

    if(RT9119_BQID_NUM <= bqId) {
        return RT9119_E_OK;
    }
    // b0
    // Accuracy improvement and shift to 3.23 format
    b0 = (b0 + 0x20) >> 6;
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(b0, bqCoeff.b0, sizeof(bqCoeff.b0));
    // b1
    // Accuracy improvement and shift to 3.23 format
    b1 = (b1 + 0x20) >> 6;
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(b1, bqCoeff.b1, sizeof(bqCoeff.b1));
    // b2
    // Accuracy improvement and shift to 3.23 format
    b2 = (b2 + 0x20) >> 6;
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(b2, bqCoeff.b2, sizeof(bqCoeff.b2));
    // a1
    // Accuracy improvement and shift to 3.23 format
    a1 = (a1 + 0x20) >> 6;
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(a1, bqCoeff.a1, sizeof(bqCoeff.a1));
    // a2
    // Accuracy improvement and shift to 3.23 format
    a2 = (a2 + 0x20) >> 6;
    // set to command buffer with endian conversion
    RT9119_le32toDataBuf(a2, bqCoeff.a2, sizeof(bqCoeff.a2));

    bqRegPos = (unsigned char*)handle->Reg;
    bqRegPos += bqRegInfoOffset[bqId];

    if( memcmp(bqRegPos, &bqCoeff, RT9119_REG_BQx_SIZE ) != 0 ) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, bqIdRegConv[bqId], (UINT8*)&bqCoeff, RT9119_REG_BQx_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }

        // Save value to DRAM
        memcpy(bqRegPos, &bqCoeff, RT9119_REG_BQx_SIZE);
    }
    return RT9119_E_OK;
}

/** RT9119_SetDRC
 *  Set DRC parameters
 *  @param  handle
 *  @param  drcInfo : pointer to DRC setting Information
 *  @retval OK/NG
 */

RT9119_Error RT9119_SetDRC(RT9119_HANDLE* handle, RT9119_DrcInfo * drcInfo)
{
    UINT16          u2WriteNum;
    unsigned char   u1Command[20];
    UINT8           eqDrcEnReg; //drcCtrl1
    UINT8           drcEnableReg; //drcCtrl2
    RT9119_RmsAe    rmsAE;
    RT9119_GainAa   gainAA;
    RT9119_GainAd   gainAD;
    RT9119_Error    err;
    UINT32          drcParam;
    UINT32          *drcParamOffset;
    RT9119_DrcMix   drcMix;
    UINT32          u4RegValue;

    /*
    drcCtrl1
     */
    eqDrcEnReg = handle->Reg->drcCtrl1[0];
    eqDrcEnReg &= ~(RT9119_REG_MASK_DRC3_ENABLE | RT9119_REG_MASK_DRC2_ENABLE | RT9119_REG_MASK_DRC1_ENABLE |RT9119_REG_MASK_DRC4_ENABLE);
    if(drcInfo->drc_GainEnable){
        eqDrcEnReg |= (RT9119_DRC3_ENABLE | RT9119_DRC2_ENABLE | RT9119_DRC1_ENABLE);
    }
    // Disable 3Bands DRC
    else{
        eqDrcEnReg |= RT9119_DRC1_DISABLE|RT9119_DRC2_DISABLE|RT9119_DRC3_DISABLE;
    }
    if(drcInfo->drc4Enable) {
        eqDrcEnReg |= RT9119_DRC4_ENABLE;
    }
    else {
        eqDrcEnReg |= RT9119_DRC4_DISABLE;
    }
    if( eqDrcEnReg != handle->Reg->drcCtrl1[0] ) {
        // EQ/DRC control register update
        //LOG(0, "RT9119_SetDRC reg (0x46): u1Command[0]=0x%02x u1Command[1]=0x%02x u1Command[2]=0x%02x u1Command[3]=0x%02x\n", u1Command[0], u1Command[1], u1Command[2], u1Command[3]);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_CTRL1, &eqDrcEnReg, RT9119_REG_DRC_CTRL1_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        // Save value to DRAM
        handle->Reg->drcCtrl1[0] = eqDrcEnReg;
        //memcpy(handle->Reg->drcCtrl1, &eqDrcEnReg, RT9119_REG_EQ_DRC_EN_SIZE);
    }

    /*
    drcCtrl2
     */
    // DRC bypass setting
    drcEnableReg = handle->Reg->drcCtrl2[0];
    drcEnableReg &= ~(RT9119_REG_MASK_DRC3_BYPASS | RT9119_REG_MASK_DRC2_BYPASS | RT9119_REG_MASK_DRC1_BYPASS);
    switch(drcInfo->multiDrcMode) {
    case RT9119_MULTI_DRC_MODE_1BAND:
        drcEnableReg |= (RT9119_REG_DRC3_BYPASS_ENABLE | RT9119_REG_DRC2_BYPASS_ENABLE | RT9119_REG_DRC1_BYPASS_DISABLE);
        break;
    case RT9119_MULTI_DRC_MODE_2BAND:
        drcEnableReg |= (RT9119_REG_DRC3_BYPASS_DISABLE | RT9119_REG_DRC2_BYPASS_ENABLE | RT9119_REG_DRC1_BYPASS_DISABLE);
        break;
    case RT9119_MULTI_DRC_MODE_3BAND:
        drcEnableReg |= (RT9119_REG_DRC3_BYPASS_DISABLE | RT9119_REG_DRC2_BYPASS_DISABLE | RT9119_REG_DRC1_BYPASS_DISABLE);
        break;
    case RT9119_MULTI_DRC_MODE_DISABLE:
    default:
        drcEnableReg |= (RT9119_REG_DRC3_BYPASS_ENABLE | RT9119_REG_DRC2_BYPASS_ENABLE | RT9119_REG_DRC1_BYPASS_DISABLE);
        break;
    }

    // Diff check
    if( drcEnableReg != handle->Reg->drcCtrl2[0] ) {
        // DRC control register update
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_CTRL2, &drcEnableReg, RT9119_REG_DRC_CTRL2_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        // Save value to DRAM
        handle->Reg->drcCtrl2[0] = drcEnableReg;
        //memcpy(handle->Reg->drcCtrl1, &drcEnableReg, RT9119_REG_DRC_ENABLE_SIZE);
    }

    //
    // DRC1
    //

    // Energy Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc1EnergyAttackTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.ae, sizeof(rmsAE.ae));
    // SONY add Start
    drcParam = s0p1ToDrc_1_AeAaAd[drcInfo->drc1EnergyReleaseTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.o_ae, sizeof(rmsAE.o_ae));
    // SONY add End
    if(memcmp(&rmsAE, handle->Reg->drc1RmsAe, RT9119_REG_DRCx_RMS_AE_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
    }

    // Attack Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc1AttackTime];
    RT9119_le32toDataBuf(drcParam, gainAA.aa, sizeof(gainAA.aa));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAA.o_aa, sizeof(gainAA.o_aa));
    if(memcmp(&gainAA, handle->Reg->drc1GainAa, RT9119_REG_DRCx_GAIN_AA_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
    }

    // Decay Time
    drcParam = s0p1ToDrc_Ad[drcInfo->drc1DecayTime];
    RT9119_le32toDataBuf(drcParam, gainAD.ad, sizeof(gainAD.ad));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAD.o_ad, sizeof(gainAD.o_ad));
    if(memcmp(&gainAD, handle->Reg->drc1GainAd, RT9119_REG_DRCx_GAIN_AD_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
    }

    // Threshold
    if(drcInfo->drc1T < RT9119_DRC_MIN_THRESHOLD) {     // under -120.0dB
        drcInfo->drc1T = RT9119_DRC_MIN_THRESHOLD;          // Clip
    }
    else if(RT9119_DRC_MAX_THRESHOLD < drcInfo->drc1T) {        // over 24.0dB
        drcInfo->drc1T = RT9119_DRC_MAX_THRESHOLD;          // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_T[1200];    // set pointer to center
    drcParam = drcParamOffset[drcInfo->drc1T];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_T_SIZE);
    if(memcmp(u1Command, handle->Reg->drc1T, RT9119_REG_DRCx_T_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_T, u1Command, RT9119_REG_DRCx_T_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1T, u1Command, RT9119_REG_DRCx_T_SIZE);
    }

    // Compress ratio
    if(drcInfo->drc1K < 0) {                // under 0%
        drcInfo->drc1K = 0;                 // Clip
    }
    else if(100 < drcInfo->drc1K) {         // over 100%
        drcInfo->drc1K = 100;               // Clip
    }

    drcParam = 0x03800000 + (0x147AE * drcInfo->drc1K);

    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_K_SIZE);
    if(memcmp(u1Command, handle->Reg->drc1K, RT9119_REG_DRCx_K_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_K, u1Command, RT9119_REG_DRCx_K_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1K, u1Command, RT9119_REG_DRCx_K_SIZE);
    }

    // Make up gain
    if(drcInfo->drc1O < -120) {         // under -12.8dB
        drcInfo->drc1O = -120;          // Clip
    }
    else if(120 < drcInfo->drc1O) {     // over 12.8dB
        drcInfo->drc1O = 120;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_O[120];// set pointer to center
    drcParam = drcParamOffset[drcInfo->drc1O];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_O_SIZE);
    if(memcmp(u1Command, handle->Reg->drc1O, RT9119_REG_DRCx_O_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC1_O, u1Command, RT9119_REG_DRCx_O_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc1O, u1Command, RT9119_REG_DRCx_O_SIZE);
    }

    // BQ
    err = RT9119_SetBQ(handle, RT9119_BQID_DRC1_1, drcInfo->drc1Bq1.b0, drcInfo->drc1Bq1.b1, drcInfo->drc1Bq1.b2, drcInfo->drc1Bq1.a1, drcInfo->drc1Bq1.a2);
    if(err != RT9119_E_OK){
        return err;
    }
//    LOG(0, "%s reg BQ(0x5D/0x5E): b0 = 0x%08x b1 = 0x%08x b2 = 0x%08x a1 = 0x%08x a2 = 0x%08x\n", __func__, drcInfo->drc1Bq2_b0, drcInfo->drc1Bq2_b1, drcInfo->drc1Bq2_b2, drcInfo->drc1Bq2_a1, drcInfo->drc1Bq2_a2);
    err = RT9119_SetBQ(handle, RT9119_BQID_DRC1_2, drcInfo->drc1Bq2.b0, drcInfo->drc1Bq2.b1, drcInfo->drc1Bq2.b2, drcInfo->drc1Bq2.a1, drcInfo->drc1Bq2.a2);
    if(err != RT9119_E_OK){
        return err;
    }

    //
    // DRC2
    //

    // Energy Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc2EnergyAttackTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.ae, sizeof(rmsAE.ae));
    // SONY add start
    drcParam = s0p1ToDrc_1_AeAaAd[drcInfo->drc2EnergyReleaseTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.o_ae, sizeof(rmsAE.o_ae));
    // SONY add end
    if(memcmp(&rmsAE, handle->Reg->drc2RmsAe, RT9119_REG_DRCx_RMS_AE_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
    }
    // Attack Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc2AttackTime];
    RT9119_le32toDataBuf(drcParam, gainAA.aa, sizeof(gainAA.aa));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAA.o_aa, sizeof(gainAA.o_aa));
    if(memcmp(&gainAA, handle->Reg->drc2GainAa, RT9119_REG_DRCx_GAIN_AA_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
    }
    // Decay Time
    drcParam = s0p1ToDrc_Ad[drcInfo->drc2DecayTime];
    RT9119_le32toDataBuf(drcParam, gainAD.ad, sizeof(gainAD.ad));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAD.o_ad, sizeof(gainAD.o_ad));
    if(memcmp(&gainAD, handle->Reg->drc2GainAd, RT9119_REG_DRCx_GAIN_AD_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
    }
    // Threshold
    if(drcInfo->drc2T < -1200) {        // under -100.0dB
        drcInfo->drc2T = -1200;         // Clip
    }
    else if(240 < drcInfo->drc2T) {     // over 20.0dB
        drcInfo->drc2T = 240;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_T[1200];    // set pointer to center
    drcParam = drcParamOffset[drcInfo->drc2T];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_T_SIZE);
    if(memcmp(u1Command, handle->Reg->drc2T, RT9119_REG_DRCx_T_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_T, u1Command, RT9119_REG_DRCx_T_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2T, u1Command, RT9119_REG_DRCx_T_SIZE);
    }
    // Compress ratio
    if(drcInfo->drc2K < 0) {                // under 0%
        drcInfo->drc2K = 0;                 // Clip
    }
    else if(100 < drcInfo->drc2K) {         // over 100%
        drcInfo->drc2K = 100;               // Clip
    }

    drcParam = 0x03800000 + (0x147AE * drcInfo->drc2K);

    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_K_SIZE);
    if(memcmp(u1Command, handle->Reg->drc2K, RT9119_REG_DRCx_K_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_K, u1Command, RT9119_REG_DRCx_K_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2K, u1Command, RT9119_REG_DRCx_K_SIZE);
    }
    // Make up gain
    if(drcInfo->drc2O < -120) {         // under -12.8dB
        drcInfo->drc2O = -120;          // Clip
    }
    else if(120 < drcInfo->drc2O) {     // over 12.8dB
        drcInfo->drc2O = 120;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_O[120];// set pointer to center
    drcParam = drcParamOffset[drcInfo->drc2O];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_O_SIZE);
    if(memcmp(u1Command, handle->Reg->drc2O, RT9119_REG_DRCx_O_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC2_O, u1Command, RT9119_REG_DRCx_O_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc2O, u1Command, RT9119_REG_DRCx_O_SIZE);
    }
    // BQ
    err = RT9119_SetBQ(handle, RT9119_BQID_DRC2_1, drcInfo->drc2Bq1.b0, drcInfo->drc2Bq1.b1, drcInfo->drc2Bq1.b2, drcInfo->drc2Bq1.a1, drcInfo->drc2Bq1.a2);
    if(err != RT9119_E_OK){
        return err;
    }
    err = RT9119_SetBQ(handle, RT9119_BQID_DRC2_2, drcInfo->drc2Bq2.b0, drcInfo->drc2Bq2.b1, drcInfo->drc2Bq2.b2, drcInfo->drc2Bq2.a1, drcInfo->drc2Bq2.a2);
    if(err != RT9119_E_OK){
        return err;
    }

    //
    // DRC3
    //

    // Energy Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc3EnergyAttackTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.ae, sizeof(rmsAE.ae));
    // SONY add start
    drcParam = s0p1ToDrc_1_AeAaAd[drcInfo->drc3EnergyReleaseTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.o_ae, sizeof(rmsAE.o_ae));
    // SONY add end
    if(memcmp(&rmsAE, handle->Reg->drc3RmsAe, RT9119_REG_DRCx_RMS_AE_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
    }
    // Attack Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc3AttackTime];
    RT9119_le32toDataBuf(drcParam, gainAA.aa, sizeof(gainAA.aa));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAA.o_aa, sizeof(gainAA.o_aa));
    if(memcmp(&gainAA, handle->Reg->drc3GainAa, RT9119_REG_DRCx_GAIN_AA_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
    }
    // Decay Time
    drcParam = s0p1ToDrc_Ad[drcInfo->drc3DecayTime];
    RT9119_le32toDataBuf(drcParam, gainAD.ad, sizeof(gainAD.ad));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAD.o_ad, sizeof(gainAD.o_ad));
    if(memcmp(&gainAD, handle->Reg->drc3GainAd, RT9119_REG_DRCx_GAIN_AD_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
    }
    // Threshold
    if(drcInfo->drc3T < -1200) {        // under -100.0dB
        drcInfo->drc3T = -1200;         // Clip
    }
    else if(240 < drcInfo->drc3T) {     // over 20.0dB
        drcInfo->drc3T = 240;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_T[1200];    // set pointer to center
    drcParam = drcParamOffset[drcInfo->drc3T];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_T_SIZE);
    if(memcmp(u1Command, handle->Reg->drc3T, RT9119_REG_DRCx_T_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_T, u1Command, RT9119_REG_DRCx_T_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3T, u1Command, RT9119_REG_DRCx_T_SIZE);
    }
    // Compress ratio
    if(drcInfo->drc3K < 0) {                // under 0%
        drcInfo->drc3K = 0;                 // Clip
    }
    else if(100 < drcInfo->drc3K) {         // over 100%
        drcInfo->drc3K = 100;               // Clip
    }

    drcParam = 0x03800000 + (0x147AE * drcInfo->drc3K);

    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_K_SIZE);
    if(memcmp(u1Command, handle->Reg->drc3K, RT9119_REG_DRCx_K_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_K, u1Command, RT9119_REG_DRCx_K_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3K, u1Command, RT9119_REG_DRCx_K_SIZE);
    }
    // Make up gain
    if(drcInfo->drc3O < -120) {         // under -12.8dB
        drcInfo->drc3O = -120;          // Clip
    }
    else if(120 < drcInfo->drc3O) {     // over 12.8dB
        drcInfo->drc3O = 120;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_O[120];// set pointer to center
    drcParam = drcParamOffset[drcInfo->drc3O];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_O_SIZE);
    if(memcmp(u1Command, handle->Reg->drc3O, RT9119_REG_DRCx_O_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC3_O, u1Command, RT9119_REG_DRCx_O_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc3O, u1Command, RT9119_REG_DRCx_O_SIZE);
    }
    // BQ
    err = RT9119_SetBQ(handle, RT9119_BQID_DRC3_1, drcInfo->drc3Bq1.b0, drcInfo->drc3Bq1.b1, drcInfo->drc3Bq1.b2, drcInfo->drc3Bq1.a1, drcInfo->drc3Bq1.a2);
    if(err != RT9119_E_OK){
        return err;
    }

    //
    // DRC4
    //
    // Energy Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc3EnergyAttackTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.ae, sizeof(rmsAE.ae));
    // SONY add start
    drcParam = s0p1ToDrc_1_AeAaAd[drcInfo->drc3EnergyReleaseTime];
    RT9119_le32toDataBuf(drcParam, rmsAE.o_ae, sizeof(rmsAE.o_ae));
    // SONY add end
    if(memcmp(&rmsAE, handle->Reg->drc4RmsAe, RT9119_REG_DRCx_RMS_AE_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_RMS_AE, (UINT8*)&rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4RmsAe, &rmsAE, RT9119_REG_DRCx_RMS_AE_SIZE);
    }
    // Attack Time
    drcParam = ms0p1ToDrc_AaAe[drcInfo->drc4AttackTime];
    RT9119_le32toDataBuf(drcParam, gainAA.aa, sizeof(gainAA.aa));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAA.o_aa, sizeof(gainAA.o_aa));
    if(memcmp(&gainAA, handle->Reg->drc4GainAa, RT9119_REG_DRCx_GAIN_AA_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_GAIN_AA, (UINT8*)&gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4GainAa, &gainAA, RT9119_REG_DRCx_GAIN_AA_SIZE);
    }
    // Decay Time
    drcParam = s0p1ToDrc_Ad[drcInfo->drc4DecayTime];
    RT9119_le32toDataBuf(drcParam, gainAD.ad, sizeof(gainAD.ad));
    RT9119_le32toDataBuf(0x00800000 - drcParam, gainAD.o_ad, sizeof(gainAD.o_ad));
    if(memcmp(&gainAD, handle->Reg->drc4GainAd, RT9119_REG_DRCx_GAIN_AD_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_GAIN_AD, (UINT8*)&gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4GainAd, &gainAD, RT9119_REG_DRCx_GAIN_AD_SIZE);
    }
    // Threshold
    if(drcInfo->drc4T < -1200) {        // under -100.0dB
        drcInfo->drc4T = -1200;         // Clip
    }
    else if(240 < drcInfo->drc4T) {     // over 20.0dB
        drcInfo->drc4T = 240;           // Clip
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_T[1200];    // set pointer to center
    drcParam = drcParamOffset[drcInfo->drc4T];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_T_SIZE);
    if(memcmp(u1Command, handle->Reg->drc4T, RT9119_REG_DRCx_T_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_T, u1Command, RT9119_REG_DRCx_T_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4T, u1Command, RT9119_REG_DRCx_T_SIZE);
    }
    // Compress ratio
    if(drcInfo->drc4K < 0) {                // under 0%
        drcInfo->drc4K = 0;                 // Clip
    }
    else if(100 < drcInfo->drc4K) {         // over 100%
        drcInfo->drc4K = 100;               // Clip
    }

    drcParam = 0x03800000 + (0x147AE * drcInfo->drc4K);

    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_K_SIZE);
    if(memcmp(u1Command, handle->Reg->drc4K, RT9119_REG_DRCx_K_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_K, u1Command, RT9119_REG_DRCx_K_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4K, u1Command, RT9119_REG_DRCx_K_SIZE);
    }
    // Make up gain
    if(drcInfo->drc4O < -120) {
        drcInfo->drc4O = -120;
    }
    else if(120 < drcInfo->drc4O) {
        drcInfo->drc4O = 120;
    }
    drcParamOffset = (unsigned int*)&db0p1ToDrc_O[120];// set pointer to center
    drcParam = drcParamOffset[drcInfo->drc4O];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRCx_O_SIZE);
    if(memcmp(u1Command, handle->Reg->drc4O, RT9119_REG_DRCx_O_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_O, u1Command, RT9119_REG_DRCx_O_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drc4O, u1Command, RT9119_REG_DRCx_O_SIZE);
    }
    // Delay
    u1Command[0] = ms0p1ToDrc_Delay[drcInfo->drc4Delay];
    if( u1Command[0] != handle->Reg->drc4Delay[0]) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC4_DELAY, u1Command, RT9119_REG_DRC4_DELAY_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        handle->Reg->drc4Delay[0] = u1Command[0];
    }
    //
    // Noise Gate
    //
    drcParamOffset = (unsigned int*)&db0p1ToDrc_T[1200];    // set pointer to center
    drcParam = drcParamOffset[drcInfo->noiseGateThreshold];
    RT9119_le32toDataBuf(drcParam, u1Command, RT9119_REG_DRC_NG_TH_SIZE);
    if(memcmp(u1Command, handle->Reg->drcNT, RT9119_REG_DRC_NG_TH_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_NG_TH, u1Command, RT9119_REG_DRC_NG_TH_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drcNT, u1Command, RT9119_REG_DRC_NG_TH_SIZE);
    }
    /*
    ** Mixer checking
    */
    if (drcInfo->inverseMidBand == RT9119_TRUE) {
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.low, sizeof(drcMix.low));
        u4RegValue = 0x03800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.mid, sizeof(drcMix.mid));
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.hi, sizeof(drcMix.hi));
    } else {
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.low, sizeof(drcMix.low));
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.mid, sizeof(drcMix.mid));
        u4RegValue = 0x00800000;
        RT9119_le32toDataBuf(u4RegValue, drcMix.hi, sizeof(drcMix.hi));
    }
    if(memcmp(&drcMix, handle->Reg->drcMixLeft, RT9119_REG_DRC_MIX_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_MIX_LEFT, (UINT8*)&drcMix, RT9119_REG_DRC_MIX_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drcMixLeft, &drcMix, RT9119_REG_DRC_MIX_SIZE);
    }
    if(memcmp(&drcMix, handle->Reg->drcMixRight, RT9119_REG_DRC_MIX_SIZE ) != 0) {
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_DRC_MIX_RIGHT, (UINT8*)&drcMix, RT9119_REG_DRC_MIX_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->drcMixRight, &drcMix, RT9119_REG_DRC_MIX_SIZE);
    }
    return RT9119_E_OK;
}

//////////////////////////////////////////////////////
//****************NEW DSP FUNCTIONS*******************
//////////////////////////////////////////////////////

/** RT9119_SetFIR
 *  Set FIR coeff
 *  @param  handle
 *  @param  FIR_First_Tap_Address: The first FIR tap address
 *  @param  FIR_Total_Tap_No: Supported Total FIR Taps
 *  @param  Enabled_Tap_No:  No of FIR tap to be set
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetFIR(RT9119_HANDLE* handle, UINT32 * FIR_First_Tap_Address, UINT32 Enabled_Tap_No)
{
    UINT16 u2WriteNum;
    UINT32 FIR_TAPX_ADDRESS = RT9119_REG_CH1_BQ_01;
    INT32 FIR_DATA_TEMP = 0;
    unsigned char i=0;
    unsigned char fir_buffer[128][4];

    if(Enabled_Tap_No>128){
        Enabled_Tap_No=128;
    }

    for(i=0;i<Enabled_Tap_No;i++,FIR_First_Tap_Address++){
        FIR_DATA_TEMP = (INT32)(*FIR_First_Tap_Address + 0x40) >> 7;
        RT9119_le32toDataBuf(FIR_DATA_TEMP, &fir_buffer[i][0], RT9119_FIR_COEFF_SIZE);
    }

    for(;i<128;i++){
        RT9119_le32toDataBuf(0, &fir_buffer[i][0], RT9119_FIR_COEFF_SIZE);
    }

    if(!Enabled_Tap_No){
        handle->Reg->fltrMisc[0] &= ~(RT9119_REG_MASK_FIR|RT9119_REG_MASK_PAGE_SEL);
        handle->Reg->fltrMisc[0] |= (RT9119_FIR_DISABLE|RT9119_PAGE_SEL_DEFAULT);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FLTR_MISC, handle->Reg->fltrMisc, RT9119_REG_FLTR_MISC_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->fir, fir_buffer, sizeof(fir_buffer));
    }
    else if(memcmp(fir_buffer,handle->Reg->fir,sizeof(fir_buffer))!=0){
        handle->Reg->fltrMisc[0] &= ~(RT9119_REG_MASK_FIR|RT9119_REG_MASK_PAGE_SEL);
        handle->Reg->fltrMisc[0] |= (RT9119_FIR_DISABLE|RT9119_PAGE_SEL_FIR);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FLTR_MISC, handle->Reg->fltrMisc, RT9119_REG_FLTR_MISC_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
        for(i=0;i<128;i++,FIR_TAPX_ADDRESS++){
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, FIR_TAPX_ADDRESS, &fir_buffer[i][0], RT9119_FIR_COEFF_SIZE);
            if(!u2WriteNum) {
                memcpy(handle->Reg->fir, fir_buffer, RT9119_FIR_COEFF_SIZE*i);
                handle->Reg->fltrMisc[0] &= ~(RT9119_REG_MASK_FIR|RT9119_REG_MASK_PAGE_SEL);
                handle->Reg->fltrMisc[0] |= (RT9119_FIR_DISABLE|RT9119_PAGE_SEL_DEFAULT);
                u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FLTR_MISC, handle->Reg->fltrMisc, RT9119_REG_FLTR_MISC_SIZE);
                return RT9119_E_ACCESS;
            }
        }
        memcpy(handle->Reg->fir, fir_buffer, sizeof(fir_buffer));
        handle->Reg->fltrMisc[0] &= ~(RT9119_REG_MASK_FIR|RT9119_REG_MASK_PAGE_SEL);
        handle->Reg->fltrMisc[0] |= (RT9119_FIR_ENABLE|RT9119_PAGE_SEL_DEFAULT);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_FLTR_MISC, handle->Reg->fltrMisc, RT9119_REG_FLTR_MISC_SIZE);
        if(!u2WriteNum) {
            return RT9119_E_ACCESS;
        }
    }
    return RT9119_E_OK;
}

/** RT9119_SetChannelVolume
 *  Set Channel Volume for Balance
 *  @param  handle
 *  @param  left channel : 0.1db/step
 *  @param  right channel : 0.1db/step
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetChannelVolume(RT9119_HANDLE* handle, int left_db, int right_db)
{
    unsigned char u1Command[RT9119_REG_CH1_VOL_SIZE];
    UINT16 u2WriteNum;
    int i;
    int i4ChannelVolume[2] ={0};

    i4ChannelVolume[0] = RT9119_db_to_volume(left_db);
    i4ChannelVolume[1] = RT9119_db_to_volume(right_db);
    //left
    RT9119_le32toDataBuf(i4ChannelVolume[0], u1Command, RT9119_REG_CH1_VOL_SIZE);
    if( memcmp(handle->Reg->ch1Volume, u1Command, RT9119_REG_CH1_VOL_SIZE ) != 0 ) {
        //Volume update
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH1_VOL, u1Command, RT9119_REG_CH1_VOL_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->ch1Volume, u1Command, RT9119_REG_CH1_VOL_SIZE);
    }
    //right
    RT9119_le32toDataBuf(i4ChannelVolume[1], u1Command, RT9119_REG_CH2_VOL_SIZE);
    if( memcmp(handle->Reg->ch2Volume, u1Command, RT9119_REG_CH2_VOL_SIZE ) != 0 ) {
        //Volume update
        //LOG(2,"SONY debug:: set to AMP - Chn2_Vol = 0x%lx\n", getChannelVolume[i].RCHN_REGISTER);
        u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_CH2_VOL, u1Command, RT9119_REG_CH2_VOL_SIZE);
        if(u2WriteNum == 0) {
            return RT9119_E_ACCESS;
        }
        memcpy(handle->Reg->ch2Volume, u1Command, RT9119_REG_CH2_VOL_SIZE);
    }

    return RT9119_E_OK;
}

static int RT9119_db_to_volume(int i4Volume)
{
    i4Volume = (i4Volume < 0 ? (i4Volume * 1024 - 320) / 640 : (i4Volume * 1024 + 320) / 640);
    i4Volume = 0x180 - i4Volume;

    if (0x7FF < i4Volume){
        i4Volume = 0x7FF;
    }
    return i4Volume;
}

/** RT9119_SetSmoothBQ
 *  Set Smooth BiQuad
 *  @param  handle
 *  @param  coeff :
 *  @param  coeff :
 *  @param  sbqId :
 *  @retval OK/NG
 */
RT9119_Error RT9119_SetSmoothBQ(RT9119_HANDLE* handle, RT9119IirCoeffSet* coeff1, RT9119IirCoeffSet* coeff2, int sbqId1, int sbqId2)
{
    UINT8 sbqControl[RT9119_REG_SBQ_CTRL_SIZE];
    UINT32 u4Regvalue;
    UINT16 u2WriteNum;
    RT9119_BqCoeff sbqCoeff1;
    RT9119_BqCoeff sbqCoeff2;
    unsigned char* bqRegPos1;
    unsigned char* bqRegPos2;
    int poll_timeout=0;
    int i;

const struct {
    int             sbqId1;
    int             sbqId2;
    unsigned int    updateFlag;
    unsigned int    tableOffset1;
    unsigned int    tableOffset2;
    unsigned char   bkBqReg1;
    unsigned char   bkBqReg2;
} infoTable[6] =
{
    { RT9119_BQID_13, RT9119_BQID_14, 1, offsetof(RT9119Reg, ch1SBq13), offsetof(RT9119Reg, ch1SBq14), RT9119_REG_CH1_SBQ_BK_1, RT9119_REG_CH1_SBQ_BK_2 },
    { RT9119_BQID_14, RT9119_BQID_13, 1, offsetof(RT9119Reg, ch1SBq14), offsetof(RT9119Reg, ch1SBq13), RT9119_REG_CH1_SBQ_BK_2, RT9119_REG_CH1_SBQ_BK_1 },
    { RT9119_BQID_15, RT9119_BQID_16, 2, offsetof(RT9119Reg, ch1SBq15), offsetof(RT9119Reg, ch1SBq16), RT9119_REG_CH1_SBQ_BK_1, RT9119_REG_CH1_SBQ_BK_2 },
    { RT9119_BQID_16, RT9119_BQID_15, 2, offsetof(RT9119Reg, ch1SBq16), offsetof(RT9119Reg, ch1SBq15), RT9119_REG_CH1_SBQ_BK_2, RT9119_REG_CH1_SBQ_BK_1 },
    { RT9119_BQID_17, RT9119_BQID_18, 3, offsetof(RT9119Reg, ch1SBq17), offsetof(RT9119Reg, ch1SBq18), RT9119_REG_CH1_SBQ_BK_1, RT9119_REG_CH1_SBQ_BK_2 },
    { RT9119_BQID_18, RT9119_BQID_17, 3, offsetof(RT9119Reg, ch1SBq18), offsetof(RT9119Reg, ch1SBq17), RT9119_REG_CH1_SBQ_BK_2, RT9119_REG_CH1_SBQ_BK_1 }
};

    // search Target BQ
    for(i = 0 ; i < 6 ; i++ ) {
        if(infoTable[i].sbqId1 == sbqId1 && infoTable[i].sbqId2 == sbqId2) {
            break;
        }
    }
    if( 6 == i ) {
        return RT9119_E_PARAM;
    }
    // Accuracy improvement and shift to 3.23 format
    coeff1->b0 = (coeff1->b0 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff1->b0, sbqCoeff1.b0, sizeof(sbqCoeff1.b0));
    coeff1->b1 = (coeff1->b1 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff1->b1, sbqCoeff1.b1, sizeof(sbqCoeff1.b1));
    coeff1->b2 = (coeff1->b2 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff1->b2, sbqCoeff1.b2, sizeof(sbqCoeff1.b2));
    coeff1->a1 = (coeff1->a1 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff1->a1, sbqCoeff1.a1, sizeof(sbqCoeff1.a1));
    coeff1->a2 = (coeff1->a2 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff1->a2, sbqCoeff1.a2, sizeof(sbqCoeff1.a2));

    coeff2->b0 = (coeff2->b0 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff2->b0, sbqCoeff2.b0, sizeof(sbqCoeff2.b0));
    coeff2->b1 = (coeff2->b1 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff2->b1, sbqCoeff2.b1, sizeof(sbqCoeff2.b1));
    coeff2->b2 = (coeff2->b2 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff2->b2, sbqCoeff2.b2, sizeof(sbqCoeff2.b2));
    coeff2->a1 = (coeff2->a1 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff2->a1, sbqCoeff2.a1, sizeof(sbqCoeff2.a1));
    coeff2->a2 = (coeff2->a2 + 0x20) >> 6;
    RT9119_le32toDataBuf(coeff2->a2, sbqCoeff2.a2, sizeof(sbqCoeff2.a2));

    bqRegPos1 = bqRegPos2 = (unsigned char*)handle->Reg;
    bqRegPos1 += infoTable[i].tableOffset1;
    bqRegPos2 += infoTable[i].tableOffset2;

    if( memcmp(bqRegPos1, &sbqCoeff1, RT9119_REG_BQx_SIZE ) != 0
        || memcmp(bqRegPos2, &sbqCoeff2, RT9119_REG_BQx_SIZE ) != 0) {
            //Poll Smooth Done Bit
            do{
                u2WriteNum = SIF_X_Read(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SBQ_CTRL, sbqControl, RT9119_REG_SBQ_CTRL_SIZE);
                if(u2WriteNum == 0) {
                    return RT9119_E_ACCESS;
                }
                RT9119_dataBufToLe32(sbqControl, &u4Regvalue, RT9119_REG_SBQ_CTRL_SIZE);
                if((u4Regvalue & RT9119_SBQ_DONE_BIT) != RT9119_SBQ_DONE_BIT){
                    poll_timeout+=1;
                }
                else{
                    break;
                }
                msleep(1);
            }while(poll_timeout<22);

            if(poll_timeout == 22)
            {
                return RT9119_E_ACCESS;
            }

            //Set to bkup1&2
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, infoTable[i].bkBqReg1, (UINT8*)&sbqCoeff1, RT9119_REG_BQx_SIZE);
            if(u2WriteNum == 0) {
                return RT9119_E_ACCESS;
            }
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, infoTable[i].bkBqReg2, (UINT8*)&sbqCoeff2, RT9119_REG_BQx_SIZE);
            if(u2WriteNum == 0) {
                return RT9119_E_ACCESS;
            }
            //Set Transition Update
            RT9119_dataBufToLe32(sbqControl, &u4Regvalue, RT9119_REG_SBQ_CTRL_SIZE);
            u4Regvalue &= ~RT9119_REG_MASK_SBQ_UPDATE;
            u4Regvalue |= infoTable[i].updateFlag;
            RT9119_le32toDataBuf(u4Regvalue, sbqControl, RT9119_REG_SBQ_CTRL_SIZE);
            u2WriteNum = RT9119_Reg_Write(handle->u2ClkDiv, SIF_CLK_DIV, handle->u1DevAddr, 1, RT9119_REG_SBQ_CTRL, sbqControl, RT9119_REG_SBQ_CTRL_SIZE);
            if(u2WriteNum == 0) {
                return RT9119_E_ACCESS;
            }
            memcpy(handle->Reg->sbqBqctrl, sbqControl, RT9119_REG_SBQ_CTRL_SIZE);
            //DRAM Update
            memcpy(bqRegPos1, &sbqCoeff1, RT9119_REG_BQx_SIZE);
            memcpy(bqRegPos2, &sbqCoeff2, RT9119_REG_BQx_SIZE);
    }
    return RT9119_E_OK;
}

//////////////////////////////////////////////////////
//*****************COMMON METHOD**********************
//////////////////////////////////////////////////////

static void RT9119_le32toDataBuf(UINT32 le32, unsigned char* dst, const unsigned int size) {
    int i;

    if(size > 4) {  // range over
        return;     // argument error
    }
    for( i = size ; i ; i-- ) {
        dst[i - 1] = (unsigned char)(le32 & 0xFF);
        le32 = le32 >> 8;
    }
}

static void RT9119_dataBufToLe32(unsigned char* src, UINT32* le32, const unsigned int size) {
    int i;
    int j;

    if(size > 4) {  // range over
        return;     // argument error
    }
    *le32 = 0;  // initialize destination
    for( i = size, j = 0 ; (i && (j < size)) ; i--, j++ ) {
        *le32 |= (src[j]) << (8*(i-1));
    }
}
#endif
