Exemple #1
0
/*
** Function Name : MFC_Open
**
** Function Description : This function open MFC instace and return instance handle.
*/
DWORD
MFC_Open(
    DWORD InitHandle,
    DWORD dwAccess,
    DWORD dwShareMode
    )
{
    MFC_HANDLE   *handle;

    // Mutex Lock
    MFC_Mutex_Lock();

    // Allocate & Clear MFC Handle
    handle = (MFC_HANDLE *) malloc(sizeof(MFC_HANDLE));
    if (!handle)
    {
        RETAILMSG(1, (L"\n[MFC_Open Error] Momory Allocation Fail.\n"));
        MFC_Mutex_Release();
        return 0;
    }
    memset(handle, 0, sizeof(MFC_HANDLE));

    // Increment OpenHandle Count
    InterlockedIncrement(&_openhandle_count);

    //
    if (_openhandle_count == 1) // Handle for Power Control
    {
        // Save Specific Handle for Power Control
        gMfcHandlePower = handle;
        RETAILMSG(1, (L"\n[MFC_Open] Power Manager Handle Opened...\n"));
    }
    else if (_openhandle_count >= 2) // Handle for User Application
    {
        // Create MFC Instance
        handle->mfc_inst = MFCInst_Create();
        if (!handle->mfc_inst)
        {
            RETAILMSG(1, (L"\n[MFC_Open Error] MFC Instance Creattion Fail.\n"));
            InterlockedDecrement(&_openhandle_count);
            free(handle);
            MFC_Mutex_Release();
            return 0;
        }

        if (_openhandle_count == 2) // First Handle for User Application
        {
            // MFC HW Init
            Mfc_Pwr_On();
            Mfc_Clk_On();

            if (MFC_HW_Init() == FALSE)
            {
                Mfc_Clk_Off();
                Mfc_Pwr_Off();
                MFCInst_Delete(handle->mfc_inst);
                InterlockedDecrement(&_openhandle_count);
                MFC_Mutex_Release();
                return 0;
            }
            Mfc_Clk_Off();
        }
    }

    // Mutex Release
    MFC_Mutex_Release();

    return (DWORD) handle;
}
Exemple #2
0
/*
** Function Name : MFC_IOControl
**
** Function Description : This function support any process of MFC instance.
*/
BOOL
MFC_IOControl(
    DWORD OpenHandle,
    DWORD dwIoControlCode,
    PBYTE pInBuf,
    DWORD nInBufSize,
    PBYTE pOutBuf,
    DWORD nOutBufSize,
    PDWORD pBytesReturned
    )
{
    MFC_HANDLE  *handle;
    MFCInstCtx     *pMfcInst;
    MFC_ARGS      *args;

    int ret                       = MFCINST_RET_OK;
    unsigned char  *p_buf         = NULL;
    int n_bufsize                 = 0;
    PVOID pMarshalledInBuf        = NULL;
    static CEDEVICE_POWER_STATE   mfc_pwr_state;
  
    BOOL    result = TRUE;

    handle = (MFC_HANDLE *) OpenHandle;

    /////////////////////
    // Parameter Check //
    /////////////////////
    if (handle == NULL)
    {
        LOG_MSG(LOG_TRACE, "MFC_IOControl", "OpenHandle == NULL\n");
        return FALSE;
    }

    if (handle != gMfcHandlePower)
    {
        if (pInBuf == NULL)
        {
            LOG_MSG(LOG_TRACE, "MFC_IOControl", "pInBuf == NULL\n");
            return FALSE;
        }
        if (nInBufSize == 0)
        {
            LOG_MSG(LOG_TRACE, "MFC_IOControl", "nInBufSize == 0\n");
            return FALSE;
        }

        if ((pOutBuf != NULL) || (nOutBufSize != 0) || (pBytesReturned != NULL))
        {
            LOG_MSG(LOG_TRACE, "MFC_IOControl", "others.....\n");
            return FALSE;
        }
    }

    pMfcInst = handle->mfc_inst;

    MFC_Mutex_Lock();

    switch ( dwIoControlCode )
    {
    case IOCTL_POWER_CAPABILITIES:
        {
            RETAILMSG(1, (L"[MFC IOCTL_POWER_CAPABILITIES]\n"));

            PPOWER_CAPABILITIES ppc;

            if ( !pBytesReturned || !pOutBuf || (nOutBufSize < sizeof(POWER_CAPABILITIES)) ) {
                SetLastError (ERROR_INVALID_PARAMETER);
                MFC_Mutex_Release();
                return FALSE;
            }
            
            __try
            {
                ppc = (PPOWER_CAPABILITIES)pOutBuf;
                memset(ppc, 0, sizeof(POWER_CAPABILITIES));

                // support D0, D4
                ppc->DeviceDx = DX_MASK(D0) | DX_MASK(D4);

                // no wake
                // no inrush

                // Report our nominal power consumption in uAmps rather than mWatts.
                ppc->Flags = POWER_CAP_PREFIX_MICRO | POWER_CAP_UNIT_AMPS;

                *pBytesReturned = sizeof(POWER_CAPABILITIES);

                RETAILMSG(1, (L"[MFC IOCTL_POWER_CAPABILITIES] leaving...\n"));
            }
            __except(EXCEPTION_EXECUTE_HANDLER)
            {
                RETAILMSG(1, (L"[MFC IOCTL_POWER_CAPABILITIES] exception...\n"));
                MFC_Mutex_Release();
                return FALSE;
            }
            break;
        }

    case IOCTL_POWER_SET:
        CEDEVICE_POWER_STATE NewDx;

        //if caller is not kernel mode, do not allow setting power state
        if (GetDirectCallerProcessId() != GetCurrentProcessId())
        {
            RETAILMSG(1, (L"[MFC IOCTL_POWER_SET] User mode access denied\r\n"));
            MFC_Mutex_Release();
            return ERROR_ACCESS_DENIED;
        }

        __try
        {
            if (pOutBuf == NULL)
            {
                return FALSE;
            }
            
            NewDx = *(PCEDEVICE_POWER_STATE) pOutBuf;
            switch ( NewDx )
            {
            case D0:    // Power Up
                    *(PCEDEVICE_POWER_STATE)pOutBuf = process_MFC_PowerUp(OpenHandle, &mfc_pwr_state);
                break;

            case D4:    // Power Down
                    *(PCEDEVICE_POWER_STATE)pOutBuf = process_MFC_PowerDown(OpenHandle, &mfc_pwr_state);
                break;

            default:
                MFC_Mutex_Release();
                return FALSE;
            }

            *pBytesReturned = sizeof(CEDEVICE_POWER_STATE);
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            RETAILMSG(1, (L"[MFC IOCTL_POWER_SET] exception...\n"));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;

    case IOCTL_MFC_MPEG4_ENC_INIT:
    case IOCTL_MFC_H264_ENC_INIT:
    case IOCTL_MFC_H263_ENC_INIT:
        {
            MFC_CODECMODE   codec_mode;
            enc_info_t      enc_info;

            if (dwIoControlCode == IOCTL_MFC_MPEG4_ENC_INIT)
                codec_mode = MP4_ENC;
            else if (dwIoControlCode == IOCTL_MFC_H264_ENC_INIT)
                codec_mode = AVC_ENC;
            else
                codec_mode = H263_ENC;

            if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_H263_ENC_INIT.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            args = (MFC_ARGS *)pMarshalledInBuf;

            // Input arguments for IOCTL_MFC_xxx_ENC_INIT
            enc_info.width        = args->enc_init.in_width;
            enc_info.height        = args->enc_init.in_height;
            enc_info.frameRateRes    = args->enc_init.in_frameRateRes;
            enc_info.frameRateDiv    = args->enc_init.in_frameRateDiv;
            enc_info.gopNum        = args->enc_init.in_gopNum;
            enc_info.bitrate        = args->enc_init.in_bitrate;

            enc_info.intraqp        = args->enc_init.in_intraqp;
            enc_info.qpmax        = args->enc_init.in_qpmax;
            enc_info.gamma        = args->enc_init.in_gamma;

            ///////////////////////////////////
            ///   Initialize MFC Instance   ///
            ///////////////////////////////////
            Mfc_Clk_On();
            ret = MFCInst_Enc_Init(pMfcInst, codec_mode, &enc_info);
            Mfc_Clk_Off();

            // Output arguments for IOCTL_MFC_xxx_ENC_INIT
            args->enc_init.ret_code = ret;

            if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_H263_ENC_INIT.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            break;
        }

    case IOCTL_MFC_MPEG4_ENC_EXE:
    case IOCTL_MFC_H264_ENC_EXE:
    case IOCTL_MFC_H263_ENC_EXE:
        {
            int nStrmLen, nHdrLen;
            if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_H263_ENC_EXE.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            args = (MFC_ARGS *)pMarshalledInBuf;
            MFCInst_GetFramBuf(pMfcInst, &p_buf, &n_bufsize);
            CleanInvalidateCacheRange((PBYTE )p_buf, (PBYTE )(p_buf + n_bufsize) );
            
            // nStrmLen is size of output stream data
            Mfc_Clk_On();
            ret = MFCInst_Encode(pMfcInst, &nStrmLen, &nHdrLen);
            Mfc_Clk_Off();

            MFCInst_GetLineBuf(pMfcInst, &p_buf, &n_bufsize);
            InvalidateCacheRange((PBYTE )p_buf, (PBYTE )(p_buf + n_bufsize) );
        
            // Output arguments for IOCTL_MFC_xxx_ENC_EXE
            args->enc_exe.ret_code = ret;
            if (ret == MFCINST_RET_OK) {
                args->enc_exe.out_encoded_size = nStrmLen;
                args->enc_exe.out_header_size  = nHdrLen;
            }

            if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_H263_ENC_EXE.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            break;
        }

    case IOCTL_MFC_MPEG4_DEC_INIT:
    case IOCTL_MFC_H263_DEC_INIT:
    case IOCTL_MFC_H264_DEC_INIT:
    case IOCTL_MFC_VC1_DEC_INIT:
        {
            MFC_CODECMODE   codec_mode;

            if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_VC1_DEC_INIT.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            args = (MFC_ARGS *)pMarshalledInBuf;

            if (dwIoControlCode == IOCTL_MFC_MPEG4_DEC_INIT) {
                codec_mode = MP4_DEC;
            }
            else if (dwIoControlCode == IOCTL_MFC_H263_DEC_INIT) {
                codec_mode = MP4_DEC;
            }
            else if (dwIoControlCode == IOCTL_MFC_H264_DEC_INIT) {
                codec_mode = AVC_DEC;
            }
            else {
                codec_mode = VC1_DEC;
            }

            /////////////////////////////////
            //   Initialize MFC Instance   //
            /////////////////////////////////
            Mfc_Clk_On();
            ret = MFCInst_Dec_Init(pMfcInst, codec_mode, args->dec_init.in_strmSize);
            Mfc_Clk_Off();

            // Output arguments for IOCTL_MFC_xxx_DEC_INIT
            args->dec_init.ret_code = ret;
            if (ret == MFCINST_RET_OK) {
                args->dec_init.out_width  = pMfcInst->width;
                args->dec_init.out_height = pMfcInst->height;
            }

            if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
            {
                RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_VC1_DEC_INIT.\r\n")));
                MFC_Mutex_Release();
                return FALSE;
            }

            break;
        }

    case IOCTL_MFC_MPEG4_DEC_EXE:
    case IOCTL_MFC_H263_DEC_EXE:
    case IOCTL_MFC_H264_DEC_EXE:
    case IOCTL_MFC_VC1_DEC_EXE:

        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_VC1_DEC_EXE.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        args = (MFC_ARGS *)pMarshalledInBuf;

        MFCInst_GetLineBuf(pMfcInst, &p_buf, &n_bufsize);
        CleanInvalidateCacheRange((PBYTE )p_buf, (PBYTE )(p_buf + n_bufsize) );

        Mfc_Clk_On();
        ret = MFCInst_Decode(pMfcInst, args->dec_exe.in_strmSize);
        Mfc_Clk_Off();

        // Output arguments for IOCTL_MFC_xxx_DEC_EXE
        args->dec_exe.ret_code = ret;

        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_VC1_DEC_EXE.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;


    case IOCTL_MFC_GET_LINE_BUF_ADDR:

        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_GET_LINE_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        args = (MFC_ARGS *)pMarshalledInBuf;

        ret = MFCInst_GetLineBuf(pMfcInst, &p_buf, &n_bufsize);
        if (ret != MFCINST_RET_OK) 
        {
            goto GetLineBuffCleanup;
        }
        
        if (handle->pStrmBuf == NULL)
        {
            // Map the Line buffer for this instance to the caller's address space
            //
            handle->hUsrProc = (HANDLE) GetDirectCallerProcessId();
            handle->pStrmBuf = (PBYTE) VirtualAllocEx(handle->hUsrProc, 
                                                        NULL,
                                                        n_bufsize, 
                                                        MEM_RESERVE, 
                                                        PAGE_NOACCESS);
            if (handle->pStrmBuf == NULL)
            {
                RETAILMSG(1, (L"DD::MFC VirtualAllocEx(pStrmBuf) returns FALSE.\n"));
                ret = MFCINST_ERR_MEMORY_ALLOCATION_FAIL;
                goto GetLineBuffCleanup;
            }
            result = VirtualCopyEx(handle->hUsrProc,
                                   handle->pStrmBuf,
                                   (HANDLE) GetCurrentProcessId(),
                                   p_buf,
                                   n_bufsize,
                                   PAGE_READWRITE );
            if (result == FALSE){
                RETAILMSG(1, (L"DD::MFC VirtualCopyEx(pStrmBuf) returns FALSE.\n"));
                VirtualFreeEx(handle->hUsrProc, handle->pStrmBuf, 0, MEM_RELEASE);
                handle->pStrmBuf = NULL;
                ret = MFCINST_ERR_MEMORY_ALLOCATION_FAIL;
                goto GetLineBuffCleanup;
            }
        }

        // Output arguments for IOCTL_MFC_GET_FRAM_BUF_ADDR
        args->get_buf_addr.out_buf_size   = n_bufsize;
        args->get_buf_addr.out_buf_addr   = (int) handle->pStrmBuf;


GetLineBuffCleanup:

        args->get_buf_addr.ret_code = ret;
        
        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_GET_LINE_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;

    case IOCTL_MFC_GET_FRAM_BUF_ADDR:

        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_GET_FRAM_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        args = (MFC_ARGS *)pMarshalledInBuf;

        // Decoder case
        ret = MFCInst_GetFramBuf(pMfcInst, &p_buf, &n_bufsize);
        if (ret != MFCINST_RET_OK) 
        {
            goto GetFrameBuffCleanup;
        }

        // Check Paramter
        if (pMfcInst->run_index * n_bufsize < 0 ||
            (pMfcInst->run_index * n_bufsize) > (int)(pMfcInst->nFramBufSize))
        {
            RETAILMSG(1, (L"[MFC ERROR] IOCTL_MFC_GET_FRAM_BUF_ADDR: Run Index out of range.\r\n"));
            ret = MFCINST_ERR_ETC;
            goto GetFrameBuffCleanup;
        }
        
        if (handle->pFramBuf == NULL)
        {
            // Map the Frame buffer for this instance to the caller's address space
            //
            handle->hUsrProc = (HANDLE) GetDirectCallerProcessId();
            handle->pFramBuf = (PBYTE) VirtualAllocEx(handle->hUsrProc, 
                                                      NULL,
                                                      pMfcInst->nFramBufSize, 
                                                      MEM_RESERVE, 
                                                      PAGE_NOACCESS);
            if (handle->pFramBuf == NULL)
            {
                RETAILMSG(1, (L"DD::MFC VirtualAllocEx(pFramBuf) returns FALSE.\n"));
                ret = MFCINST_ERR_MEMORY_ALLOCATION_FAIL;
                goto GetFrameBuffCleanup;
            }

            result= VirtualCopyEx(handle->hUsrProc,       // HANDLE hDstProc
                                  handle->pFramBuf,
                                  (HANDLE) GetCurrentProcessId(),     // HANDLE hSrcProc
                                  pMfcInst->pFramBuf,
                                  pMfcInst->nFramBufSize,
                                  PAGE_READWRITE);
            if (result == FALSE)
            {
                RETAILMSG(1, (L"DD::MFC VirtualCopyEx(pFramBuf) returns FALSE.\n"));
                VirtualFreeEx(handle->hUsrProc, handle->pFramBuf, 0, MEM_RELEASE);
                handle->pFramBuf = NULL;
                ret = MFCINST_ERR_MEMORY_ALLOCATION_FAIL;
                goto GetFrameBuffCleanup;
            }
        }

        if (pMfcInst->run_index >= 0)
        {
            args->get_buf_addr.out_buf_addr  = (int) (handle->pFramBuf + (pMfcInst->run_index * n_bufsize));

#if (MFC_ROTATE_ENABLE == 1)
            // If PostRotMode is enabled, then the output YUV buffer will be different.
            // In VC-1 mode, the rotated output will be the original one.
            if ( (pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->PostRotMode & 0x0010) )
            {
                args->get_buf_addr.out_buf_addr = (int) (handle->pFramBuf + (pMfcInst->frambufCnt * n_bufsize));
            }
#endif
        }
        else
        {
            args->get_buf_addr.out_buf_addr  = 0;
        }
        
        args->get_buf_addr.out_buf_size   = n_bufsize;
        
GetFrameBuffCleanup:

        args->get_buf_addr.ret_code = ret;
        
        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_GET_FRAM_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;

    case IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:

        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        args = (MFC_ARGS *)pMarshalledInBuf;

        // Decoder case
        ret = MFCInst_GetFramBufPhysical(pMfcInst, &p_buf, &n_bufsize);

        // Output arguments for IOCTL_MFC_xxx_DEC_EXE
        args->get_buf_addr.ret_code = ret;

        if (ret == MFCINST_RET_OK) 
        { 
            // Output arguments for IOCTL_MFC_GET_FRAM_BUF_ADDR
            args->get_buf_addr.out_buf_addr   = (int) p_buf;
            args->get_buf_addr.out_buf_size   = n_bufsize;
        }

        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;

    case IOCTL_MFC_GET_MPEG4_ASP_PARAM:

        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_GET_MPEG4_ASP_PARAM.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        args = (MFC_ARGS *)pMarshalledInBuf;

#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
        ret = MFCINST_RET_OK;
        args->mpeg4_asp_param.ret_code              = MFCINST_RET_OK;
        args->mpeg4_asp_param.mp4asp_vop_time_res   = pMfcInst->RET_DEC_SEQ_INIT_BAK_MP4ASP_VOP_TIME_RES;
        args->mpeg4_asp_param.byte_consumed         = pMfcInst->RET_DEC_PIC_RUN_BAK_BYTE_CONSUMED;
        args->mpeg4_asp_param.mp4asp_fcode          = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_FCODE;
        args->mpeg4_asp_param.mp4asp_time_base_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_TIME_BASE_LAST;
        args->mpeg4_asp_param.mp4asp_nonb_time_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_NONB_TIME_LAST;
        args->mpeg4_asp_param.mp4asp_trd            = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_MP4ASP_TRD;

#if (_WIN32_WCE >= 600)
        if (handle->pFramBuf != NULL){
            args->mpeg4_asp_param.mv_addr      = ((unsigned int) handle->pFramBuf) + (pMfcInst->mv_mbyte_addr - pMfcInst->phyadrFramBuf);
            args->mpeg4_asp_param.mb_type_addr = args->mpeg4_asp_param.mv_addr + 25920;    
            args->mpeg4_asp_param.mv_size      = 25920; // '25920' is the maximum MV size (=45*36*16)
            args->mpeg4_asp_param.mb_type_size = 1620; // '1620' is the maximum MBTYE size (=45*36*1)
        }
#else
        args->mpeg4_asp_param.mv_addr      = ((unsigned int) pMfcInst->pFramBuf) + (pMfcInst->mv_mbyte_addr - pMfcInst->phyadrFramBuf);
        args->mpeg4_asp_param.mb_type_addr = args->mpeg4_asp_param.mv_addr + 25920;    
        args->mpeg4_asp_param.mv_size      = 25920;
        args->mpeg4_asp_param.mb_type_size = 1620;
#endif

        InvalidateCacheRange((PBYTE )args->mpeg4_asp_param.mv_addr, (PBYTE )(args->mpeg4_asp_param.mv_addr + args->mpeg4_asp_param.mv_size) );
        InvalidateCacheRange((PBYTE )args->mpeg4_asp_param.mb_type_addr , (PBYTE )(args->mpeg4_asp_param.mb_type_addr  + args->mpeg4_asp_param.mb_type_size) );
#endif

        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_GET_MPEG4_ASP_PARAM.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }

        break;

    case IOCTL_MFC_GET_CONFIG:
        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_GET_CONFIG.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }
        args = (MFC_ARGS *)pMarshalledInBuf;

        ret = MFC_GetConfigParams(pMfcInst, args);

        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_GET_CONFIG.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }
        break;

    case IOCTL_MFC_SET_CONFIG:
        if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR, TRUE)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeOpenCallerBuffer failed in IOCTL_MFC_SET_CONFIG.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }
        args = (MFC_ARGS *)pMarshalledInBuf;

        Mfc_Clk_On();
        ret = MFC_SetConfigParams(pMfcInst, args);
        Mfc_Clk_Off();

        if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pInBuf, nInBufSize, ARG_IO_PTR)))
        {
            RETAILMSG(1, (TEXT("MFC_IOControl: CeCloseCallerBuffer failed in IOCTL_MFC_SET_CONFIG.\r\n")));
            MFC_Mutex_Release();
            return FALSE;
        }
        break;

    default:
        RETAILMSG(1, (L"[MFC IOControl] Requested ioctl command is not defined. (ioctl cmd=0x%X)\n", dwIoControlCode));
        MFC_Mutex_Release();
        return FALSE;
    }

    MFC_Mutex_Release();

    switch (ret)
    {
    case MFCINST_RET_OK:
        return TRUE;
    default:
        return FALSE;
    }
    return FALSE;
}
static int s3c_mfc_ioctl(struct inode *inode, struct file *file, unsigned
		int cmd, unsigned long arg)
{
	int		ret	= 0;
	MFCInstCtx	*pMfcInst;
	MFC_HANDLE	*handle;
	unsigned char	*OutBuf	= NULL;
	MFC_CODECMODE	codec_mode	= 0;
	int		buf_size;
	unsigned int	tmp;
	MFC_ARGS	args;
	enc_info_t	enc_info;

// modified by RainAde for header type of mpeg4 (+ VOS/VO)
#if 1
	// Hdr0 : SPS or VOL
	// Hdr1 : PPS or VOS
	// Hdr2 : VO (VIS)
	int 	        nStrmLen, nHdrLen, nHdr0Len, nHdr1Len, nHdr2Len;
#else 
// modified by RainAde for composer interface
	int 	        nStrmLen, nHdrLen, nSps, nPps;
#endif

	void		*temp;
	unsigned int		vir_mv_addr;
	unsigned int		vir_mb_type_addr;

	
	//////////////////////
	//	Parameter Check	//
	//////////////////////
	handle = (MFC_HANDLE *)file->private_data;
	if (handle->mfc_inst == NULL) {
		return -EFAULT;
	}

	pMfcInst = handle->mfc_inst;


	switch(cmd)
	{
		case IOCTL_MFC_MPEG4_ENC_INIT:
		case IOCTL_MFC_H264_ENC_INIT:
		case IOCTL_MFC_H263_ENC_INIT:
			MFC_Mutex_Lock();
			LOG_MSG(LOG_TRACE, "mfc_ioctl", "cmd = %d\r\n", cmd);

			Copy_From_User(&args.enc_init, (MFC_ENC_INIT_ARG *)arg, sizeof(MFC_ENC_INIT_ARG));
			
			if ( cmd == IOCTL_MFC_MPEG4_ENC_INIT )
				codec_mode = MP4_ENC;
			else if ( cmd == IOCTL_MFC_H264_ENC_INIT )
				codec_mode = AVC_ENC;
			else if ( cmd == IOCTL_MFC_H263_ENC_INIT )
				codec_mode = H263_ENC;
			
			//////////////////////////////
			//	Initialize MFC Instance	//
			//////////////////////////////
			enc_info.width			= args.enc_init.in_width;
			enc_info.height			= args.enc_init.in_height;
			enc_info.bitrate		= args.enc_init.in_bitrate;
			enc_info.gopNum			= args.enc_init.in_gopNum;
			enc_info.frameRateRes	= args.enc_init.in_frameRateRes;
			enc_info.frameRateDiv	= args.enc_init.in_frameRateDiv;
			
			ret = MFCInst_Enc_Init(pMfcInst, codec_mode, &enc_info);
			
			args.enc_init.ret_code = ret;
			Copy_To_User((MFC_ENC_INIT_ARG *)arg, &args.enc_init, sizeof(MFC_ENC_INIT_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_ENC_EXE:
		case IOCTL_MFC_H264_ENC_EXE:
		case IOCTL_MFC_H263_ENC_EXE:
			MFC_Mutex_Lock();

			Copy_From_User(&args.enc_exe, (MFC_ENC_EXE_ARG *)arg, sizeof(MFC_ENC_EXE_ARG));

			tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;
        
                        // from 2.8.5
			//dmac_clean_range(pMfcInst->pFramBuf, pMfcInst->pFramBuf + tmp);
			//outer_clean_range(__pa(pMfcInst->pFramBuf), __pa(pMfcInst->pFramBuf + tmp));
			// from 2.8.5 : cache flush
			cpu_cache.flush_kern_all();
			
			//////////////////////////
			//	Decode MFC Instance	//
			//////////////////////////

			// modified by RainAde for composer interface
			//ret = MFCInst_Encode(pMfcInst, &nStrmLen, &nHdrLen, &nHdr0Len, &nHdr1Len);
			// modified by RainAde for header type of mpeg4 (+ VOS/VO)
			ret = MFCInst_Encode(pMfcInst, &nStrmLen, &nHdrLen, &nHdr0Len, &nHdr1Len, &nHdr2Len);
			
                        // from 2.8.5
                        //dmac_clean_range(pMfcInst->pStrmBuf, pMfcInst->pStrmBuf + MFC_LINE_BUF_SIZE_PER_INSTANCE);
			//outer_clean_range(__pa(pMfcInst->pStrmBuf), __pa(pMfcInst->pStrmBuf + MFC_LINE_BUF_SIZE_PER_INSTANCE));
			
			args.enc_exe.ret_code	= ret;
			if (ret == MFCINST_RET_OK) {
				args.enc_exe.out_encoded_size = nStrmLen;
				args.enc_exe.out_header_size  = nHdrLen;
// modified by RainAde for composer interface
				args.enc_exe.out_header0_size  = nHdr0Len;
				args.enc_exe.out_header1_size  = nHdr1Len;	
				// modified by RainAde for header type of mpeg4 (+ VOS/VO)
				args.enc_exe.out_header2_size  = nHdr2Len;					
			}
			Copy_To_User((MFC_ENC_EXE_ARG *)arg, &args.enc_exe, sizeof(MFC_ENC_EXE_ARG));
			
			// added by RainAde for cache coherency
			cpu_cache.dma_inv_range(pMfcInst->pStrmBuf, pMfcInst->pStrmBuf + MFC_LINE_BUF_SIZE_PER_INSTANCE);
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_DEC_INIT:
		case IOCTL_MFC_H264_DEC_INIT:
		case IOCTL_MFC_H263_DEC_INIT:
		case IOCTL_MFC_VC1_DEC_INIT:
			MFC_Mutex_Lock();
#ifdef CONFIG_MACH_SATURN
			lcd_gamma_change(LCD_VIDEO); // when decoder init to start playing video, AMOLED gamma set to video mode
#endif

			Copy_From_User(&args.dec_init, (MFC_DEC_INIT_ARG *)arg, sizeof(MFC_DEC_INIT_ARG));
			
			// yj: fix the PiP problem
			cpu_cache.flush_kern_all();

			if ( cmd == IOCTL_MFC_MPEG4_DEC_INIT )
				codec_mode = MP4_DEC;
			else if ( cmd == IOCTL_MFC_H264_DEC_INIT )
				codec_mode = AVC_DEC;
			else if ( cmd == IOCTL_MFC_H263_DEC_INIT)
				codec_mode = H263_DEC;
			else {
				codec_mode = VC1_DEC;
			}
			
			//////////////////////////////
			//	Initialize MFC Instance	//
			//////////////////////////////
			ret = MFCInst_Init(pMfcInst, codec_mode, args.dec_init.in_strmSize);

			args.dec_init.ret_code	= ret;
			if (ret == MFCINST_RET_OK) {
				args.dec_init.out_width	     = pMfcInst->width;
				args.dec_init.out_height     = pMfcInst->height;
				args.dec_init.out_buf_width  = pMfcInst->buf_width;
				args.dec_init.out_buf_height = pMfcInst->buf_height;
			}
			Copy_To_User((MFC_DEC_INIT_ARG *)arg, &args.dec_init, sizeof(MFC_DEC_INIT_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_DEC_EXE:
		case IOCTL_MFC_H264_DEC_EXE:
		case IOCTL_MFC_H263_DEC_EXE:
		case IOCTL_MFC_VC1_DEC_EXE:
			MFC_Mutex_Lock();

			Copy_From_User(&args.dec_exe, (MFC_DEC_EXE_ARG *)arg, sizeof(MFC_DEC_EXE_ARG));

			// from 2.8.5
			//dmac_clean_range(pMfcInst->pStrmBuf, pMfcInst->pStrmBuf + MFC_LINE_BUF_SIZE_PER_INSTANCE);
			//outer_clean_range(__pa(pMfcInst->pStrmBuf), __pa(pMfcInst->pStrmBuf + MFC_LINE_BUF_SIZE_PER_INSTANCE));
			// from 2.8.5 : cache flush
			cpu_cache.flush_kern_all();
			
			if (pMfcInst->inbuf_type == DEC_INBUF_LINE_BUF) {
				ret = MFCInst_Decode(pMfcInst, args.dec_exe.in_strmSize); 
			}
			else if (pMfcInst->inbuf_type == DEC_INBUF_RING_BUF) {
				ret = MFCInst_Decode_Stream(pMfcInst, args.dec_exe.in_strmSize);
			}
			else {
				LOG_MSG(LOG_ERROR, "s3c_mfc_ioctl", "Buffer type is not defined.\n");
				MFC_Mutex_Release();
				args.dec_exe.ret_code = -1;
				return -EINVAL;
			}

			args.dec_exe.ret_code = ret;
			Copy_To_User((MFC_DEC_EXE_ARG *)arg, &args.dec_exe, sizeof(MFC_DEC_EXE_ARG));

			// added by RainAde for cache coherency
			tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;
			cpu_cache.dma_inv_range(pMfcInst->pFramBuf, pMfcInst->pFramBuf + tmp);

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_RING_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			ret = MFCInst_GetRingBuf(pMfcInst, &OutBuf, &buf_size); 
			
			args.get_buf_addr.out_buf_size	= buf_size;
			args.get_buf_addr.out_buf_addr	= args.get_buf_addr.in_usr_data + ((int)(OutBuf - GetDataBufVirAddr()));
			args.get_buf_addr.ret_code		= ret;
			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_LINE_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			ret = MFCInst_GetLineBuf(pMfcInst, &OutBuf, &buf_size);
			
			args.get_buf_addr.out_buf_size	= buf_size;
			args.get_buf_addr.out_buf_addr	= args.get_buf_addr.in_usr_data + (OutBuf - GetDataBufVirAddr());
			args.get_buf_addr.ret_code		= ret;

			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_DBK_BUF_ADDR:	// newly added by yj: returns to DBK_BUF' virtual address and its size.
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_dbkbuf_addr, (MFC_GET_DBK_BUF_ARG *)arg, sizeof(MFC_GET_DBK_BUF_ARG));

			if (pMfcInst->isMp4DbkOn != 1) {
				LOG_MSG(LOG_ERROR, "s3c_mfc_ioctl", "MFC DBK_BUF is not internally allocated yet.\n");
				MFC_Mutex_Release();
				return -EFAULT;
			}

			args.get_dbkbuf_addr.out_buf_size	= (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
			args.get_dbkbuf_addr.out_buf_addr = args.get_dbkbuf_addr.in_usr_mapped_addr + 
											((unsigned int)GetDbkBufVirAddr() - (unsigned int)GetDataBufVirAddr());
			
			args.get_dbkbuf_addr.ret_code	= MFCINST_RET_OK;
			
			Copy_To_User((MFC_GET_DBK_BUF_ARG *)arg, &args.get_dbkbuf_addr, sizeof(MFC_GET_DBK_BUF_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_FRAM_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			if (pMfcInst->pFramBuf == NULL) {
				LOG_MSG(LOG_ERROR, "s3c_mfc_ioctl", "MFC Frame buffer is not internally allocated yet.\n");
				MFC_Mutex_Release();
				return -EFAULT;
			}

			// FRAM_BUF address is calculated differently for Encoder and Decoder.
			switch (pMfcInst->codec_mode) {
			case MP4_DEC:
			case AVC_DEC:
			case VC1_DEC:
			case H263_DEC:
				// Decoder case
				args.get_buf_addr.out_buf_size	= (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;

				tmp	= (unsigned int)args.get_buf_addr.in_usr_data + ( ((unsigned int) pMfcInst->pFramBuf)	\
					+ (pMfcInst->idx) * (args.get_buf_addr.out_buf_size + ZERO_COPY_HDR_SIZE) - (unsigned int)GetDataBufVirAddr() );
#if (MFC_ROTATE_ENABLE == 1)
				if ( (pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->PostRotMode & 0x0010) ) {
					tmp	= (unsigned int)args.get_buf_addr.in_usr_data + ( ((unsigned int) pMfcInst->pFramBuf)	\
					+ (pMfcInst->frambufCnt) * (args.get_buf_addr.out_buf_size + ZERO_COPY_HDR_SIZE) - (unsigned int)GetDataBufVirAddr() );	
				}
#endif
				args.get_buf_addr.out_buf_addr = tmp;
				break;

			case MP4_ENC:
			case AVC_ENC:
			case H263_ENC:
				// Encoder case
				tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;
				args.get_buf_addr.out_buf_addr = args.get_buf_addr.in_usr_data + (pMfcInst->idx * tmp) + (int)(pMfcInst->pFramBuf - GetDataBufVirAddr());
				break;
			}

			args.get_buf_addr.ret_code	= MFCINST_RET_OK;
			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			args.get_buf_addr.out_buf_size	= (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
//			args.get_buf_addr.out_buf_size	= ((pMfcInst->width+2*DIVX_PADDING) * (pMfcInst->height+2*DIVX_PADDING) * 3) >> 1;
		tmp	= (unsigned int)S3C6400_BASEADDR_MFC_DATA_BUF + ( ((unsigned int) pMfcInst->pFramBuf)	\
			+ (pMfcInst->idx) * (args.get_buf_addr.out_buf_size + ZERO_COPY_HDR_SIZE) - (unsigned int)GetDataBufVirAddr() );

//.[ i: sichoi 081103 (ROTATE)
#if (MFC_ROTATE_ENABLE == 1)
        if ( (pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->PostRotMode & 0x0010) ) 
		{
            tmp = (unsigned int)S3C6400_BASEADDR_MFC_DATA_BUF + ( ((unsigned int) pMfcInst->pFramBuf)   \
            + (pMfcInst->frambufCnt) * (args.get_buf_addr.out_buf_size + ZERO_COPY_HDR_SIZE) - (unsigned int)GetDataBufVirAddr() );  
        }
#endif
//.] sichoi 081103

			args.get_buf_addr.out_buf_addr = tmp;
			args.get_buf_addr.ret_code = MFCINST_RET_OK;

			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_GET_MPEG4_ASP_PARAM:
		#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
			Copy_From_User(&args.mpeg4_asp_param, (MFC_GET_MPEG4ASP_ARG *)arg, sizeof(MFC_GET_MPEG4ASP_ARG));
		
			ret = MFCINST_RET_OK;
			args.mpeg4_asp_param.ret_code              = MFCINST_RET_OK;
			args.mpeg4_asp_param.mp4asp_vop_time_res   = pMfcInst->RET_DEC_SEQ_INIT_BAK_MP4ASP_VOP_TIME_RES;
			args.mpeg4_asp_param.byte_consumed         = pMfcInst->RET_DEC_PIC_RUN_BAK_BYTE_CONSUMED;
			args.mpeg4_asp_param.mp4asp_fcode          = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_FCODE;
			args.mpeg4_asp_param.mp4asp_time_base_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_TIME_BASE_LAST;
			args.mpeg4_asp_param.mp4asp_nonb_time_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_NONB_TIME_LAST;
			args.mpeg4_asp_param.mp4asp_trd            = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_MP4ASP_TRD;
			
   			args.mpeg4_asp_param.mv_addr      = (args.mpeg4_asp_param.in_usr_mapped_addr + MFC_STRM_BUF_SIZE) + (pMfcInst->mv_mbyte_addr - pMfcInst->phyadrFramBuf);
			args.mpeg4_asp_param.mb_type_addr = args.mpeg4_asp_param.mv_addr + 25920;	
			args.mpeg4_asp_param.mv_size      = 25920;
			args.mpeg4_asp_param.mb_type_size = 1620;
		
			vir_mv_addr = (unsigned int)((pMfcInst->pStrmBuf + MFC_STRM_BUF_SIZE) + (pMfcInst->mv_mbyte_addr - pMfcInst->phyadrFramBuf));
			vir_mb_type_addr = vir_mv_addr + 25920;

			Copy_To_User((MFC_GET_MPEG4ASP_ARG *)arg, &args.mpeg4_asp_param, sizeof(MFC_GET_MPEG4ASP_ARG));

                        // from 2.8.5
			//dmac_clean_range(vir_mv_addr, vir_mv_addr + args.mpeg4_asp_param.mv_size);
			//outer_clean_range(__pa(vir_mv_addr), __pa(vir_mv_addr + args.mpeg4_asp_param.mv_size));

			//dmac_clean_range(vir_mb_type_addr, vir_mb_type_addr + args.mpeg4_asp_param.mb_type_size);
			//outer_clean_range(__pa(vir_mb_type_addr), __pa(vir_mb_type_addr + args.mpeg4_asp_param.mb_type_size));
		#endif	
			break;
		case IOCTL_MFC_GET_CONFIG:
			MFC_Mutex_Lock();

			Copy_From_User(&args, (MFC_ARGS *)arg, sizeof(MFC_ARGS));

			ret = MFC_GetConfigParams(pMfcInst, &args);

			Copy_To_User((MFC_ARGS *)arg, &args, sizeof(MFC_ARGS));

			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_SET_CONFIG:
			MFC_Mutex_Lock();

			Copy_From_User(&args, (MFC_ARGS *)arg, sizeof(MFC_ARGS));

			ret = MFC_SetConfigParams(pMfcInst, &args);

			Copy_To_User((MFC_ARGS *)arg, &args, sizeof(MFC_ARGS));
			
			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_SET_H263_MULTIPLE_SLICE:
			MFC_Mutex_Lock();

			pMfcInst->multiple_slice = 1;

			MFC_Mutex_Release();
			break;

		case IOCTL_VIRT_TO_PHYS:
			//MFC_Mutex_Lock();

			temp = __virt_to_phys((void *)arg);
			return (int)temp;
			//MFC_Mutex_Release();
			break;
			
		default:
			MFC_Mutex_Lock();
			LOG_MSG(LOG_TRACE, "s3c_mfc_ioctl", "Requested ioctl command is not defined. (ioctl cmd=0x%X)\n", cmd);
			MFC_Mutex_Release();
			return -EINVAL;
	}

	switch(ret) {
	case MFCINST_RET_OK:
		return TRUE;
	default:
		return -1;
	}
	return -1;
}
static int s3c_mfc_release(struct inode *inode, struct file *file)
{
	MFC_HANDLE		*handle = NULL;
	MFCINST_DEC_INBUF_TYPE	inbuf_type;
	int			ret;

	MFC_Mutex_Lock();
#ifdef CONFIG_MACH_SATURN
	lcd_gamma_change(LCD_IDLE); // when finishing playing video, AMOLED gamma change to idle mode
#endif

    #if 1 //mfc.error.recovery
    // If the last issued command is timed out, reset the MFC for error recovery
    // When MFC doesn't respond with DEC_INIT command (timeout)
    // It seems that it doesn't operate normally. It doesn't even respond
    // to swfi command and locks up the cpu when going to sleep. 
    // (SWFI instruction waits for the response from the DOMAIN-V)
    // 
    if(mfc_critial_error) {
        printk(KERN_ERR "\x1b[1;31m" "@#@#@# Reset mfc for error recovery" "\x1b[0m \n");
        MFC_HW_Init();
    }
    #endif
	handle = (MFC_HANDLE *)file->private_data;
	if (handle->mfc_inst == NULL) {
		ret = -1;
		goto err_handle;
	};
	
	//printk("Exit MFC Linux Driver\n");

	inbuf_type = handle->mfc_inst->inbuf_type;
	
	LOG_MSG(LOG_TRACE, "mfc_release", "delete inst no : %d\n", handle->mfc_inst->inst_no);

#if (MFC_LINE_RING_SHARE == 1)
	// In case of (MFC_LINE_RING_SHARE == 1), all the instances were reserved.
	// Therefore the instances need to be released.
	if (inbuf_type == DEC_INBUF_RING_BUF) {
		MfcInstPool_ReleaseAll();
	}
#endif

	MFCInst_Delete(handle->mfc_inst);

	kfree(handle);

#ifdef USE_MFC_DOMAIN_GATING
	CLOCK_DISABLE;
#endif /* USE_MFC_DOMAIN_GATING */

	_openhandle_count--;

	if(_openhandle_count == 0) {

#if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE)
		mfc_pmdev.state = DEV_IDLE;
		kdpmd_set_event(mfc_pmdev.devid, KDPMD_DRVCLOSE);
		kdpmd_wakeup();
		kdpmd_wait(mfc_pmdev.devid);
#endif
#ifdef CONFIG_CPU_FREQ
		set_dvfs_level(1);
#endif /* CONFIG_CPU_FREQ */

#ifdef USE_MFC_DOMAIN_GATING
		DOMAIN_POWER_OFF;
#endif /* USE_MFC_DOMAIN_GATING */
	}

	ret = 0;

err_handle:
	MFC_Mutex_Release();
	return ret;
}
static int s3c_mfc_open(struct inode *inode, struct file *file)
{
	MFC_HANDLE		*handle;
	int			ret;

	//////////////////
	//  Mutex Lock	//
	//////////////////
	MFC_Mutex_Lock();

#ifdef USE_MFC_DOMAIN_GATING
	if(_openhandle_count == 0) {
		DOMAIN_POWER_ON;
	}
#endif /* USE_MFC_DOMAIN_GATING */

	_openhandle_count++;

#ifdef USE_MFC_DOMAIN_GATING
	CLOCK_ENABLE;
#endif /* USE_MFC_DOMAIN_GATING */

	if(_openhandle_count == 1) {
#if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE)
		kdpmd_set_event(mfc_pmdev.devid, KDPMD_DRVOPEN);
		kdpmd_wakeup();
		kdpmd_wait(mfc_pmdev.devid);
		mfc_pmdev.state = DEV_RUNNING;
		printk("mfc_open woke up\n");
#endif

		//////////////////////////////////////
		//	3. MFC Hardware Initialization	//
		//////////////////////////////////////
		if (MFC_HW_Init() == FALSE) 
		{
			ret = -ENODEV;	
			goto err_MFC_HW_Init;
		}
	}


	handle = (MFC_HANDLE *)kzalloc(sizeof(MFC_HANDLE), GFP_KERNEL);
	if(!handle) {
		LOG_MSG(LOG_ERROR, "s3c_mfc_open", "MFC open error\n");
		ret = -1;
		goto err_kzmalloc;
	}
	
	
	//////////////////////////////
	//	MFC Instance creation	//
	//////////////////////////////
	handle->mfc_inst = MFCInst_Create();
	if (handle->mfc_inst == NULL) {
		LOG_MSG(LOG_ERROR, "s3c_mfc_open", "MFC Instance allocation was failed!\r\n");
		ret = -1;
		goto err_MFCInst_Create;
	}

	/*
	 * MFC supports multi-instance. so each instance have own data structure
	 * It saves file->private_data
	 */
	file->private_data = (MFC_HANDLE *)handle;

#ifdef CONFIG_CPU_FREQ
	set_dvfs_level(0);
#endif /* CONFIG_CPU_FREQ */

	LOG_MSG(LOG_TRACE, "mfc_open", "MFC open success! \r\n");
	ret = 0;
	goto no_err;

err_MFCInst_Create:
	kfree (handle);
err_kzmalloc:
err_MFC_HW_Init:
#ifdef USE_MFC_DOMAIN_GATING
	CLOCK_DISABLE;
#endif /* USE_MFC_DOMAIN_GATING */
	_openhandle_count --;

#ifdef USE_MFC_DOMAIN_GATING
	if(_openhandle_count == 0) 
		DOMAIN_POWER_OFF;
#endif /* USE_MFC_DOMAIN_GATING */
no_err:
	MFC_Mutex_Release();
	return ret;
}
static int s3c_mfc_resume(struct platform_device *pdev)
{
	unsigned int	dwMfcBase;
	int 			i, index = 0;
	MFCInstCtx 		*mfcinst_ctx;
	int         	inst_no;
	int				is_mfc_on = 0;
#ifndef CONFIG_PLAT_S5P64XX
	unsigned int	mfc_pwr, domain_v_ready;
	unsigned 	mfc_clk_val;
	unsigned int	mfc_clk_temp;
#endif /* CONFIG_PLAT_S5P64XX */
	int		tmp_openhandle_count;

	
	MFC_Mutex_Lock();

	tmp_openhandle_count = _openhandle_count;
#ifdef USE_MFC_DOMAIN_GATING
	{
		int tmp_openhandle_count = _openhandle_count;
		while (tmp_openhandle_count-- > 0)
		{
			CLOCK_ENABLE;
		}
	}
#endif /* USE_MFC_DOMAIN_GATING */

#ifndef CONFIG_PLAT_S5P64XX
	// mfc clock set 133 Mhz
	mfc_clk_val = readl(S3C_CLK_DIV0);
	mfc_clk_temp = (mfc_clk_val & (0xF << 28))>>28;

	if(mfc_clk_temp == 0)
	{ /* MFC clock shouldn't exceed 133MHZ */
		mfc_clk_val |= (1<<28);
	}
	else if(mfc_clk_temp >= 2)
	{ /*If MFC clock rate is less than 66MHZ, It is recommended to reset it to 133MHz */
		mfc_clk_val =  mfc_clk_val & (~(0xF << 28));
		mfc_clk_val |= (1<<28);	
	}
	__raw_writel(mfc_clk_val, S3C_CLK_DIV0);

	// 1. MFC Power On(Domain V)
	mfc_pwr = readl(S3C_NORMAL_CFG);
	mfc_pwr |= (1<<9);
	__raw_writel(mfc_pwr, S3C_NORMAL_CFG);


	// 2. Check MFC power on
	do {
		domain_v_ready = readl(S3C_BLK_PWR_STAT);
		printk("domain v ready : 0x%X\n", domain_v_ready);
		msleep(1);
	}while(!(domain_v_ready & (1<<1)));
#endif /* CONFIG_PLAT_S5P64XX */

	// 3. Firmware download
	MfcFirmwareIntoCodeDownReg();

	// 4. Power On state
	// Validate all the MFC Instances
	for (inst_no = 0; inst_no < MFC_NUM_INSTANCES_MAX; inst_no++) {
		mfcinst_ctx = MFCInst_GetCtx(inst_no);
		if (mfcinst_ctx) {
			is_mfc_on = 1;

			// When MFC Power On, the MFC instance is validated.
			// Then the MFC operations (DEC_EXE, ENC_EXE, etc.) will be performed again
			MFCInst_PowerOnState(mfcinst_ctx);
			printk(KERN_INFO "MFC_Resume %d-th instance is validated\n", inst_no);
		}
	}


	if (is_mfc_on) {
		// 5. Restore MFC SFR
		dwMfcBase = (unsigned int)GetMfcSfrVirAddr();
		for( i=SAVE_START_ADDR; i<= SAVE_END_ADDR; i+=4 )
		{
			MFC_WRITE_REG( ( dwMfcBase + i ), mfc_save[index] );
			index++;
		}

		// 6. Command MFC wakeup
		MFC_Wakeup();
	}

#ifdef USE_MFC_DOMAIN_GATING
	if(_openhandle_count == 0) {
		DOMAIN_POWER_OFF;
	}
#endif /* USE_MFC_DOMAIN_GATING */

	MFC_Mutex_Release();
	return 0;
}
static int s3c_mfc_suspend(struct platform_device *dev, pm_message_t state)
{
	MFCInstCtx *mfcinst_ctx;
	int         inst_no;
	int			is_mfc_on = 0;
	int			i, index = 0;
	unsigned int	dwMfcBase;


	MFC_Mutex_Lock();

	is_mfc_on = 0;

	// 1. Power Off state
	// Invalidate all the MFC Instances
	for (inst_no = 0; inst_no < MFC_NUM_INSTANCES_MAX; inst_no++) {
		mfcinst_ctx = MFCInst_GetCtx(inst_no);
		if (mfcinst_ctx) {
			is_mfc_on = 1;

			// On Power Down, the MFC instance is invalidated.
			// Then the MFC operations (DEC_EXE, ENC_EXE, etc.) will not be performed
			// until it is validated by entering Power up state transition
			MFCInst_PowerOffState(mfcinst_ctx);
			printk(KERN_INFO "MFC_Suspend %d-th instance is invalidated\n", inst_no);
		}
	}

	/* 2. Command MFC sleep and save MFC SFR */
	if (is_mfc_on) {
		dwMfcBase = (unsigned int)GetMfcSfrVirAddr();

		for(i=SAVE_START_ADDR; i <= SAVE_END_ADDR; i+=4)
		{
			mfc_save[index] = (unsigned int)MFC_READ_REG(dwMfcBase + i);
			index++;	
		}

		MFC_Sleep();
	}

#ifdef USE_MFC_DOMAIN_GATING
	{
		/* 3. Disable MFC clock */
		int tmp_openhandle_count = _openhandle_count;
		while (tmp_openhandle_count-- > 0)
		{
			CLOCK_DISABLE;
		}
	}
#endif /* USE_MFC_DOMAIN_GATING */
/*
	// 4. MFC Power Off(Domain V)
	mfc_pwr = readl(S3C_NORMAL_CFG);
	mfc_pwr &= ~(1<<9);
	printk("mfc_pwr : 0x%X\n", mfc_pwr);
	__raw_writel(mfc_pwr, S3C_NORMAL_CFG);
*/

	MFC_Mutex_Release();

	return 0;
}