/*
 * Project Name MFC DRIVER IN WINCE
 * Copyright  2009 Samsung Electronics Co, Ltd. All Rights Reserved.
 *
 * This file implements MFC driver.
 *
 * @name MFC DRIVER Module (MfcOpr.c)
 * @author Jiyoung Shin (idon.shin@samsung.com)
 * @date 2009/06/05
 */

#include "bsp.h"
#include "MfcCommon.h"
#include "mfc_reg.h"
#include "MfcOpr.h"
#include "MfcLogMsg.h"
#include "MfcMemory.h"
#include "MfcFW.h"
#include "MfcPower.h"

static void MFC_CMD_RESET(volatile MFC_SFR *MfcSfr);
static void MFC_CMD_HOST2RISC(volatile MFC_SFR *MfcSfr, MFC_FACADE_CMD command, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4);
static void MFC_CMD_CODEC_DEC(MFC_CODEC_COMM_DEC *DecCommSfr, unsigned int arg, unsigned int ch_id);
static void MFC_CMD_CODEC_ENC(MFC_CODEC_COMM_ENC *EncCommSfr, unsigned int arg, unsigned int ch_id);
static SSBSIP_MFC_ERROR_CODE SetDecStreamBuffer(MFC_INST_CTX  *MfcCtx, int buf_addr, unsigned int buf_size, unsigned int startByteNum);
static SSBSIP_MFC_ERROR_CODE SetDecFrameBuffer(MFC_INST_CTX  *MfcCtx, MFC_DEC_EXE_ARG *DecArg);
static SSBSIP_MFC_ERROR_CODE SetFWWorkingBuffer(MFC_INST_CTX  *MfcCtx);
static SSBSIP_MFC_ERROR_CODE DecodeOneFrame(MFC_INST_CTX  *MfcCtx,  MFC_DEC_EXE_ARG *DecArg, unsigned int startByteNum, unsigned int *consumedStrmSize);
static void SetEncodeInitParam(MFC_INST_CTX  *MfcCtx, MFC_SFR *MfcSfr, SSBSIP_MFC_CODEC_TYPE mfc_codec_type, ARGS *args);

static void MFC_CMD_RESET(volatile MFC_SFR *MfcSfr)
{
    unsigned int StatusReg;

/*
    do{
        StatusReg = MfcSfr->MFC_MC_STATUS;
        MFCDelay(1);
    }while(StatusReg != 0);
*/
    MfcSfr->MFC_SW_RESET = 0x3f7;		// VI reset
    MfcSfr->MFC_SW_RESET = 0x3f6;		// RISC reset
    MfcSfr->MFC_SW_RESET = 0x3e2;		// All reset except MC
    MFCDelay(1);
/*   
    do{
        StatusReg = MfcSfr->MFC_MC_STATUS;
        MFCDelay(1);
    }while(StatusReg & 0x3);
*/    
    MfcSfr->MFC_SW_RESET = 0;
    MfcSfr->MFC_SW_RESET = 0x3fe;

    // Set dram base Addr
    MfcSfr->MFC_MC_DRAMBASE_ADDR_A = GetDramAPhyBaseAddr();
    MfcSfr->MFC_MC_DRAMBASE_ADDR_B = GetDramBPhyBaseAddr();
    LOG_MSG(LOG_TRACE, "MFCOpen", "MFC_MC_DRAMBASE_ADDR_A : 0x%08x MFC_MC_DRAMBASE_ADDR_B : 0x%08x\n",
                                    MfcSfr->MFC_MC_DRAMBASE_ADDR_A, MfcSfr->MFC_MC_DRAMBASE_ADDR_B);

    if(((GetDramAPhyBaseAddr()% 0x10000) != 0) || ((GetDramBPhyBaseAddr()% 0x10000) != 0)){
        LOG_MSG(LOG_ERROR, "MFCOpen", "GetDramAPhyBaseAddr() and GetDramBPhyBaseAddr() address have to be aligned at 64KB(0x10000)\n");
        return MFC_RET_OPEN_FAIL;
    }
    
    MfcSfr->MFC_NUM_MASTER = 1;
    MfcSfr->MFC_MC_RS_IBASE = 0;   // firmware code & buffer location -> A port
    MfcSfr->codec_comm.dec_comm.MFC_SI_CH1_INST_ID = 0x0000ffff;
    MfcSfr->codec_comm.dec_comm.MFC_SI_CH2_INST_ID = 0x0000ffff;


    MfcSfr->MFC_RISC2HOST_CMD = 0;
    MfcSfr->MFC_HOST2RISC_CMD = 0;
    MFCClearIntr();
}

static void MFC_CMD_HOST2RISC(volatile MFC_SFR *MfcSfr, MFC_FACADE_CMD command, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4)
{
    unsigned int StatusReg;
    
    do{
        StatusReg = MfcSfr->MFC_HOST2RISC_CMD;
        MFCDelay(1);
    }while(StatusReg != 0);

    MfcSfr->MFC_HOST2RISC_ARG1 = arg1;
    MfcSfr->MFC_HOST2RISC_ARG2 = arg2;
    MfcSfr->MFC_HOST2RISC_ARG3 = arg3;
    MfcSfr->MFC_HOST2RISC_ARG4 = arg4;
    MfcSfr->MFC_HOST2RISC_CMD = command;

}

static void MFC_CMD_CODEC_DEC(MFC_CODEC_COMM_DEC *DecCommSfr, unsigned int arg, unsigned int ch_id)
{
    DecCommSfr->MFC_SI_CH1_INST_ID = (arg | ch_id);
}

static void MFC_CMD_CODEC_ENC(MFC_CODEC_COMM_ENC *EncCommSfr, unsigned int arg, unsigned int ch_id)
{
    EncCommSfr->MFC_SI_CH1_INST_ID = (arg | ch_id);
}

static SSBSIP_MFC_ERROR_CODE SetDecStreamBuffer(MFC_INST_CTX  *MfcCtx, int buf_addr, unsigned int buf_size, unsigned int startByteNum)
{
    volatile MFC_SFR *MfcSfr;
    MFC_CODEC_COMM_DEC *DecCommSfr;
    MFC_SHARED_MEM *MfcShm;
    int alignedBufAddr;

    MfcSfr = GetSfrVirAddr();
    MfcShm = GetSharedMemVirAddr(MfcCtx->InstNo);
    DecCommSfr = &(MfcSfr->codec_comm);    
        
    LOG_MSG(LOG_DEBUG, "SetDecStreamBuffer++", "buf_addr : 0x%08x  buf_size : 0x%x startByteNum : %d\n", buf_addr, buf_size, startByteNum);
    
    
    // Stream buffer have to be located in DRAM_0
    if(buf_addr < GetDramAPhyBaseAddr()){
        LOG_MSG(LOG_DEBUG, "SetDecStreamBuffer", "buf_addr is invalid.... buf_addr have to be at DRAM_0\n");
        return MFC_RET_DEC_EXE_ERR;
    }

    alignedBufAddr = buf_addr - startByteNum;
    if(alignedBufAddr % 4096 != 0){
        LOG_MSG(LOG_DEBUG, "SetDecStreamBuffer", "start byte num is wrong(%d)\n", startByteNum);
        return MFC_RET_DEC_EXE_ERR;

    }
    DecCommSfr->MFC_SI_CH1_SB_ST_ADDR = (alignedBufAddr - GetDramAPhyBaseAddr())>>11;
    DecCommSfr->MFC_SI_CH1_DESC_ADDR = (GetFWDataBufPhyAddr(MfcCtx->InstNo) - GetDramAPhyBaseAddr())>>11;
    DecCommSfr->MFC_SI_CH1_SB_FRAME_SIZE = buf_size;
    DecCommSfr->MFC_SI_CH1_CPB_SIZE = 3072*1024; // why it need to be set ?
    DecCommSfr->MFC_SI_CH1_DESC_SIZE = MFC_DEC_DESC_BUFF_SIZE;
    MfcShm->START_BYTE_NUM = startByteNum;

    LOG_MSG(LOG_DEBUG,  "SetDecStreamBuffer--", "\n");
    return MFC_RET_OK;
}


static SSBSIP_MFC_ERROR_CODE SetDecFrameBuffer(MFC_INST_CTX  *MfcCtx, MFC_DEC_EXE_ARG *DecArg)
{
    unsigned int    Width, Height, FrameSize;
    volatile MFC_SFR *MfcSfr;
    MFC_COMMON *DpbSfr;
    unsigned int    i;
    unsigned int    *p_sfr;
    int DpbBaseAddr;

    LOG_MSG(LOG_DEBUG, "SetDecFrameBuffer++", "\n");
    LOG_MSG(LOG_DEBUG, "SetDecFrameBuffer", "Ybuffer:0x%x YSize:0x%x Cbbuffer:0x%08x CbSize:0x%x\n", 
                    DecArg->in_frmYBuf, DecArg->in_frmYSize, DecArg->in_frmCbBuf, DecArg->in_frmCbSize);
    LOG_MSG(LOG_DEBUG, "SetDecFrameBuffer", "MfcCtx->DPBSize:0x%x MfcCtx->DPBCnt:%d\n", 
                    MfcCtx->DPBSize, MfcCtx->DPBCnt);


    MfcSfr = GetSfrVirAddr();
    DpbSfr = &(MfcSfr->dpb);
    
    if(DecArg->in_frmYSize + DecArg->in_frmCbSize < MfcCtx->DPBSize){
        LOG_MSG(LOG_ERROR, "SetDecFrameBuffer", "input frame buffer size is invalid\n");
        return MFC_RET_DEC_EXE_ERR;
    }

    LOG_MSG(LOG_DEBUG, "SetDecFrameBuffer", "MfcCtx->YSize:0x%x MfcCtx->CbSize:0x%x\n", 
                    MfcCtx->YSize, MfcCtx->CbSize);
    if(MfcCtx->MfcCodecType == H264_DEC){
        // Y
        DpbBaseAddr =  DecArg->in_frmYBuf - GetDramBPhyBaseAddr();
        p_sfr = &(DpbSfr->MFC_COMMON_BASE_ADDR_64);
        for(i = 0; i < MfcCtx->DPBCnt; i++){
            *p_sfr = (DpbBaseAddr + i*MfcCtx->YSize) >> 11;
            p_sfr++;
        }
        
        // Motion Vector
        DpbBaseAddr += MfcCtx->YSize*MfcCtx->DPBCnt;
        p_sfr = &(DpbSfr->MFC_COMMON_BASE_ADDR_96);
        for(i = 0; i < MfcCtx->DPBCnt; i++){
            *p_sfr = (DpbBaseAddr + i*MfcCtx->MVSize) >> 11;
            p_sfr++;
        }
        
        // CbCr
        DpbBaseAddr = DecArg->in_frmCbBuf - GetDramAPhyBaseAddr();
        p_sfr = &(DpbSfr->MFC_COMMON_BASE_ADDR_0);
        for(i = 0; i < MfcCtx->DPBCnt; i++){
            *p_sfr = (DpbBaseAddr + i*MfcCtx->CbSize) >> 11;
            p_sfr++;
        }


    }
    else{
        // Y
        DpbBaseAddr =  DecArg->in_frmYBuf - GetDramBPhyBaseAddr();
        p_sfr = &(DpbSfr->MFC_COMMON_BASE_ADDR_64);
        for(i = 0; i < MfcCtx->DPBCnt; i++){
            *p_sfr = (DpbBaseAddr + i*MfcCtx->YSize) >> 11;
            p_sfr++;
        }

        // CbCr
        DpbBaseAddr = DecArg->in_frmCbBuf - GetDramAPhyBaseAddr();
        p_sfr = &(DpbSfr->MFC_COMMON_BASE_ADDR_0);
        for(i = 0; i < MfcCtx->DPBCnt; i++){
            *p_sfr = (DpbBaseAddr + i*MfcCtx->CbSize) >> 11;
            p_sfr++;
        }
    }


    LOG_MSG(LOG_DEBUG, "SetDecFrameBuffer--", "\n");
    return MFC_RET_OK;

}

static SSBSIP_MFC_ERROR_CODE SetFWWorkingBuffer(MFC_INST_CTX  *MfcCtx)
{
    volatile MFC_SFR *MfcSfr;
    MFC_SHARED_MEM *MfcShm;
    unsigned int WorkBufferBaseAddr;


    LOG_MSG(LOG_DEBUG, "SetFWWorkingBuffer++", "\n");
    LOG_MSG(LOG_WARNING, "SetFWWorkingBuffer", "GetFWDataBufPhyAddr(%d) :  0x%08x\n", MfcCtx->InstNo, GetFWDataBufPhyAddr(MfcCtx->InstNo));
    MfcSfr = GetSfrVirAddr();


    if(MfcCtx->MfcCodecType == H264_DEC){
        LOG_MSG(LOG_DEBUG, "SetFWWorkingBuffer", "H264_DEC\n");

        // set firmware buffer
        WorkBufferBaseAddr = GetFWDataBufPhyAddr(MfcCtx->InstNo) + MFC_DEC_DESC_BUFF_SIZE - GetDramAPhyBaseAddr();
            
        MfcSfr->dpb.dec_h264_buffer.MFC_DBP_H264_VERT_NB_MV = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_VERT_NB_MV_BUFF_SIZE;
        MfcSfr->dpb.dec_h264_buffer.MFC_DBP_H264_NB_PIXEL_INTRA = (WorkBufferBaseAddr >> 11);

        // set DPB size in shared memory
        MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);
        MfcShm->ALLOCATED_LUMA_DPB_SIZE = MfcCtx->YSize;
        MfcShm->ALLOCATED_CHROMA_DPB_SIZE = MfcCtx->CbSize;
        MfcShm->ALLOCATED_MV_SIZE = MfcCtx->MVSize;
    }
    else if((MfcCtx->MfcCodecType == H264_ENC) || (MfcCtx->MfcCodecType == MPEG4_ENC) || (MfcCtx->MfcCodecType == H263_ENC)){
        LOG_MSG(LOG_DEBUG, "SetFWWorkingBuffer", "ENC\n");

        WorkBufferBaseAddr = GetFWDataBufPhyAddr(MfcCtx->InstNo) + MFC_FW_DEC_BUFF_SIZE - GetDramAPhyBaseAddr();
        
        MfcSfr->dpb.enc_buffer.MFC_ENC_DP_UPPER_MV_ADDR = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_ENC_UPPER_MV_BUFF_SIZE;
        MfcSfr->dpb.enc_buffer.MFC_ENC_DP_COZERO_FLAG_ADDR = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_ENC_DIRECT_COZERO_FLAG_BUFF_SIZE;
        MfcSfr->dpb.enc_buffer.MFC_ENC_DP_UPPER_INTRA_MD_ADDR = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_ENC_UPPER_INTRA_MD_BUFF_SIZE;
        MfcSfr->dpb.enc_buffer.MFC_ENC_DP_NBOR_INFO_MPENC_ADDR = (WorkBufferBaseAddr >> 11);
    }
    else{
        LOG_MSG(LOG_DEBUG, "SetFWWorkingBuffer", "other DEC\n");   

        // set firmware buffer
        WorkBufferBaseAddr = GetFWDataBufPhyAddr(MfcCtx->InstNo) + MFC_DEC_DESC_BUFF_SIZE - GetDramAPhyBaseAddr();
            
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_NB_ACDC_COEFF = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_NB_ACDC_COEFF_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_UPPER_NB_MV = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_UPPER_NB_MV_BUFF_IZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_ANCHOR_MV = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_ANCHOR_MV_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_OVERLAP_TRANS = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_OVERLAP_TRANS_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_BITPLANE_3 = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_BITBPLANE_3_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_BITPLANE_2 = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_BITBPLANE_2_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_BITPLANE_1 = (WorkBufferBaseAddr >> 11);
        WorkBufferBaseAddr += MFC_DEC_BITBPLANE_1_BUFF_SIZE;
        MfcSfr->dpb.dec_except_h264_buffer.MFC_DBP_SYNTAX_PARSER = (WorkBufferBaseAddr >> 11);

        // set DPB size in shared memory
        MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);
        MfcShm->ALLOCATED_LUMA_DPB_SIZE = MfcCtx->YSize;
        MfcShm->ALLOCATED_CHROMA_DPB_SIZE = MfcCtx->CbSize;
        MfcShm->ALLOCATED_MV_SIZE = 0;
    }
    
    LOG_MSG(LOG_DEBUG, "SetFWWorkingBuffer--", "\n");
    return MFC_RET_OK;
}

SSBSIP_MFC_ERROR_CODE SetMFCSleep(MFC_INST_CTX  *MfcCtx)
{
    volatile MFC_SFR *MfcSfr;
    SSBSIP_MFC_ERROR_CODE ret;

    LOG_MSG(LOG_WARNING, "SetMFCSleep", "++\n");
    MfcSfr = GetSfrVirAddr();

    MFCClockOnOff(CLK_ON);
    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_SYS_SLEEP, 0, 0, 0, 0);

    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SYS_SLEPP_RET)) == 0){
        LOG_MSG(LOG_ERROR, "SetMFCSleep", "MFC_R2H_CMD_SYS_SLEPP_RET is failed\n");
        return MFC_RET_FAIL;
    }

    MFCDelay(10);
    MFCClockOnOff(CLK_OFF);
    MFCPowerOnOff(POWER_OFF);

    LOG_MSG(LOG_WARNING, "SetMFCSleep", "--\n");
    return MFC_RET_OK;

}

SSBSIP_MFC_ERROR_CODE SetMFCWakeUp(MFC_INST_CTX  *MfcCtx)
{

    volatile MFC_SFR *MfcSfr;
    SSBSIP_MFC_ERROR_CODE ret;
    unsigned int FWPhyBuf;
    unsigned int VSPPhyBuf;
    unsigned int CodecType;

    LOG_MSG(LOG_WARNING, "SetMFCWakeUp", "++\n");
    MfcSfr = GetSfrVirAddr();

    MFCPowerOnOff(POWER_ON);
    MFCClockOnOff(CLK_ON);

    //////////////////////////////////////////////
    // 1. MFC reset                             //
    //////////////////////////////////////////////
    MFC_CMD_RESET(MfcSfr);
    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_SYS_WAKEUP, 0, 0, 0, 0);
    MFCDelay(1);
    MfcSfr->MFC_SW_RESET = 0x3ff;

    LOG_MSG(LOG_TRACE, "SetMFCWakeUp", "1. Loading Firmware\n");

   if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SYS_WAKEUP_RET)) == 0){
        LOG_MSG(LOG_ERROR, "SetMFCWakeUp", "MFC_R2H_CMD_SYS_WAKEUP_RET is failed\n");
        return MFC_RET_FAIL;
    }

    //////////////////////////////////////////////
    // 2. Initialize FW                         //
    //////////////////////////////////////////////
    LOG_MSG(LOG_TRACE, "SetMFCWakeUp", "2. Initialize Firmware\n");
    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_SYS_INIT, MFC_FIRMWARE_CODE_SIZE, 0, 0, 0);

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SYS_INIT_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCOpen", "firmware initialization is failed\n");
        return MFC_RET_OPEN_FAIL;
    }

    LOG_MSG(LOG_WARNING, "SetMFCWakeUp", "--\n");
    MFCClockOnOff(CLK_OFF);
    
    return MFC_RET_OK;
}


// This function sets the MFC SFR values according to the input arguments.
static void SetEncodeInitParam(MFC_INST_CTX  *MfcCtx, MFC_SFR *MfcSfr,  SSBSIP_MFC_CODEC_TYPE mfc_codec_type, ARGS *args)
{
    MFC_DPB_ENC *EncSfr;
    MFC_ENC_INIT_MPEG4_ARG *EncInitMpeg4Arg;
    MFC_ENC_INIT_H263_ARG *EncInitH263Arg;
    MFC_ENC_INIT_H264_ARG *EncInitH264Arg;
    MFC_SHARED_MEM *MfcShm;
    unsigned int YSize = 0, CbCrSize = 0;
    int ABufAddr = 0, BBufAddr = 0;

    EncSfr = &(MfcSfr->dpb);
    MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);
    EncInitMpeg4Arg = (MFC_ENC_INIT_MPEG4_ARG *) args;
    EncInitH264Arg  = (MFC_ENC_INIT_H263_ARG  *) args;
    EncInitH263Arg = (MFC_ENC_INIT_H264_ARG  *) args;
    mfc_codec_type = EncInitH264Arg->in_cfg.codecType;

    LOG_MSG(LOG_DEBUG, "SetEncodeInitParam", "in_cfg.SourceWidth : %d  in_cfg.SourceWidth: %d\r\n", 
                                                                                EncInitMpeg4Arg->in_cfg.SourceWidth, EncInitMpeg4Arg->in_cfg.SourceHeight);

    if(mfc_codec_type == MPEG4_ENC){
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam++", "mfc_codec_type : %d  in_dpb_portA_addr: 0x%08x in_dpb_portB_addr : 0x%08x \r\n", 
                            mfc_codec_type, EncInitMpeg4Arg->in_dpb_portA_addr, EncInitMpeg4Arg->in_dpb_portB_addr);

        YSize = Align(Align(EncInitMpeg4Arg->in_cfg.SourceWidth, 128) * Align(EncInitMpeg4Arg->in_cfg.SourceHeight, 32), 64*1024);
        CbCrSize = Align(Align(EncInitMpeg4Arg->in_cfg.SourceWidth, 128) * Align(EncInitMpeg4Arg->in_cfg.SourceHeight, 32)>> 1, 64*1024);
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam", "[MPEG4]YSize : 0x%x CbCrSize : 0x%x \r\n", YSize,CbCrSize);

        ABufAddr = Align(EncInitMpeg4Arg->in_dpb_portA_addr, 16*1024) - GetDramAPhyBaseAddr();
        BBufAddr = Align(EncInitMpeg4Arg->in_dpb_portB_addr, 16*1024) - GetDramBPhyBaseAddr();
    }
    else if(mfc_codec_type == H263_ENC){
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam++", "mfc_codec_type : %d  in_dpb_portA_addr: 0x%08x in_dpb_portB_addr : 0x%08x \r\n", 
                           mfc_codec_type, EncInitH263Arg->in_dpb_portA_addr, EncInitH263Arg->in_dpb_portB_addr);

        YSize = Align(Align(EncInitH263Arg->in_cfg.SourceWidth, 128) * Align(EncInitH263Arg->in_cfg.SourceHeight, 32), 64*1024);
        CbCrSize = Align(Align(EncInitH263Arg->in_cfg.SourceWidth, 128) * Align(EncInitH263Arg->in_cfg.SourceHeight, 32)>> 1, 64*1024);
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam", "[H263_ENC]YSize : 0x%x CbCrSize : 0x%x \r\n", YSize,CbCrSize);
        
        ABufAddr = Align(EncInitH263Arg->in_dpb_portA_addr, 16*1024) - GetDramAPhyBaseAddr();
        BBufAddr = Align(EncInitH263Arg->in_dpb_portB_addr, 16*1024) - GetDramBPhyBaseAddr();
    }
    else if(mfc_codec_type == H264_ENC){
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam++", "mfc_codec_type : %d  in_dpb_portA_addr: 0x%08x in_dpb_portB_addr : 0x%08x \r\n", 
                           mfc_codec_type, EncInitH264Arg->in_dpb_portA_addr, EncInitH264Arg->in_dpb_portB_addr);

        YSize = Align(Align(EncInitH264Arg->in_cfg.SourceWidth, 128) * Align(EncInitH264Arg->in_cfg.SourceHeight, 32), 64*1024);
        CbCrSize = Align(Align(EncInitH264Arg->in_cfg.SourceWidth, 128) * Align(EncInitH264Arg->in_cfg.SourceHeight, 32)>> 1, 64*1024);
        LOG_MSG(LOG_DEBUG, "SetEncodeInitParam", "[H264_ENC]YSize : 0x%x CbCrSize : 0x%x \r\n", YSize,CbCrSize);
             
        ABufAddr = Align(EncInitH264Arg->in_dpb_portA_addr, 16*1024) - GetDramAPhyBaseAddr();
        BBufAddr = Align(EncInitH264Arg->in_dpb_portB_addr, 16*1024) - GetDramBPhyBaseAddr();
    }

    EncSfr->MFC_ENC_DP_REF0_LUMA_ADDR = (Align(ABufAddr, 64*1024)) >> 11;
    ABufAddr += YSize;
    EncSfr->MFC_ENC_DP_REF1_LUMA_ADDR = (Align(ABufAddr, 64*1024)) >> 11;
    ABufAddr += YSize;
    EncSfr->MFC_ENC_DP_REF0_B_FRAME_CHROMA_ADDR = (Align(ABufAddr, 64*1024)) >> 11;
    ABufAddr += CbCrSize;
    EncSfr->MFC_ENC_DP_REF0_B_FRAME_LUMA_ADDR = (Align(ABufAddr, 64*1024)) >> 11;

    MfcSfr->dpb.enc_buffer.MFC_ENC_DP_UPPER_INTRA_PRED_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += MFC_ENC_UPPER_INTRA_PRED_BUFF_SIZE;
    EncSfr->MFC_ENC_DP_REF0_CHROMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += CbCrSize;
    EncSfr->MFC_ENC_DP_REF2_LUMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += YSize;
    EncSfr->MFC_ENC_DP_REF1_CHROMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += CbCrSize;
    EncSfr->MFC_ENC_DP_REF2_CHROMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += CbCrSize;
    EncSfr->MFC_ENC_DP_REF3_LUMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;
    BBufAddr += YSize;
    EncSfr->MFC_ENC_DP_REF3_CHROMA_ADDR = (Align(BBufAddr, 64*1024)) >> 11;



    MfcSfr->MFC_EDFU_STR_BF_MODE_CTRL = STREAM_BUF_FRAME_MODE;

    // stream control register
    MfcSfr->MFC_EDFU_SF_EPB_ON_CTRL = 1;	// automatical EPB insertion on
    
    // set memory structure of current frame
    MfcSfr->MFC_ENC_MAP_FOR_CUR =  MB_LINEAR_MODE;

    switch (mfc_codec_type) {
    case MPEG4_ENC:
        {
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "ProfileIDC : %d LevelIDC : %d \r\n", EncInitMpeg4Arg->in_cfg.ProfileIDC, EncInitMpeg4Arg->in_cfg.LevelIDC);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "SliceMode : %d SliceArgument : %d \r\n", EncInitMpeg4Arg->in_cfg.SliceMode, EncInitMpeg4Arg->in_cfg.SliceArgument);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "RandomIntraMBRefresh : %d NumberBFrames : %d \r\n", EncInitMpeg4Arg->in_cfg.RandomIntraMBRefresh, EncInitMpeg4Arg->in_cfg.NumberBFrames);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "DisableQpelME : %d \r\n", EncInitMpeg4Arg->in_cfg.DisableQpelME);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "EnableFRMRateControl : %d \r\n", EncInitMpeg4Arg->in_cfg.EnableFRMRateControl);
            LOG_MSG(LOG_WARNING, "[MPEG4]", "TimeIncreamentRes : %d VopTimeIncreamentEnc:%d Bitrate : %d \r\n", EncInitMpeg4Arg->in_cfg.TimeIncreamentRes, EncInitMpeg4Arg->in_cfg.VopTimeIncreament, EncInitMpeg4Arg->in_cfg.Bitrate);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "FrameQp : %d CBRPeriodRf : %d \r\n", EncInitMpeg4Arg->in_cfg.FrameQp, EncInitMpeg4Arg->in_cfg.CBRPeriodRf);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "QSCodeMax : %d QSCodeMin : %d \r\n", EncInitMpeg4Arg->in_cfg.QSCodeMax, EncInitMpeg4Arg->in_cfg.QSCodeMin);
            LOG_MSG(LOG_DEBUG, "[MPEG4]", "IDRPeriod : %d\r\n", EncInitMpeg4Arg->in_cfg.IDRPeriod);

            //
            // common config value
            //
            MfcSfr->MFC_HSIZE_PX = EncInitMpeg4Arg->in_cfg.SourceWidth;
            MfcSfr->MFC_VSIZE_PX = EncInitMpeg4Arg->in_cfg.SourceHeight;

            // set registers related to multi-slice
            if (EncInitMpeg4Arg->in_cfg.SliceMode == 0)
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = 0;
            }
            else if (EncInitMpeg4Arg->in_cfg.SliceMode  == 1)	// fixed # mb in slice
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = (0<<1)|0x1;
                MfcSfr->MFC_ENC_MSLICE_MB = EncInitMpeg4Arg->in_cfg.SliceArgument;
            }
            else if (EncInitMpeg4Arg->in_cfg.SliceMode  == 2)	// fixed # bytes in slice
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = (1<<1)|0x1;
                MfcSfr->MFC_ENC_MSLICE_BYTE = EncInitMpeg4Arg->in_cfg.SliceArgument;
            }
            else if (EncInitMpeg4Arg->in_cfg.SliceMode  == 4)
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = 0x5;  // ox5 : multislicing is done by varriable MB count value , enable of resync marker or Multi slice
            }

            MfcSfr->MFC_ENC_CIR_NUM = EncInitMpeg4Arg->in_cfg.RandomIntraMBRefresh;

            // rate control config.
            if(EncInitMpeg4Arg->in_cfg.FrameQp <= 0 ){
                LOG_MSG(LOG_WARNING, "[MPEG4]", "FrameQp is invalid(lower than 1)...It sets as default value(20)\r\n");
                EncInitMpeg4Arg->in_cfg.FrameQp = 20;
            }
            MfcSfr->MFC_RC_CONFIG = ((EncInitMpeg4Arg->in_cfg.EnableFRMRateControl<<9)|
                                    (EncInitMpeg4Arg->in_cfg.FrameQp<<0));

            // bit rate
            MfcSfr->MFC_RC_BIT_RATE = EncInitMpeg4Arg->in_cfg.Bitrate;

            // frame rate
            MfcSfr->MFC_RC_FRAME_RATE = EncInitMpeg4Arg->in_cfg.TimeIncreamentRes/EncInitMpeg4Arg->in_cfg.VopTimeIncreament;
            printf("MfcSfr->MFC_RC_FRAME_RATE : %d\n", MfcSfr->MFC_RC_FRAME_RATE);

            // Qunatization Parameter Boundary
            MfcSfr->MFC_RC_QBOUND = (EncInitMpeg4Arg->in_cfg.QSCodeMax<<8)|(EncInitMpeg4Arg->in_cfg.QSCodeMin<<0);

            // reaction coefficient
            if (EncInitMpeg4Arg->in_cfg.EnableFRMRateControl == 1)
            {
                MfcSfr->MFC_RC_RPARA = EncInitMpeg4Arg->in_cfg.CBRPeriodRf;
            }
            //
            //
            //
            MfcSfr->MFC_ENC_PADDIMG_CTRL = 0;
            MfcSfr->MFC_PROFILE = (EncInitMpeg4Arg->in_cfg.LevelIDC << 8) | EncInitMpeg4Arg->in_cfg.ProfileIDC;
            MfcSfr->MFC_PICTURE_STRUCT = 0;
            
            MfcSfr->MFC_ENC_PADDIMG_CTRL = (EncInitH264Arg->in_cfg.PadControlOn<<31)
                                |(EncInitH264Arg->in_cfg.CrPadVal<<16)
                                |(EncInitH264Arg->in_cfg.CbPadVal<<8)
                                |(EncInitH264Arg->in_cfg.LumaPadVal<<0);
            
            // loop filter control register
            MfcSfr->MFC_LF_CONTROL = 1;
            MfcSfr->MFC_ENC_PIC_TYPE_CTRL = (1<<18)|(EncInitMpeg4Arg->in_cfg.NumberBFrames << 16)|(EncInitMpeg4Arg->in_cfg.IDRPeriod);
            MfcSfr->MFC_ENC_REF_NUM_SEL = 0;
            MfcSfr->MPEG4_ENC_QUART_PXL = !(EncInitMpeg4Arg->in_cfg.DisableQpelME);

            // set shared memory area
            MfcCtx->timeIncrement = EncInitMpeg4Arg->in_cfg.VopTimeIncreament;
            MfcShm->VOP_TIMING = ((1<<31)|(EncInitMpeg4Arg->in_cfg.TimeIncreamentRes << 16)|(0 & 0xFFFF));

            if(EncInitMpeg4Arg->in_cfg.EnableFRMRateControl == 0){
                if(EncInitMpeg4Arg->in_cfg.FrameQp_B <= 0){
                    LOG_MSG(LOG_WARNING, "[MPEG4]", "FrameQp_B is invalid(lower than 1)...It sets as FrameQp+3(%d)\r\n", EncInitMpeg4Arg->in_cfg.FrameQp+3);
                    EncInitMpeg4Arg->in_cfg.FrameQp_B = EncInitMpeg4Arg->in_cfg.FrameQp + 3;
                }

                if(EncInitMpeg4Arg->in_cfg.FrameQp_P <= 0){
                    LOG_MSG(LOG_WARNING, "[MPEG4]", "FrameQp_P is invalid(lower than 1)...It sets as FrameQp+1(%d)\r\n", EncInitMpeg4Arg->in_cfg.FrameQp+1);
                    EncInitMpeg4Arg->in_cfg.FrameQp_P = EncInitMpeg4Arg->in_cfg.FrameQp + 1;
                }

                MfcShm->P_B_FRAME_QP = ((EncInitMpeg4Arg->in_cfg.FrameQp_B << 6) | (EncInitMpeg4Arg->in_cfg.FrameQp_P & 0x3F));
            }
            
            break;
        }

    case H263_ENC:
        {
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "SliceMode : %d \r\n", EncInitH263Arg->in_cfg.SliceMode);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "RandomIntraMBRefresh : %d \r\n", EncInitH263Arg->in_cfg.RandomIntraMBRefresh);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "EnableFRMRateControl : %d \r\n", EncInitH263Arg->in_cfg.EnableFRMRateControl);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "FrameRate : %d Bitrate : %d \r\n", EncInitH263Arg->in_cfg.FrameRate, EncInitH263Arg->in_cfg.Bitrate);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "FrameQp : %d CBRPeriodRf : %d \r\n", EncInitH263Arg->in_cfg.FrameQp, EncInitH263Arg->in_cfg.CBRPeriodRf);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "QSCodeMax : %d QSCodeMin : %d \r\n", EncInitH263Arg->in_cfg.QSCodeMax, EncInitH263Arg->in_cfg.QSCodeMin);
            LOG_MSG(LOG_DEBUG, "[H263_ENC]", "IDRPeriod : %d\r\n", EncInitH263Arg->in_cfg.IDRPeriod);

            //
            // common config value
            //
            MfcSfr->MFC_HSIZE_PX = EncInitH263Arg->in_cfg.SourceWidth;
            MfcSfr->MFC_VSIZE_PX = EncInitH263Arg->in_cfg.SourceHeight;

            // set registers related to multi-slice
            if (EncInitH263Arg->in_cfg.SliceMode == 0)
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = 0;
            }
            else
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = (0<<1)|0x1;
                MfcSfr->MFC_ENC_MSLICE_MB = 0;
            }

            MfcSfr->MFC_ENC_CIR_NUM = EncInitH263Arg->in_cfg.RandomIntraMBRefresh;

            // rate control config.
            if(EncInitH263Arg->in_cfg.FrameQp <= 0 ){
                LOG_MSG(LOG_WARNING, "[H263]", "FrameQp is invalid(lower than 1)...It sets as default value(20)\r\n");
                EncInitH263Arg->in_cfg.FrameQp = 20;
            }
            MfcSfr->MFC_RC_CONFIG = ((EncInitH263Arg->in_cfg.EnableFRMRateControl<<9)|
                                    (EncInitH263Arg->in_cfg.FrameQp<<0));

            // frame rate
            MfcSfr->MFC_RC_FRAME_RATE = EncInitH263Arg->in_cfg.FrameRate;


            // bit rate
            MfcSfr->MFC_RC_BIT_RATE = EncInitH263Arg->in_cfg.Bitrate;


            // Qunatization Parameter Boundary
            MfcSfr->MFC_RC_QBOUND = (EncInitH263Arg->in_cfg.QSCodeMax<<8)|(EncInitH263Arg->in_cfg.QSCodeMin<<0);

            // reaction coefficient
            if (EncInitH263Arg->in_cfg.EnableFRMRateControl == 1)
            {
            MfcSfr->MFC_RC_RPARA = EncInitH263Arg->in_cfg.CBRPeriodRf;
            }
            //
            //
            //
            MfcSfr->MFC_ENC_PADDIMG_CTRL = 0;
            MfcSfr->MFC_PROFILE = 0x20;
            MfcSfr->MFC_PICTURE_STRUCT = 0;

            // loop filter control register
            MfcSfr->MFC_LF_CONTROL = 1;
            MfcSfr->MFC_ENC_PIC_TYPE_CTRL = (1<<18)|(EncInitH263Arg->in_cfg.IDRPeriod);
            MfcSfr->MFC_ENC_REF_NUM_SEL = 0;
            MfcSfr->MPEG4_ENC_QUART_PXL = 0;

            // set shared memory area
            if(EncInitH263Arg->in_cfg.EnableFRMRateControl == 0){
                if(EncInitH263Arg->in_cfg.FrameQp_P <= 0){
                    LOG_MSG(LOG_WARNING, "[H263]", "FrameQp_P is invalid(lower than 1)...It sets as FrameQp+1(%d)\r\n", EncInitH263Arg->in_cfg.FrameQp+1);
                    EncInitH263Arg->in_cfg.FrameQp_P = EncInitH263Arg->in_cfg.FrameQp;
                }

                MfcShm->P_B_FRAME_QP = (EncInitH263Arg->in_cfg.FrameQp_P & 0x3F);
            }

            break;
        }

    case H264_ENC:
        {
            unsigned int profile;
            unsigned int NumOfRefsForP;

            LOG_MSG(LOG_DEBUG, "[H264]", "ProfileIDC : %d LevelIDC : %d \r\n", EncInitH264Arg->in_cfg.ProfileIDC, EncInitH264Arg->in_cfg.LevelIDC);
            LOG_MSG(LOG_DEBUG, "[H264]", "SliceMode : %d SliceArgument : %d \r\n", EncInitH264Arg->in_cfg.SliceMode, EncInitH264Arg->in_cfg.SliceArgument);
            LOG_MSG(LOG_DEBUG, "[H264]", "RandomIntraMBRefresh : %d NumberBFrames : %d \r\n", EncInitH264Arg->in_cfg.RandomIntraMBRefresh, EncInitH264Arg->in_cfg.NumberBFrames);
            LOG_MSG(LOG_DEBUG, "[H264]", "EnableFRMRateControl : %d EnableMBRateControl : %d \r\n", EncInitH264Arg->in_cfg.EnableFRMRateControl, EncInitH264Arg->in_cfg.EnableMBRateControl);
            LOG_MSG(LOG_DEBUG, "[H264]", "FrameRate : %d Bitrate : %d \r\n", EncInitH264Arg->in_cfg.FrameRate, EncInitH264Arg->in_cfg.Bitrate);
            LOG_MSG(LOG_DEBUG, "[H264]", "FrameQp : %d CBRPeriodRf : %d \r\n", EncInitH264Arg->in_cfg.FrameQp, EncInitH264Arg->in_cfg.CBRPeriodRf);
            LOG_MSG(LOG_DEBUG, "[H264]", "QSCodeMax : %d QSCodeMin : %d \r\n", EncInitH264Arg->in_cfg.QSCodeMax, EncInitH264Arg->in_cfg.QSCodeMin);
            LOG_MSG(LOG_DEBUG, "[H264]", "IDRPeriod : %d\r\n", EncInitH264Arg->in_cfg.IDRPeriod);
            
            //
            // common config value
            //            
            MfcSfr->MFC_HSIZE_PX = EncInitH264Arg->in_cfg.SourceWidth;
               
            if (EncInitH264Arg->in_cfg.PictureInterlace == 1)
                MfcSfr->MFC_VSIZE_PX = EncInitH264Arg->in_cfg.SourceHeight/2;
            else
               MfcSfr->MFC_VSIZE_PX = EncInitH264Arg->in_cfg.SourceHeight;

            // set registers related to multi-slice
            if (EncInitH264Arg->in_cfg.SliceMode == 0)
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = 0;

            }
            else if (EncInitH264Arg->in_cfg.SliceMode  == 1)	// fixed # mb in slice
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = (0<<1)|0x1;
                MfcSfr->MFC_ENC_MSLICE_MB = EncInitMpeg4Arg->in_cfg.SliceArgument;
            }
            else if (EncInitH264Arg->in_cfg.SliceMode  == 2)	// fixed # bytes in slice
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = (1<<1)|0x1;
                MfcSfr->MFC_ENC_MSLICE_BYTE = EncInitMpeg4Arg->in_cfg.SliceArgument;
            }
            else if (EncInitH264Arg->in_cfg.SliceMode  == 4)
            {
                MfcSfr->MFC_ENC_MSLICE_CTRL = 0x5;  // ox5 : multislicing is done by varriable MB count value , enable of resync marker or Multi slice
            }

                MfcSfr->MFC_ENC_CIR_NUM = EncInitH264Arg->in_cfg.RandomIntraMBRefresh;

            // rate control config.
            if(EncInitH264Arg->in_cfg.FrameQp <= 0 ){
                LOG_MSG(LOG_WARNING, "[H264]", "FrameQp is invalid(lower than 1)...It sets as default value(20)\r\n");
                EncInitH264Arg->in_cfg.FrameQp = 20;
            }
                
            MfcSfr->MFC_RC_CONFIG = ((EncInitH264Arg->in_cfg.EnableFRMRateControl<<9)|
                                    (EncInitH264Arg->in_cfg.EnableMBRateControl<<8)|
                                    (EncInitH264Arg->in_cfg.FrameQp<<0));

            // frame rate
            MfcSfr->MFC_RC_FRAME_RATE = EncInitH264Arg->in_cfg.FrameRate;


            // bit rate
            MfcSfr->MFC_RC_BIT_RATE = EncInitH264Arg->in_cfg.Bitrate;


            // Qunatization Parameter Boundary
            MfcSfr->MFC_RC_QBOUND = (EncInitH264Arg->in_cfg.QSCodeMax<<8)|(EncInitH264Arg->in_cfg.QSCodeMin<<0);

            // reaction coefficient
            if (EncInitH264Arg->in_cfg.EnableFRMRateControl == 1)
            {
                MfcSfr->MFC_RC_RPARA = EncInitH264Arg->in_cfg.CBRPeriodRf;
            }
            //
            //
            //
            profile = EncInitH264Arg->in_cfg.ProfileIDC;
            profile |= (1<<2);	// [3:2] = Chroma IDC (1 for encoding)
            profile |= (EncInitH264Arg->in_cfg.Transform8x8Mode << 4);	// [4] = 8x8 enable flag (don't-care for encoding)
            profile |= (EncInitH264Arg->in_cfg.LevelIDC << 8);		// [15:8] = level control		
            MfcSfr->MFC_PROFILE = profile;
            MfcSfr->MFC_PICTURE_STRUCT = EncInitH264Arg->in_cfg.PictureInterlace;

            MfcSfr->MFC_LF_CONTROL= EncInitH264Arg->in_cfg.LoopFilterDisable;

            // loop fileter alpha & beta offset registers
            MfcSfr->MFC_LF_ALPHA_OFF = EncInitH264Arg->in_cfg.LoopFilterAlphaC0Offset * 2;
            MfcSfr->MFC_LF_BETA_OFF= EncInitH264Arg->in_cfg.LoopFilterBetaOffset * 2;

            MfcSfr->MFC_ENC_PIC_TYPE_CTRL = (1<<18)|(EncInitH264Arg->in_cfg.NumberBFrames << 16)|(EncInitH264Arg->in_cfg.IDRPeriod);
            if (EncInitH264Arg->in_cfg.NumberReferenceFrames == 2)
                MfcSfr->MFC_ENC_REF_NUM_SEL = 1;
            else
                MfcSfr->MFC_ENC_REF_NUM_SEL = 0;
            
            MfcSfr->MFC_ENC_PADDIMG_CTRL = (EncInitH264Arg->in_cfg.PadControlOn<<31)
                                            |(EncInitH264Arg->in_cfg.CrPadVal<<16)
                                            |(EncInitH264Arg->in_cfg.CbPadVal<<8)
                                            |(EncInitH264Arg->in_cfg.LumaPadVal<<0);
            
            if (EncInitH264Arg->in_cfg.EnableMBRateControl == 1)
                MfcSfr->MFC_RC_MB_CTRL = (EncInitH264Arg->in_cfg.DarkDisable<<3)
                                            |(EncInitH264Arg->in_cfg.SmoothDisable<<2)
                                            |(EncInitH264Arg->in_cfg.StaticDisable<<1)
                                            |(EncInitH264Arg->in_cfg.ActivityDisable<<0);

            MfcSfr->H264_ENC_ENTRP_MODE = EncInitH264Arg->in_cfg.SymbolMode;

            // num. of ref.
            NumOfRefsForP = EncInitH264Arg->in_cfg.NumberRefForPframes;
            if (NumOfRefsForP > 2) 
            {
                NumOfRefsForP = 2;
            }
            if (NumOfRefsForP > EncInitH264Arg->in_cfg.NumberReferenceFrames)
            {
                NumOfRefsForP = EncInitH264Arg->in_cfg.NumberReferenceFrames;
            }

            MfcSfr->H264_ENC_NUM_OF_REF = (NumOfRefsForP<<5)|(EncInitH264Arg->in_cfg.NumberReferenceFrames);

            // active num. of ref.
            MfcSfr->H264_ENC_ACTIVE_NUM_OF_REF = (((EncInitH264Arg->in_cfg.NumberReferenceFrames-1)&0x1f)<<5)
                                                    |((EncInitH264Arg->in_cfg.NumberReferenceFrames-1)&0x1f);

            // inter weighted parameter
            MfcSfr->H264_ENC_MDINTER_WEIGHT = 0;

            // intra weighted parameter
            MfcSfr->H264_ENC_MDINTRA_WEIGHT = 0;

            //motion vector enable in intra
            MfcSfr->H264_ENC_INTRAMV_EN = 0;

            // direct mode???
            MfcSfr->H264_ENC_DIREC8X8_INF_FLAG = 0;

            // list0 field information
            MfcSfr->H264_ENC_LIST0_TOP_FIELD = 0; // 0 : frame mode

            // list1 field information
            MfcSfr->H264_ENC_LIST1_TOP_FIELD = 0; // 0 : frame mode

            // disable QpelME & halfpelME
            MfcSfr->MPEG4_ENC_QUART_PXL = 0;

            // 8x8 transform enable flag
            MfcSfr->H264_ENC_TRANS_8X8_FLAG = EncInitH264Arg->in_cfg.Transform8x8Mode;

            //MfcSfr->H264_ENC_I4X4_I8X8_WEIGHT = 0x3a280632; 
            //MfcSfr->H264_ENC_I16X16_WEIGHT = 0x1cc;
            //MfcSfr->H264_ENC_PRED_MODE_CONTROL = 0x7a; 

            // set shared memory area
            if(EncInitH264Arg->in_cfg.EnableFRMRateControl == 0){
                if(EncInitH264Arg->in_cfg.FrameQp_B <= 0){
                    LOG_MSG(LOG_WARNING, "[H264]", "FrameQp_B is invalid(lower than 1)...It sets as FrameQp+3(%d)\r\n", EncInitH264Arg->in_cfg.FrameQp+3);
                    EncInitH264Arg->in_cfg.FrameQp_B = EncInitH264Arg->in_cfg.FrameQp;
                }

                if(EncInitH264Arg->in_cfg.FrameQp_P <= 0){
                    LOG_MSG(LOG_WARNING, "[H264]", "FrameQp_P is invalid(lower than 1)...It sets as FrameQp+1(%d)\r\n", EncInitH264Arg->in_cfg.FrameQp+1);
                    EncInitH264Arg->in_cfg.FrameQp_P = EncInitH264Arg->in_cfg.FrameQp;
                }
                    
                MfcShm->P_B_FRAME_QP = ((EncInitH264Arg->in_cfg.FrameQp_B << 6) | (EncInitH264Arg->in_cfg.FrameQp_P & 0x3F));
            }
            
            break;
        }
       
    default:
        LOG_MSG(LOG_ERROR, "[SetEncodeInitParam] Invalid MFC codec type", "\r\n");
    }

    LOG_MSG(LOG_DEBUG, "SetEncodeInitParam--", "\r\n");

}


SSBSIP_MFC_ERROR_CODE MFCOpen()
{
    volatile MFC_SFR *MfcSfr;
    unsigned int StatusReg;

    LOG_MSG(LOG_WARNING, "MFCOpen++", "\r\n");

    MfcSfr = GetSfrVirAddr();
    //////////////////////////////////////////////
    // 0. Loading FW                            //
    //    - load & boot firmware                //
    //////////////////////////////////////////////
    memcpy(GetFWCodeBufVirAddr(),  mfc_fw,  sizeof(mfc_fw));

    
    //////////////////////////////////////////////
    // 1. MFC reset                             //
    //////////////////////////////////////////////
    MFC_CMD_RESET(MfcSfr);

    MfcSfr->MFC_SW_RESET = 0x3ff;
   
    LOG_MSG(LOG_TRACE, "MFC_CMD_RESET", "1. Loading Firmware\n");

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_FW_STATUS_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCOpen", "firmware loading is failed\n");
        return MFC_RET_OPEN_FAIL;
    }

    //////////////////////////////////////////////
    // 2. Initialize FW                         //
    //////////////////////////////////////////////
    LOG_MSG(LOG_TRACE, "MFCOpen", "2. Initialize Firmware\n");
    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_SYS_INIT, MFC_FIRMWARE_CODE_SIZE, 0, 0, 0);

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SYS_INIT_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCOpen", "firmware initialization is failed\n");
        return MFC_RET_OPEN_FAIL;
    }

    LOG_MSG(LOG_WARNING, "MFCOpen", "FirmwareVersion : %08x\n",  MfcSfr->MFC_FW_VERSION);

    //
    // need to add shared memory initialization
    //
    return MFC_RET_OK;
}




SSBSIP_MFC_ERROR_CODE MFCEncodeInit(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    volatile MFC_SFR *MfcSfr;
    unsigned int    codec_type;
    int ret;
    MFC_ENC_INIT_H264_ARG *InitArg;
    MFC_CODEC_COMM_ENC *EncCommSfr;
    unsigned int FWCtxBuffPhyAddr;

    LOG_MSG(LOG_DEBUG, "MFCEncodeInit++", "\r\n");
    MfcSfr = GetSfrVirAddr();
    EncCommSfr = &(MfcSfr->codec_comm);
    InitArg = (MFC_ENC_INIT_H264_ARG *)args;
    MfcCtx->MfcCodecType = InitArg->in_cfg.codecType;
    MfcSfr->MFC_ENC_INT_MASK = 0xf; 

    LOG_MSG(LOG_WARNING, "MFCEncodeInit", "InstNo : %d CodecType : %d\r\n", 
                                            MfcCtx->InstNo, MfcCtx->MfcCodecType);

    //////////////////////////////////////////////
    // 3. Open Instance                         //
    //    - set codec_type                      //
    //    - return channel ID                   //
    //////////////////////////////////////////////

    codec_type = GetMfcCodecType(MfcCtx->MfcCodecType);
    FWCtxBuffPhyAddr = (GetFWCtxBufPhyAddr(MfcCtx->InstNo) - GetDramAPhyBaseAddr())>>11;
    memset(GetSharedMemVirAddr(MfcCtx->InstNo), 0x00, MFC_DEC_SHARED_MEMORY_SIZE);
    EncCommSfr->MFC_SI_CH1_HOST_WR_ADR = GetSharedMemPhyAddr(MfcCtx->InstNo) - GetDramAPhyBaseAddr();
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "MFC_SI_CH1_HOST_WR_ADR: 0x%08x\n", EncCommSfr->MFC_SI_CH1_HOST_WR_ADR);
    MfcSfr->MFC_ENC_B_RECON_WRITE_ON = 1;

    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_OPEN_CH, codec_type, PIXEL_CACHE_ON, FWCtxBuffPhyAddr, MFC_FIRMWARE_INSTANCE_BUFF_SIZE);

    LOG_MSG(LOG_DEBUG, "MFCEncodeInit", "3. Open Instance(CtxAddr : 0x%08x)\n", FWCtxBuffPhyAddr);
    printf("ShmPhyMem : 0x%08x\n", GetSharedMemPhyAddr(MfcCtx->InstNo));

    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_OPEN_CH_RET)) == 0){
        LOG_MSG(LOG_ERROR, "MFCEncodeInit", "open_instance is failed\n");
        return MFC_RET_ENC_INIT_FAIL;
    }

    MfcCtx->ChID = MfcSfr->MFC_RISC2HOST_ARG1;
    LOG_MSG(LOG_DEBUG, "MFCEncodeInit", "MfcCtx->ChID : %d\n", MfcCtx->ChID);

    SetFWWorkingBuffer(MfcCtx);
    SetEncodeInitParam(MfcCtx, MfcSfr, codec_type, args);
    EncCommSfr->MFC_SI_RTN_CHID = 0xffff;
    
    LOG_MSG(LOG_DEBUG, "MFCEncodeInit", "in_Strm_St : 0x%08x in_Strm_End: 0x%08x\n", InitArg->in_Strm_St, InitArg->in_Strm_End);
    EncCommSfr->MFC_SI_CH1_SB_U_ADDR = ((Align(InitArg->in_Strm_St, 16*1024) - GetDramAPhyBaseAddr())>>11);
    EncCommSfr->MFC_SI_CH1_SB_L_ADDR = ((Align(InitArg->in_Strm_St, 16*1024) - GetDramAPhyBaseAddr())>>11);
    EncCommSfr->MFC_SI_CH1_SB_SIZE = InitArg->in_Strm_End - InitArg->in_Strm_St;

    MfcSfr->MFC_EDFU_STR_BF_U_EMPTY_0 = 1;
    MfcSfr->MFC_EDFU_STR_BF_L_EMPTY_0 = 1;

    if( (MfcSfr->MFC_EDFU_STR_BF_MODE_CTRL&0x1) == 0x1 )   // Stream Buffer Frame Mode
    {
        MfcSfr->MFC_EDFU_SF_BF_CTRL = (0x1<<1);	// buffer reset command
    }

    MFC_CMD_CODEC_ENC(EncCommSfr, MFC_CODEC_CMD_ENC_HEADER, MfcCtx->ChID);

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SEQ_DONE_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCEncodeInit", "header encoding is failed\n");
        return MFC_RET_ENC_INIT_FAIL;
    }
    EncCommSfr->MFC_SI_RTN_CHID = 0xffff; 

    LOG_MSG(LOG_DEBUG, "MFCEncodeInit", "Encoded Header Size : %d\r\n", EncCommSfr->MFC_SI_STREAM_SIZE);
    InitArg->out_header_size = EncCommSfr->MFC_SI_STREAM_SIZE;
    
    LOG_MSG(LOG_DEBUG, "MFCEncodeInit--", "\r\n");
    return MFC_RET_OK;
}


SSBSIP_MFC_ERROR_CODE MFCEncodeExe(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    volatile MFC_SFR *MfcSfr;
    MFC_CODEC_COMM_ENC *EncCommSfr;
    MFC_ENC_EXE_ARG *EncExeArg;
    MFC_SHARED_MEM *MfcShm;
    int ret;

    //////////////////////////////////////////////
    // 5. Encode Frame							//
    //////////////////////////////////////////////

    EncExeArg = (MFC_ENC_EXE_ARG *) args;
    LOG_MSG(LOG_DEBUG, "MFCEncodeExe++", "EncExeArg->in_Strm_St : 0x%08x EncExeArg->in_Strm_End :0x%08x \r\n", EncExeArg->in_Strm_St, EncExeArg->in_Strm_End);
    LOG_MSG(LOG_DEBUG, "MFCEncodeExe", "EncExeArg->in_Y_addr : 0x%08x EncExeArg->in_CbCr_addr :0x%08x \r\n", EncExeArg->in_Y_addr, EncExeArg->in_CbCr_addr);

    MfcSfr = GetSfrVirAddr();
    EncCommSfr = &(MfcSfr->codec_comm);

    EncCommSfr->MFC_SI_CH1_SB_U_ADDR = ((Align(EncExeArg->in_Strm_St, 16*1024) - GetDramAPhyBaseAddr())>>11);
    EncCommSfr->MFC_SI_CH1_SB_L_ADDR = ((Align(EncExeArg->in_Strm_St, 16*1024) - GetDramAPhyBaseAddr())>>11);
    EncCommSfr->MFC_SI_CH1_SB_SIZE = EncExeArg->in_Strm_End - EncExeArg->in_Strm_St;


    // current frame buffer address	
    EncCommSfr->MFC_SI_CH1_CURRENT_Y_ADDR = ((Align(EncExeArg->in_Y_addr, 16*1024) - GetDramBPhyBaseAddr())>>11);
    EncCommSfr->MFC_SI_CH1_CURRENT_C_ADDR = ((Align(EncExeArg->in_CbCr_addr, 16*1024) - GetDramBPhyBaseAddr())>>11);

    // force frame insertion
    if(MfcCtx->forceSetFrameType == I_FRAME){
        EncCommSfr->MFC_SI_CH1_FRAME_INSERT_TYPE = (1<<0);
        MfcCtx->forceSetFrameType = DONT_CARE;
    }
    else if(MfcCtx->forceSetFrameType == NOT_CODED){
        EncCommSfr->MFC_SI_CH1_FRAME_INSERT_TYPE = (1<<1);
        MfcCtx->forceSetFrameType = DONT_CARE;
    }else
        EncCommSfr->MFC_SI_CH1_FRAME_INSERT_TYPE = 0;
    
    MfcSfr->MFC_EDFU_STR_BF_U_EMPTY_0 = 1;
    MfcSfr->MFC_EDFU_STR_BF_L_EMPTY_0 = 1;

    if( (MfcSfr->MFC_EDFU_STR_BF_MODE_CTRL&0x1) == 0x1 )   // Stream Buffer Frame Mode
    {
        MfcSfr->MFC_EDFU_SF_BF_CTRL = (0x1<<1);	// buffer reset command
    }
    
    MFC_CMD_CODEC_ENC(EncCommSfr, MFC_CODEC_CMD_ENC_FRAME, MfcCtx->ChID);
    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_FRAME_DONE_RET)) == 0){
        LOG_MSG(LOG_ERROR, "MFCEncodeExe", "encoding frame is failed\n");
        return MFC_RET_ENC_EXE_ERR;
    }
    EncCommSfr->MFC_SI_RTN_CHID = 0xffff;

    EncExeArg->out_frameType = EncCommSfr->MFC_SI_SLICE_TYPE;
    EncExeArg->out_encoded_size = EncCommSfr->MFC_SI_STREAM_SIZE;
    EncExeArg->out_header_size  = 0;

    //memset(GetSharedMemVirAddr(MfcCtx->InstNo), 0x00, MFC_DEC_SHARED_MEMORY_SIZE);
    MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);

    // set shared memory area
    MfcShm->VOP_TIMING |= (MfcCtx->timeIncrement & 0xFFFF);
    MfcShm->ENC_PARAM_CHANGE = 0;
    MfcShm->NEW_RC_BIT_RATE = 0;
    MfcShm->NEW_RC_FRAME_RATE = 0;
    LOG_MSG(LOG_DEBUG, "MFCEncodeExe--", "frame type(%d) encodedSize(%d)\r\n", EncExeArg->out_frameType, EncExeArg->out_encoded_size);
    return MFC_RET_OK;
}



SSBSIP_MFC_ERROR_CODE MFCDecodeInit(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    volatile MFC_SFR *MfcSfr;
    SSBSIP_MFC_ERROR_CODE   ret;
    MFC_DEC_INIT_ARG *InitArg;
    MFC_CODEC_COMM_DEC *DecCommSfr;
    unsigned int AlignedWidth, AlignedYHeight, AlignedCbHeight, AlignedMVHeight;
    unsigned int FWCtxBuffPhyAddr;

    LOG_MSG(LOG_DEBUG, "MFCDecodeInit++", "\r\n");
    InitArg = (MFC_DEC_INIT_ARG *)args;
    MfcSfr = GetSfrVirAddr();
    DecCommSfr = &(MfcSfr->codec_comm);

    // Context setting from input param
    MfcCtx->MfcCodecType = InitArg->in_codecType;
    MfcCtx->IsPackedPB = InitArg->in_packedPB;

    LOG_MSG(LOG_WARNING, "MFCDecodeInit", "InstNo : %d CodecType : %d MfcCtx->packedPB : %d CRCEnable : %d \r\n", 
                MfcCtx->InstNo, MfcCtx->MfcCodecType, MfcCtx->IsPackedPB, MfcCtx->CrcEnable);

    LOG_MSG(LOG_WARNING, "MFCDecodeInit", "GetDramAPhyBaseAddr : 0x%08x GetDramBPhyBaseAddr : 0x%08x \r\n", 
                GetDramAPhyBaseAddr(), GetDramBPhyBaseAddr());

    //////////////////////////////////////////////
    // 3. Open Instance                         //
    //    - set codec_type                      //
    //    - return channel ID                   //
    //////////////////////////////////////////////
    
    FWCtxBuffPhyAddr = (GetFWCtxBufPhyAddr(MfcCtx->InstNo) - GetDramAPhyBaseAddr())>>11;
    memset(GetSharedMemVirAddr(MfcCtx->InstNo), 0x00, MFC_DEC_SHARED_MEMORY_SIZE);
    DecCommSfr->MFC_SI_CH1_HOST_WR_ADR = GetSharedMemPhyAddr(MfcCtx->InstNo) - GetDramAPhyBaseAddr();
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "MFC_SI_CH1_HOST_WR_ADR: 0x%08x\n", DecCommSfr->MFC_SI_CH1_HOST_WR_ADR);

    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_OPEN_CH, GetMfcCodecType(MfcCtx->MfcCodecType), PIXEL_CACHE_ON|(MfcCtx->CrcEnable<<CRC_GENERATION_BIT), FWCtxBuffPhyAddr, MFC_FIRMWARE_INSTANCE_BUFF_SIZE);

    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "3. Open Instance(CtxAddr : 0x%08x)\n", FWCtxBuffPhyAddr);

    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_OPEN_CH_RET)) == 0){
        LOG_MSG(LOG_ERROR, "MFCDecodeInit", "open_instance is failed\n");
        return MFC_RET_DEC_INIT_FAIL;
    }

    MfcCtx->ChID = MfcSfr->MFC_RISC2HOST_ARG1;
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "MfcCtx->ChID : %d\n", MfcCtx->ChID);

    //////////////////////////////////////////////
    // 4. Header Parsing                        //
    //    - set post filter, pixelCache         //
    //    - set Input Stream buffer             //
    //    - set NUM_EXTRA_DPB                   //
    //////////////////////////////////////////////

    MfcSfr->MFC_LF_CONTROL = MfcCtx->postEnable;
    SetDecStreamBuffer(MfcCtx, InitArg->in_strmBuf, InitArg->in_strmSize, 0);

    DecCommSfr->MFC_SI_CH1_DPB_CONFIG_CTRL = 0;  
    if(MfcCtx->SliceEnable)
        DecCommSfr->MFC_SI_CH1_DPB_CONFIG_CTRL |= ENABLE_SLICE_BASED_IF;
    if(MfcCtx->displayDelay < 16)
        DecCommSfr->MFC_SI_CH1_DPB_CONFIG_CTRL |= (ENABLE_H264_DISPLAY_DELAY|(MfcCtx->displayDelay << 16)); 
    
    LOG_MSG(LOG_WARNING, "MFCDecodeInit", "4. Header Parsing(DisplayDelay : %d)\n", MfcCtx->displayDelay);
    
    MFC_CMD_CODEC_DEC(DecCommSfr, MFC_CODEC_CMD_DEC_HEADER, MfcCtx->ChID);

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_SEQ_DONE_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCDecodeInit", "header decoding is failed\n");
        return MFC_RET_DEC_INIT_FAIL;
    }
    DecCommSfr->MFC_SI_RTN_CHID = 0xffff;
    MfcCtx->img_width = DecCommSfr->MFC_SI_HRESOL;
    MfcCtx->img_height = DecCommSfr->MFC_SI_VRESOL;

    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "img_width : %d img_height : %d\n", MfcCtx->img_width, MfcCtx->img_height);

    InitArg->out_img_width = MfcCtx->img_width;
    InitArg->out_img_height = MfcCtx->img_height;


    // calculate DPB size
    LOG_MSG(LOG_WARNING, "MFCDecodeInit", "MfcSfr->DPB_CNT:%d MfcCtx->extraDPB: %d\r\n", DecCommSfr->MFC_SI_BUF_NUMBER, MfcCtx->extraDPB);
    MfcCtx->DPBCnt = (DecCommSfr->MFC_SI_BUF_NUMBER + MfcCtx->extraDPB);

    AlignedWidth = Align(MfcCtx->img_width, 128);
    AlignedYHeight = Align(MfcCtx->img_height, 32);
    AlignedCbHeight = Align(MfcCtx->img_height/2, 32);
    AlignedMVHeight = Align(MfcCtx->img_height/4, 32);
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "AlignedWidth : %d AlignedYHeight : %d\n", AlignedWidth, AlignedYHeight);
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "AlignedCbHeight : %d AlignedMVHeight : %d\n", AlignedCbHeight, AlignedMVHeight);

/*
    InitArg->out_buf_width = AlignedWidth;
    InitArg->out_buf_height = AlignedYHeight;
*/
    InitArg->out_buf_width = Align(MfcCtx->img_width, 16);
    InitArg->out_buf_height = Align(MfcCtx->img_height, 16);
    
    MfcCtx->YSize = Align(AlignedWidth*AlignedYHeight, 64*1024);
    MfcCtx->CbSize = Align(AlignedWidth*AlignedCbHeight, 64*1024);
    
    if(MfcCtx->MfcCodecType == H264_DEC){
        MfcCtx->MVSize = Align(AlignedWidth*AlignedMVHeight, 64*1024);
        InitArg->out_dpb_y_size = (MfcCtx->YSize + MfcCtx->MVSize)*MfcCtx->DPBCnt;
        InitArg->out_dpb_cb_size = MfcCtx->CbSize*MfcCtx->DPBCnt;
    }
    else{
        InitArg->out_dpb_y_size = MfcCtx->YSize*MfcCtx->DPBCnt;
        InitArg->out_dpb_cb_size = MfcCtx->CbSize*MfcCtx->DPBCnt;
    }

    MfcCtx->DPBSize = InitArg->out_dpb_y_size + InitArg->out_dpb_cb_size;

       
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit", "MfcCtx->DPBSize : 0x%x \n", MfcCtx->DPBSize);
    LOG_MSG(LOG_DEBUG, "MFCDecodeInit--", "\r\n");
    return MFC_RET_OK;
}

SSBSIP_MFC_ERROR_CODE MFCDecodeBufferInit(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    MFC_DEC_BUFFER_INIT_ARG *Arg;
    volatile MFC_SFR *MfcSfr;
    MFC_CODEC_COMM_DEC *DecCommSfr;
    
    LOG_MSG(LOG_DEBUG, "MFCDecodeBufferInit++", "\r\n");

    MfcSfr = GetSfrVirAddr();
    DecCommSfr = &(MfcSfr->codec_comm);
    Arg = (MFC_DEC_BUFFER_INIT_ARG *)args;

    
    //////////////////////////////////////////////
    // 5. Set Codec & DPB Buffer                 //
    //////////////////////////////////////////////
    LOG_MSG(LOG_WARNING, "MFCDecodeBufferInit", "5. Set Codec & DPB Buffer(MfcCtx->DPBCnt : %d)\n", MfcCtx->DPBCnt);
    SetFWWorkingBuffer(MfcCtx);
    
    SetDecFrameBuffer(MfcCtx, (MFC_DEC_EXE_ARG *)Arg);
    
    DecCommSfr->MFC_SI_CH1_DPB_CONFIG_CTRL |= (0x3fff & MfcCtx->DPBCnt); 
 
    MFC_CMD_CODEC_DEC(DecCommSfr, MFC_CODEC_CMD_DEC_INIT_BUFF, MfcCtx->ChID);

    if(WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_INIT_BUFFER_RET) == 0){
        LOG_MSG(LOG_ERROR, "MFCDecodeBufferInit", "buffer_init is failed\n");
        return MFC_RET_DEC_INIT_FAIL;
    }
    DecCommSfr->MFC_SI_RTN_CHID = 0xffff;
    LOG_MSG(LOG_DEBUG, "MFCDecodeBufferInit--", "\r\n");
    
    return MFC_RET_OK;
    
}
static SSBSIP_MFC_ERROR_CODE DecodeOneFrame(MFC_INST_CTX  *MfcCtx,  MFC_DEC_EXE_ARG *DecArg, unsigned int startByteNum, unsigned int *consumedStrmSize)
{
    volatile MFC_SFR *MfcSfr;
    MFC_CODEC_COMM_DEC *DecCommSfr;
    int ret;


    LOG_MSG(LOG_DEBUG, "MFCDecodeOneFrame++", "IntNo%d  in_strmSize: %d \r\n", MfcCtx->InstNo, DecArg->in_strmSize);


    MfcSfr = GetSfrVirAddr();

    DecCommSfr = &(MfcSfr->codec_comm);

    SetDecStreamBuffer(MfcCtx, DecArg->in_strmBuf, DecArg->in_strmSize, startByteNum);
    SetDecFrameBuffer(MfcCtx, DecArg);
    DecCommSfr->MFC_SI_CH1_RELEASE_BUFFER = 0xffffffff;

    if(MfcCtx->endOfFrame){
        LOG_MSG(LOG_WARNING, "MFCDecodeOneFrame", "MfcCtx->endOfFrame = 1\n");
        MFC_CMD_CODEC_DEC(DecCommSfr, MFC_CODEC_CMD_DEC_LAST_FRAME, MfcCtx->ChID);
        MfcCtx->endOfFrame = 0;
    }
    else{
        MFC_CMD_CODEC_DEC(DecCommSfr, MFC_CODEC_CMD_DEC_FRAME, MfcCtx->ChID);
    }

    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_FRAME_DONE_RET)) == 0){
        LOG_MSG(LOG_ERROR, "MFCDecodeOneFrame", "decoding frame is failed\n");
        return MFC_RET_DEC_EXE_ERR;
    }
    DecCommSfr->MFC_SI_RTN_CHID = 0xffff;

    
    DecArg->out_displayStatus = DecCommSfr->MFC_SI_DISPLAY_STATUS & 0x3;
    DecArg->out_res_change = (DecCommSfr->MFC_SI_DISPLAY_STATUS >> 4) & 0x3;
    DecArg->out_consumedByte = DecCommSfr->MFC_DEC_FRM_SIZE;
    *consumedStrmSize = DecCommSfr->MFC_DEC_FRM_SIZE;
    MfcCtx->FrameType = (DecCommSfr->MFC_COMMON_SI_RG_8 & 0x7);
   
    if((DecArg->out_displayStatus == DECODING_ONLY) || (DecArg->out_displayStatus == DISPLAY_END)){  // decoding only
        DecArg->out_displayYAddr = 0;
        DecArg->out_displayCAddr = 0;
    }
    else{
        DecArg->out_displayYAddr = DecCommSfr->MFC_SI_DISPLAY_Y_ADR << 11;
        DecArg->out_displayCAddr = DecCommSfr->MFC_SI_DISPLAY_C_ADR << 11;

    }

    if(DecCommSfr->MFC_SI_DISPLAY_STATUS & 0x4 == MFC_INTERLACED_FRAME){
        LOG_MSG(LOG_DEBUG, "MFCDecodeOneFrame", "MFC_INTERLACED_FRAME\r\n");
    }
    else{
        DecArg->out_timestampTop = 0;
        DecArg->out_timestampBottom = 0;        
    }
    
    LOG_MSG(LOG_DEBUG, "MFCDecodeOneFrame", "(Y_ADDR : 0x%08x  C_ADDR : 0x%08x)\r\n", DecArg->out_displayYAddr , DecArg->out_displayCAddr);  
    LOG_MSG(LOG_DEBUG, "MFCDecodeOneFrame--", "\r\n");
    
    return MFC_RET_OK;
}


SSBSIP_MFC_ERROR_CODE MFCDecodeExe(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    SSBSIP_MFC_ERROR_CODE ret;
    MFC_DEC_EXE_ARG *DecArg;
    unsigned int consumedStrmSize;
    static int count = 0;
    unsigned int startByteNum;

    //////////////////////////////////////////////
    // 6. Decode Frame                          //
    //////////////////////////////////////////////
    LOG_MSG(LOG_DEBUG, "MFCDecodeExe++", "\r\n");

    DecArg = (MFC_DEC_EXE_ARG *)args;
    startByteNum = 0;
    ret = DecodeOneFrame(MfcCtx,  DecArg, startByteNum, &consumedStrmSize);

    if((MfcCtx->IsPackedPB) && (MfcCtx->FrameType == MFC_RET_FRAME_P_FRAME) && (DecArg->in_strmSize - consumedStrmSize > 4)){
        LOG_MSG(LOG_DEBUG, "MFCDecodeExe", "Packed PB\n");
        startByteNum = (DecArg->in_strmBuf + consumedStrmSize) % 4096;
        DecArg->in_strmBuf += consumedStrmSize;
        DecArg->in_strmSize -= consumedStrmSize;

        ret = DecodeOneFrame(MfcCtx,  DecArg, startByteNum, &consumedStrmSize);
    }

    LOG_MSG(LOG_DEBUG, "MFCDecodeExe--", "\r\n");

    return ret; 
}

SSBSIP_MFC_ERROR_CODE MFCClose(MFC_INST_CTX  *MfcCtx)
{
    volatile MFC_SFR *MfcSfr;
    SSBSIP_MFC_ERROR_CODE ret;

    LOG_MSG(LOG_WARNING, "MFCClose", "\r\n");
    MfcSfr = GetSfrVirAddr();
    MFC_CMD_HOST2RISC(MfcSfr, MFC_H2R_CMD_CLOSE_CH, MfcCtx->ChID, 0, 0, 0);
    MfcSfr->MFC_ENC_INT_MASK = 0x0;
    
    if((ret = WaitForDone(MFC_WAIT_DONE_INTR, MFC_R2H_CMD_CLOSE_CH_RET)) == 0){
        LOG_MSG(LOG_ERROR, "MFCClose", "closing is failed\n");
        return MFC_RET_CLOSE_FAIL;
    }
    return MFC_RET_OK;

}

SSBSIP_MFC_ERROR_CODE MFCGetConfig(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    MFC_GET_CONFIG_ARG *GetCnfArg;
    volatile MFC_SFR *MfcSfr;
    MFC_CODEC_COMM_DEC *DecCommSfr;

    GetCnfArg = (MFC_GET_CONFIG_ARG *)args;
    GetCnfArg->out_config_value[0] = 0;
    
    MfcSfr = GetSfrVirAddr();
    DecCommSfr = &(MfcSfr->codec_comm);
    
    switch(GetCnfArg->in_config_param){
        case MFC_DEC_GETCONF_CRC_DATA:
            {
                if(MfcCtx->MfcState != MFCINST_STATE_DEC_EXE){
                    LOG_MSG(LOG_ERROR, "MFCGetConfig", "MFC_DEC_GETCONF_CRC_DATA : state is invalid\n");
                    return MFC_RET_DEC_GET_CONF_FAIL;
                }
                
                if((DecCommSfr->MFC_SI_DECODE_STATUS & 0x20) == 0x20){
                    if((DecCommSfr->MFC_SI_DECODE_STATUS & 0x10) == 0x10){ // the number of CRC is 4
                        GetCnfArg->out_config_value[0] = 4;
                        GetCnfArg->out_config_value[1] = DecCommSfr->MFC_SI_CRC_DATA_1;
                        GetCnfArg->out_config_value[2] = DecCommSfr->MFC_SI_CRC_DATA_2;
                        GetCnfArg->out_config_value[3] = DecCommSfr->MFC_SI_CRC_DATA_3;
                        GetCnfArg->out_config_value[4] = DecCommSfr->MFC_SI_CRC_DATA_4;
                    }
                    else{                                                  // the number of CRC is 2
                        GetCnfArg->out_config_value[0] = 2;
                        GetCnfArg->out_config_value[1] = DecCommSfr->MFC_SI_CRC_DATA_1;
                        GetCnfArg->out_config_value[2] = DecCommSfr->MFC_SI_CRC_DATA_2;
                    }                   
                }

                break;
            }
        }
    return MFC_RET_OK;
}


SSBSIP_MFC_ERROR_CODE MFCSetConfig(MFC_INST_CTX  *MfcCtx,  ARGS *args)
{
    MFC_SET_CONFIG_ARG *SetCnfArg;
    MFC_SHARED_MEM *MfcShm;

    SetCnfArg = (MFC_SET_CONFIG_ARG *)args;

    switch(SetCnfArg->in_config_param){
        case MFC_DEC_SETCONF_POST_ENABLE:
            {
                if(MfcCtx->MfcState >= MFCINST_STATE_DEC_INITIALIZE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_POST_ENABLE : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }
                
                if((SetCnfArg->in_config_value[0] == 0) || (SetCnfArg->in_config_value[0] == 1))
                    MfcCtx->postEnable = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "POST_ENABL should be 0 or 1...It will be set 0 by default\n");
                    MfcCtx->postEnable = 0;
                }
                break;
            }
        case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
            {
                if(MfcCtx->MfcState >= MFCINST_STATE_DEC_INITIALIZE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_EXTRA_BUFFER_NUM : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }
                
                if((SetCnfArg->in_config_value[0] >= 0) || (SetCnfArg->in_config_value[0] <= MFC_MAX_EXTRA_DPB))
                    MfcCtx->extraDPB = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "EXTRA_BUFFER_NUM should be between 0 and 5...It will be set 5 by default\n");
                    MfcCtx->extraDPB = MFC_MAX_EXTRA_DPB;
                }
                break;
            }
        case MFC_DEC_SETCONF_DISPLAY_DELAY:
            {
                if(MfcCtx->MfcState >= MFCINST_STATE_DEC_INITIALIZE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_DISPLAY_DELAY : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }

                if((SetCnfArg->in_config_value[0] >= 0) || (SetCnfArg->in_config_value[0] <= 16))
                    MfcCtx->displayDelay = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "DISPLAY_DELAY should be between 0 and 16\n");
                    MfcCtx->displayDelay = 0;
                }

                break;
            }
        case MFC_DEC_SETCONF_IS_LAST_FRAME:
            {
                if(MfcCtx->MfcState != MFCINST_STATE_DEC_EXE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_IS_LAST_FRAME : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }

                if((SetCnfArg->in_config_value[0] == 0) || (SetCnfArg->in_config_value[0] == 1))
                    MfcCtx->endOfFrame = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "IS_LAST_FRAME should be 0 or 1\n");
                    MfcCtx->endOfFrame = 0;
                }
                break;
            }
        case MFC_DEC_SETCONF_SLICE_ENABLE:
            {
                if(MfcCtx->MfcState >= MFCINST_STATE_DEC_INITIALIZE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_SLICE_ENABLE : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }

                if((SetCnfArg->in_config_value[0] == 0) || (SetCnfArg->in_config_value[0] == 1))
                    MfcCtx->SliceEnable = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "MFC_DEC_SETCONF_SLICE_ENABLE should be 0 or 1\n");
                    MfcCtx->SliceEnable = 16;
                }
                break;
            }
        case MFC_DEC_SETCONF_CRC_ENABLE:
            {
                if(MfcCtx->MfcState >= MFCINST_STATE_DEC_INITIALIZE){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_DEC_SETCONF_CRC_ENABLE : state is invalid\n");
                    return MFC_RET_DEC_SET_CONF_FAIL;
                }

                if((SetCnfArg->in_config_value[0] == 0) || (SetCnfArg->in_config_value[0] == 1))
                    MfcCtx->CrcEnable = SetCnfArg->in_config_value[0];
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "MFC_DEC_SETCONF_CRC_ENABLE should be 0 or 1\n");
                    MfcCtx->CrcEnable = 0;
                }
                break;
            }
        case MFC_ENC_SETCONF_FRAME_TYPE:
            {
                if((MfcCtx->MfcState < MFCINST_STATE_ENC_INITIALIZE) || (MfcCtx->MfcState > MFCINST_STATE_ENC_EXE)){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
                    return MFC_RET_ENC_SET_CONF_FAIL;
                }

                if((SetCnfArg->in_config_value[0] < DONT_CARE) && (SetCnfArg->in_config_value[0] > NOT_CODED)){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "FRAME_TYPE should be between 0 and 2\n");
                    MfcCtx->forceSetFrameType = DONT_CARE;    
                }
                else{
                    MfcCtx->forceSetFrameType = SetCnfArg->in_config_value[0];
                }
                break;
            }
        
        case MFC_ENC_SETCONF_CHANGE_FRAME_RATE :
            {
                if((MfcCtx->MfcState < MFCINST_STATE_ENC_INITIALIZE) || (MfcCtx->MfcState > MFCINST_STATE_ENC_EXE)){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_ENC_SETCONF_CHANGE_FRAME_RATE : state is invalid\n");
                    return MFC_RET_ENC_SET_CONF_FAIL;
                }

                if(SetCnfArg->in_config_value[0] > 0){
                    printf("frame rate : %d\n", SetCnfArg->in_config_value[0]);
                    MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);
                    MfcShm->ENC_PARAM_CHANGE = RC_CHANGE_ENABLE_FRAME_RATE;
                    MfcShm->NEW_RC_FRAME_RATE = SetCnfArg->in_config_value[0];
                    MfcShm->VOP_TIMING = ((1<<31)|(SetCnfArg->in_config_value[0] << 16)|(0 & 0xFFFF));
                    MfcCtx->timeIncrement = 1;

                }
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "FRAME_RATE should be biger than 0\n");
                }
                break;
            }
        
        case MFC_ENC_SETCONF_CHANGE_BIT_RATE : 
            {
                if((MfcCtx->MfcState < MFCINST_STATE_ENC_INITIALIZE) || (MfcCtx->MfcState > MFCINST_STATE_ENC_EXE)){
                    LOG_MSG(LOG_ERROR, "MFCSetConfig", "MFC_ENC_SETCONF_CHANGE_BIT_RATE : state is invalid\n");
                    return MFC_RET_ENC_SET_CONF_FAIL;
                }

                if(SetCnfArg->in_config_value[0] > 0){
                    printf("bit rate : %d\n", SetCnfArg->in_config_value[0]);
                    MfcShm = (MFC_SHARED_MEM *)GetSharedMemVirAddr(MfcCtx->InstNo);
                    MfcShm->ENC_PARAM_CHANGE = RC_CHANGE_ENABLE_BIT_RATE;
                    MfcShm->NEW_RC_BIT_RATE = SetCnfArg->in_config_value[0];
                }
                else{
                    LOG_MSG(LOG_WARNING, "MFCSetConfig", "BIT_RATE should be biger than 0\n");
                }
                break;
            }
        
        default:
            LOG_MSG(LOG_ERROR, "MFCSetConfig", "invalid config param\n");
            return MFC_RET_FAIL;
    }

    return MFC_RET_OK;
}




