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

/*-----------------------------------------------------------------------------
 * $RCSfile: io_mtstc.c,v $
 * $Revision: #2 $
 *---------------------------------------------------------------------------*/

/** @file io_mtstc.c
 *  This file contains implementation of exported APIs of STC module.
 */


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


#include "mtb2r.h"
#include "mtb2r_mwif.h"
#include "mtstc.h"
#include "stc_drvif.h"
#include "b2r_if.h"
#include "b2r_drvif.h"
#include "fbm_drvif.h"
#include "cb_low.h"
#include <linux/mtal_ioctl.h>
#include "dmx_pcr.h"

//-----------------------------------------------------------------------------
// Configurations
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------
#define MTB2R_VIRTUAL_FB_NUM (4)
//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------


typedef struct
{
    UCHAR ucFbgId;
    UCHAR ucEsId;
} MTB2R_VIRTUAL_FBG;

//-----------------------------------------------------------------------------
// Define definitions
//-----------------------------------------------------------------------------

EXTERN UINT32 _u4DrvVideoGetMute(UINT32 u4Path);

#define B2R_USE_HW_DECODER 1

//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------
#define USR_SPACE_ACCESS_VALIDATE_1ARG(arg)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(int)))                            \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return -1;                                          \
    }

#define COPY_FROM_USER_1ARG(ArgUsr, ArgKernel)              \
    if (copy_from_user(&ArgKernel, (void __user *)ArgUsr,   \
                       sizeof(int)))                        \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return -1;                                          \
    }

#define USR_SPACE_ACCESS_VALIDATE_2ARG(arg)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(MTAL_IOCTL_2ARG_T)))              \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return -1;                                          \
    }

#define COPY_FROM_USER_2ARG(ArgUsr, ArgKernel)              \
    if (copy_from_user(&ArgKernel, (void __user *)ArgUsr,   \
                       sizeof(MTAL_IOCTL_2ARG_T)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return -1;                                          \
    }
#define USR_SPACE_ACCESS_VALIDATE_3ARG(arg)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(MTAL_IOCTL_3ARG_T)))              \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return -1;                                          \
    }

#define COPY_FROM_USER_3ARG(ArgUsr, ArgKernel)              \
    if (copy_from_user(&ArgKernel, (void __user *)ArgUsr,   \
                       sizeof(MTAL_IOCTL_3ARG_T)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return -1;                                          \
    }
#define USR_SPACE_ACCESS_VALIDATE_4ARG(arg)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(MTAL_IOCTL_4ARG_T)))              \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return -1;                                          \
    }

#define COPY_FROM_USER_4ARG(ArgUsr, ArgKernel)              \
    if (copy_from_user(&ArgKernel, (void __user *)ArgUsr,   \
                       sizeof(MTAL_IOCTL_4ARG_T)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return -1;                                          \
    }
#define USR_SPACE_ACCESS_VALIDATE_5ARG(arg)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(MTAL_IOCTL_5ARG_T)))              \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return -1;                                          \
    }

#define COPY_FROM_USER_5ARG(ArgUsr, ArgKernel)              \
    if (copy_from_user(&ArgKernel, (void __user *)ArgUsr,   \
                       sizeof(MTAL_IOCTL_5ARG_T)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return -1;                                          \
    }
#define USR_SPACE_ACCESS_VALIDATE_ARG(arg,type)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   sizeof(type)))              \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");     \
        return MTR_ERR_INV;                                          \
    }

#define USR_SPACE_ACCESS_VALIDATE_ARG_K(arg,size)                 \
    if (!access_ok(VERIFY_READ, (void __user *)arg,         \
                   size))              \
    {                                                       \
        printk("mtal_ioctl_video valid argument error\n");     \
        return MTR_ERR_INV;                                          \
    }

#define COPY_TO_USER_ARG(ArgUsr, ArgKernel,type)              \
    if (copy_to_user((void __user *)ArgUsr, &ArgKernel,   \
                       sizeof(type)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return MTR_ERR_INV;                                          \
    }
#define COPY_FROM_USER_ARG(ArgUsr, ArgKernel,type)              \
    if (copy_from_user(&ArgKernel,(void __user *)ArgUsr,    \
                       sizeof(type)))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return MTR_ERR_INV;                                          \
    }

#define COPY_TO_USER_DATA(ArgUsr, ArgKernel, size)              \
    if (copy_to_user((void __user *)ArgUsr, (void *)ArgKernel,   \
                       size))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return MTR_ERR_INV;                                          \
    }
#define COPY_FROM_USER_DATA(ArgUsr, ArgKernel, size)              \
    if (copy_from_user((void *)ArgKernel,(void __user *)ArgUsr,    \
                       size))          \
    {                                                       \
        printk("mtal_ioctl_video argument error\n");      \
        return MTR_ERR_INV;                                          \
    }


//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------

#define MTB2R_INVALID_ES_ID 0xFF
#define MTB2R_INVALID_FBG_ID 0xFF

//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------

MTB2R_VIRTUAL_FBG _arMtb2rFbg[FBG_MAX_NS] = {{0xFF}};


//-----------------------------------------------------------------------------
// Static functions
//-----------------------------------------------------------------------------
static MT_RESULT_T _MTB2R_GetPts(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT32* pu4PtsValue;
    UINT32 u4PtsValue;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    pu4PtsValue = (UINT32*)(rArg.ai4Arg[1]);

    u4PtsValue = VDP_GetPts(ucVdpId);

    USR_SPACE_ACCESS_VALIDATE_ARG(pu4PtsValue,UINT32);
    COPY_TO_USER_ARG(pu4PtsValue, u4PtsValue, UINT32);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetDispDrvStable(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8* pu1DispDrvStable;
    UINT8 u1DispDrvStable;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    pu1DispDrvStable = (UINT8*)(rArg.ai4Arg[1]);

    u1DispDrvStable = !_u4DrvVideoGetMute(ucVdpId);

    USR_SPACE_ACCESS_VALIDATE_ARG(pu1DispDrvStable,UINT8);
    COPY_TO_USER_ARG(pu1DispDrvStable, u1DispDrvStable, UINT8);

    return MTR_OK;
}


static MT_RESULT_T _MTB2R_GetStepForward(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8* pu1StepFroward;
    UINT8 u1StepFroward;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    pu1StepFroward = (UINT8*)(rArg.ai4Arg[1]);

    u1StepFroward = VDP_GetStepForward(ucVdpId);

    USR_SPACE_ACCESS_VALIDATE_ARG(pu1StepFroward,UINT8);
    COPY_TO_USER_ARG(pu1StepFroward, u1StepFroward, UINT8);

    return MTR_OK;
}
static MT_RESULT_T _MTB2R_GetPosInfo(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_POS_INFO_T* prPosInfo;
    MTB2R_POS_INFO_T rPosInfo;

    x_memset(&rPosInfo,0,sizeof(MTB2R_POS_INFO_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prPosInfo = (MTB2R_POS_INFO_T*)(rArg.ai4Arg[1]);

    VDP_GetPosInfo(ucVdpId,(VDP_POS_INTO_T*)&rPosInfo);

    USR_SPACE_ACCESS_VALIDATE_ARG(prPosInfo,MTB2R_POS_INFO_T);
    COPY_TO_USER_ARG(prPosInfo, rPosInfo, MTB2R_POS_INFO_T);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetCaptureInfo(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_CAPTURE_INFO_T* prCaptureInfo;
    MTB2R_CAPTURE_INFO_T rCaptureInfo;

    x_memset(&rCaptureInfo,0,sizeof(MTB2R_CAPTURE_INFO_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prCaptureInfo = (MTB2R_CAPTURE_INFO_T*)(rArg.ai4Arg[1]);

    VDP_GetLockFrameBufferAddr(ucVdpId,(VDP_CAPTURE_INTO_T*)&rCaptureInfo);

    USR_SPACE_ACCESS_VALIDATE_ARG(prCaptureInfo,MTB2R_CAPTURE_INFO_T);
    COPY_TO_USER_ARG(prCaptureInfo, rCaptureInfo, MTB2R_CAPTURE_INFO_T);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetCaptureInfo2(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_CAPTURE_INFO_T* prCaptureInfo;
    MTB2R_CAPTURE_INFO_T rCaptureInfo;

    x_memset(&rCaptureInfo,0,sizeof(MTB2R_CAPTURE_INFO_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prCaptureInfo = (MTB2R_CAPTURE_INFO_T*)(rArg.ai4Arg[1]);

    VDP_GetDisplayFrameBufferAddr(ucVdpId,(VDP_CAPTURE_INTO_T*)&rCaptureInfo);

    USR_SPACE_ACCESS_VALIDATE_ARG(prCaptureInfo,MTB2R_CAPTURE_INFO_T);
    COPY_TO_USER_ARG(prCaptureInfo, rCaptureInfo, MTB2R_CAPTURE_INFO_T);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetPicInfo(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_PIC_INFO_T* prPicInfo;
    MTB2R_PIC_INFO_T rPicInfo;
    MT_RESULT_T eRetVal = MTR_OK;

    x_memset(&rPicInfo,0,sizeof(MTB2R_PIC_INFO_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prPicInfo = (MTB2R_PIC_INFO_T*)(rArg.ai4Arg[1]);

    if (VDP_GetPicInfo(ucVdpId,(VDP_PIC_INFO_T*)&rPicInfo) != VDP_SET_OK)
    {
        eRetVal = MTR_NOT_OK;
    }

    USR_SPACE_ACCESS_VALIDATE_ARG(prPicInfo,MTB2R_PIC_INFO_T);
    COPY_TO_USER_ARG(prPicInfo, rPicInfo, MTB2R_PIC_INFO_T);

    return eRetVal;
}

static MT_RESULT_T _MTB2R_GetPlayMode(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8* pu1PlayMode;
    UINT8 u1PlayMode;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    pu1PlayMode = (UINT8*)(rArg.ai4Arg[1]);

    u1PlayMode = VDP_GetPlayMode(ucVdpId);

    USR_SPACE_ACCESS_VALIDATE_ARG(pu1PlayMode,UINT8);
    COPY_TO_USER_ARG(pu1PlayMode, u1PlayMode, UINT8);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetGameMode(unsigned long arg)
{
#ifdef CC_B2R_SUPPORT_GAME_MODE

    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    B2R_GM_TYPE_T eMode;
  
    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    eMode = (B2R_GM_TYPE_T)(rArg.ai4Arg[1]);

    B2R_SetGameMode(ucVdpId, eMode);
    
 #endif  
    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetSlowForward(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8* pu1SlowForward;
    UINT8 u1SlowForward;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    pu1SlowForward = (UINT8*)(rArg.ai4Arg[1]);

    u1SlowForward = VDP_GetSlowForward(ucVdpId);

    USR_SPACE_ACCESS_VALIDATE_ARG(pu1SlowForward,UINT8);
    COPY_TO_USER_ARG(pu1SlowForward, u1SlowForward, UINT8);

    return MTR_OK;
}
#ifdef CC_B2R_RM_SUPPORT
static void _MTVB2R_RmNotify(UCHAR ucConflicVdpId, MTB2R_RM_COND_T eCond,UCHAR ucCurrentVdpId)
{
    MTB2R_RM_CB_T rPara;

  //  MTVDEC_PRINT("_MTPVR_RmNotify ucEsId(%d) ucCond(%d).\n", ucEsId, eCond);
    
    rPara.u1ConflictVdpId  = ucConflicVdpId;
    rPara.u1CurrentVdpId   = ucCurrentVdpId;
    rPara.eCond   = eCond;

    _CB_PutEvent(CB_MTAL_B2R_RM_NFY, sizeof(MTB2R_RM_CB_T), (void*)&rPara);
}
#endif
static MT_RESULT_T _MTVB2R_Reg_Callback(void)
{
    #ifdef CC_B2R_RM_SUPPORT
    B2R_RegRmCb((PFN_B2R_RM_CB)_MTVB2R_RmNotify);
    #endif
    return MTR_OK;
}
static MT_RESULT_T _MTB2R_RmSet(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    BOOL fgSuccess = 0;
    UCHAR ucvdpId;
   
    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucvdpId=(UINT8)(rArg.ai4Arg[0]);
    fgSuccess=(BOOL)rArg.ai4Arg[1];
    #ifdef CC_B2R_RM_SUPPORT
    B2R_RmSetKickDone(ucvdpId,fgSuccess);
    #endif
    return MTR_OK;
}
//#endif
static MT_RESULT_T _MTB2R_SetABInfo(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_AB_INFO_T* prABInfo;
    MTB2R_AB_INFO_T rABInfo;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prABInfo = (MTB2R_AB_INFO_T*)(rArg.ai4Arg[1]);

    USR_SPACE_ACCESS_VALIDATE_ARG(prABInfo, MTB2R_AB_INFO_T);
    COPY_FROM_USER_ARG(prABInfo, rABInfo, MTB2R_AB_INFO_T);

    if(VDP_SetABInfo(ucVdpId,(VDP_AB_INTO_T*)&rABInfo))
    {
        return MTR_OK;
    }
    else
    {
        return MTR_NOT_OK;
    }
}

static MT_RESULT_T _MTB2R_SetThumbnailMode(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgThumbnailMode;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);
    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgThumbnailMode = (BOOL)rArg.ai4Arg[1];

    if(VDP_SetThumbnailMode(ucVdpId,fgThumbnailMode))
    {
        return MTR_OK;
    }
    else
    {
        return MTR_NOT_OK;
    }

}

static MT_RESULT_T _MTB2R_SetSeek(unsigned long arg)
{
    MTAL_IOCTL_3ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgSet;
    UINT32 u4Pts;

    USR_SPACE_ACCESS_VALIDATE_3ARG(arg);
    COPY_FROM_USER_3ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgSet = (BOOL)rArg.ai4Arg[1];
    u4Pts = (UINT32)rArg.ai4Arg[2];

    VDP_SetSeek(ucVdpId,fgSet,u4Pts);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetPauseMM(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgPause;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgPause = (BOOL)rArg.ai4Arg[1];

    VDP_SetPauseMm(ucVdpId,fgPause);

    return MTR_OK;
}
#if defined(CC_MAPLE_CUST_DRV)

static MT_RESULT_T _MTB2R_SetSyncMode2(unsigned long arg)
{
    MTAL_IOCTL_5ARG_T rArg;
    UINT8 ucStcId,ucAdecId,ucAdec2Id,ucVdecId;
    UINT8 u4SyncMode;

    USR_SPACE_ACCESS_VALIDATE_5ARG(arg);
    COPY_FROM_USER_5ARG(arg, rArg);

    ucStcId    =  (UINT8)rArg.ai4Arg[0];
    ucAdecId   = (UINT8)rArg.ai4Arg[1];
    ucAdec2Id  = (UINT8)rArg.ai4Arg[2];
	ucVdecId   =  (UINT8)rArg.ai4Arg[3];
	u4SyncMode =(UINT8)rArg.ai4Arg[4];
    STC_SetSyncMode2( ucStcId, ucAdecId,  ucAdec2Id, ucVdecId,  u4SyncMode);

    return MTR_OK;
}
#endif
static MT_RESULT_T _MTB2R_SetStepForward(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8 u1StepForward;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    u1StepForward = (UINT8)rArg.ai4Arg[1];

    VDP_SetStepForward(ucVdpId,u1StepForward);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetFBNoTimeout(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgFBNoTimeout;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgFBNoTimeout = (BOOL)rArg.ai4Arg[1];

    VDP_SetFBNoTimeout(ucVdpId,fgFBNoTimeout);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetSpeed(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTSTC_SPEED_TYPE_T eSpeed;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    eSpeed = (MTSTC_SPEED_TYPE_T)rArg.ai4Arg[1];

    VDP_SetSpeed(ucVdpId,(STC_SPEED_TYPE_T)eSpeed);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetTrickMode(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgTrickMode;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgTrickMode = (BOOL)rArg.ai4Arg[1];

    VDP_SetTrickMode(ucVdpId,fgTrickMode);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetInput(unsigned long arg)
{
    MTAL_IOCTL_3ARG_T rArg;
    UINT8 ucVdpId;
    UINT8 ucEsId;
    UINT8 ucPort;

    USR_SPACE_ACCESS_VALIDATE_3ARG(arg);
    COPY_FROM_USER_3ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    ucEsId = (BOOL)rArg.ai4Arg[1];
    ucPort = (UINT32)rArg.ai4Arg[2];

    VDP_SetInput(ucVdpId,ucEsId,ucPort);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetSlowForward(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    BOOL fgSlowMode;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    fgSlowMode = (BOOL)rArg.ai4Arg[1];

    VDP_SetSlowForward(ucVdpId,fgSlowMode);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetCbAttachedId(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    UINT8 ucAttachedId;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    ucAttachedId = (BOOL)rArg.ai4Arg[1];

    VDP_SetCbAttachedSrcId(ucVdpId,ucAttachedId);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SelectGroupType(unsigned long arg)
{
    MTAL_IOCTL_5ARG_T rArg;
    UINT8 u1FbgId;
    UINT8* pu1FbgId;
    UINT8 u1EsId;
    UINT32 u4FrameWidth;
    UINT32 u4FrameHeight;
    MTB2R_DISPLAY_FORMAT_T eFrameFormat;
    //UINT8 u1FbgType;

    USR_SPACE_ACCESS_VALIDATE_5ARG(arg);
    COPY_FROM_USER_5ARG(arg, rArg);

    pu1FbgId = (UINT8*)rArg.ai4Arg[0];
    u1EsId = (UINT8)rArg.ai4Arg[1];
    u4FrameWidth = (UINT32)rArg.ai4Arg[2];
    u4FrameHeight = (UINT32)rArg.ai4Arg[3];
    eFrameFormat = (MTB2R_DISPLAY_FORMAT_T)rArg.ai4Arg[4];

    if(u1EsId >= VDP_NS)
    {
        printk("warning ! , u1EsId = %d\n", u1EsId);
    }

    // make it same with u1EsId temporally.
    u1FbgId = u1EsId;
    if(u1FbgId < FBG_MAX_NS)
    {
        if(_arMtb2rFbg[u1FbgId].ucEsId != MTB2R_INVALID_ES_ID)
        {
            printk("warning ! , _arMtb2rFbg[u1FbgId].u1EsId = %d\n", _arMtb2rFbg[u1FbgId].ucEsId);
        }
        _arMtb2rFbg[u1FbgId].ucEsId = u1EsId;
        _arMtb2rFbg[u1FbgId].ucFbgId = u1EsId; // this is virtual FbgId, set to same with EsId
    }
    
    USR_SPACE_ACCESS_VALIDATE_ARG(pu1FbgId,UINT8);
    COPY_TO_USER_ARG(pu1FbgId, u1FbgId, UINT8);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetSeqHdr(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 u1FbgId;
    MTB2R_SEQ_HDR_T* prFrameSeqHdr;
    MTB2R_SEQ_HDR_T  rFrameSeqHdr;
    FBM_SEQ_HDR_T* prFbmSeqHdr = NULL;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    u1FbgId = (UINT8)rArg.ai4Arg[0];
    prFrameSeqHdr = (MTB2R_SEQ_HDR_T*)rArg.ai4Arg[1];

    USR_SPACE_ACCESS_VALIDATE_ARG(prFrameSeqHdr,MTB2R_SEQ_HDR_T);
    COPY_FROM_USER_ARG(prFrameSeqHdr, rFrameSeqHdr,MTB2R_SEQ_HDR_T);
    prFbmSeqHdr = FBM_GetFrameBufferSeqHdr(u1FbgId);

    if(prFbmSeqHdr != NULL)
    {
        prFbmSeqHdr->ucAspRatInf = MPEG_ASPECT_RATIO_1_1;
        prFbmSeqHdr->ucFrmRatCod = (UINT8)rFrameSeqHdr.eFrameRate;
        prFbmSeqHdr->fgProgressiveSeq = rFrameSeqHdr.fgProgressiveSeq;

        prFbmSeqHdr->u2LineSize = (UINT16)rFrameSeqHdr.u4LineSize;

        prFbmSeqHdr->u2HSize = (UINT16)rFrameSeqHdr.u4FrameWidth;
        prFbmSeqHdr->u2VSize = (UINT16)rFrameSeqHdr.u4FrameHeight;
        prFbmSeqHdr->u2OrgHSize = (UINT16)rFrameSeqHdr.u4FrameWidth;
        prFbmSeqHdr->u2OrgVSize = (UINT16)rFrameSeqHdr.u4FrameHeight;

        prFbmSeqHdr->u4ResizeWidth = rFrameSeqHdr.u4FrameWidth;
        prFbmSeqHdr->u4ResizeHeight = rFrameSeqHdr.u4FrameHeight;

#if B2R_USE_HW_DECODER
        prFbmSeqHdr->fgSwDecoder = FALSE;
#else
        prFbmSeqHdr->fgSwDecoder = TRUE;
#endif

        if(rFrameSeqHdr.eAddrMode == MTB2R_RASTER_MODE)
        {
            prFbmSeqHdr->fgRasterOrder = TRUE;
        }
        else
        {
            prFbmSeqHdr->fgRasterOrder = FALSE;
        }
    }
    return MTR_OK;
}

static MT_RESULT_T _MTB2R_GetEmptyFrameBuffer(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 u1FbgId;
    //MTB2R_PIC_HDR_T* prFrameHdr;
    //MTB2R_PIC_HDR_T  rFrameHdr;
    //FBM_POOL_T *prFbmPool;

    //x_memset(&rFrameHdr,0,sizeof(MTB2R_PIC_INFO_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    u1FbgId = (UINT8)rArg.ai4Arg[0];
    //prFrameHdr = (MTB2R_PIC_HDR_T*)rArg.ai4Arg[1];

    UNUSED(u1FbgId);
    return MTR_OK;
}


static MT_RESULT_T _MTB2R_FreeFrameBuffer(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 u1FbgId;
    UINT8 u1RealFbgId;
    B2R_PRM_T* prVdpPrm = NULL;
    UINT8 u1DispFbgId;
    UINT8 u1DispFbId;
    MTB2R_PIC_HDR_T* prFrameHdr;
    MTB2R_PIC_HDR_T  rFrameHdr;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    u1FbgId = (UINT8)rArg.ai4Arg[0];
    prFrameHdr = (MTB2R_PIC_HDR_T*)rArg.ai4Arg[1];
    USR_SPACE_ACCESS_VALIDATE_ARG(prFrameHdr,MTB2R_PIC_HDR_T);
    COPY_FROM_USER_ARG(prFrameHdr, rFrameHdr,MTB2R_PIC_HDR_T);
	u1RealFbgId = rFrameHdr.u1FbgId;

    if(u1FbgId < FBG_MAX_NS)
    {
        prVdpPrm = (B2R_PRM_T*)VDP_GetVdpPrm(VDP_Es2Vdp(_arMtb2rFbg[u1FbgId].ucEsId));
    }

    if(!prVdpPrm)
    {
        printk("%s(L:%d) prVdpPrm null\n", __FUNCTION__, __LINE__);
        return MTR_OK;
    }
#ifdef CC_3D_MM_DS_SUPPORT
	if(prVdpPrm->ucFbgId != u1RealFbgId && prVdpPrm->ucSubFbgId != u1RealFbgId)
	{
		printk("warning! Free Fbgid = %d , driver Fbgid = (%d, %d)\n", 
			u1RealFbgId, prVdpPrm->ucFbgId, prVdpPrm->ucSubFbgId);
		return MTR_OK;
	}
#endif
    u1DispFbgId = u1RealFbgId; //prVdpPrm->rPortPrm.ucFbgId;

    u1DispFbId = FBM_GetFrameBufferFromDispQ(u1DispFbgId);

    if(u1DispFbId != 0xff && u1DispFbgId != 0xff)
    {
    	FBM_PIC_HDR_T* prPicHdr;
		prPicHdr  = FBM_GetFrameBufferPicHdr(u1DispFbgId, u1DispFbId);
        FBM_SetFrameBufferStatus(u1DispFbgId, u1DispFbId, FBM_FB_STATUS_LOCK);
        FBM_SetFrameBufferStatus(u1DispFbgId, u1DispFbId, FBM_FB_STATUS_EMPTY);
    }

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetDispFrame(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 u1VdpId = 0;
    UINT8 u1FbgId = 0;
    B2R_PRM_T* prVdpPrm = NULL;
    MTB2R_PIC_HDR_T* prFrameHdr = NULL;
    MTB2R_PIC_HDR_T  rFrameHdr ;
    //send a message to b2r to get next frame buffer to display
    VDP_B2R_CHG_FRAME_MSG_T rMsg;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    u1FbgId = (UINT8)rArg.ai4Arg[0];
    prFrameHdr = (MTB2R_PIC_HDR_T*)rArg.ai4Arg[1];

    USR_SPACE_ACCESS_VALIDATE_ARG(prFrameHdr,MTB2R_PIC_HDR_T);
    COPY_FROM_USER_ARG(prFrameHdr, rFrameHdr,MTB2R_PIC_HDR_T);

    x_memset(&rMsg, 0, sizeof(VDP_B2R_CHG_FRAME_MSG_T));
    
    if(u1FbgId < FBG_MAX_NS)
    {
        u1VdpId = (VDP_Es2Vdp(_arMtb2rFbg[u1FbgId].ucEsId));
    }
    
    prVdpPrm = (B2R_PRM_T*)VDP_GetVdpPrm(u1VdpId);

    if(!prVdpPrm)
    {
        printk("%s(L:%d) prVdpPrm null\n", __FUNCTION__, __LINE__);
        return MTR_OK;
    }

    if(prVdpPrm != NULL)
    {
        if(prVdpPrm->ucFbgId == 0xFF || prVdpPrm->ucFbgId != rFrameHdr.u1FbgId)
        {
            printk("warning! render Fbgid = %d , driver Fbgid = %d\n",rFrameHdr.u1FbgId,prVdpPrm->ucFbgId);
            return MTR_OK;
        }
    }

    if(VDP_GstEnablGstLog(u1VdpId))
    {
        printk("render fbg = %d , fbid = %d , flag = 0x%x\n",rFrameHdr.u1FbgId,rFrameHdr.u1FbId,rFrameHdr.u4Flag);
    }
    
    rMsg.u4VdpId = (UINT32)u1VdpId;
    rMsg.u4Flag = (UINT32)rFrameHdr.u4Flag;
    VDP_SendB2RChgFrameMsg(&rMsg);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_FlushFrame(unsigned long arg)
{
    UINT8 u1VdpId = 0;
    UINT8 u1FbgId = 0;

    u1FbgId = (UINT8)arg;

    if(u1FbgId < FBG_MAX_NS)
    {
        u1VdpId = (VDP_Es2Vdp(_arMtb2rFbg[u1FbgId].ucEsId));
    }
    
    if(VDP_GstEnablGstLog(u1VdpId))
    {
        printk("flush render vdpid = %d\n", u1VdpId);
    }

    VDP_FlushB2RChgFrameMsg(u1VdpId);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_ReleaseFbg(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 u1FbgId;
    UINT8 u1EsId;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    u1FbgId = (UINT8)rArg.ai4Arg[0];
    u1EsId = (UINT8)rArg.ai4Arg[1];
    if(u1FbgId < FBG_MAX_NS)
    {
        u1EsId = _arMtb2rFbg[u1FbgId].ucEsId;
        _arMtb2rFbg[u1FbgId].ucEsId = MTB2R_INVALID_ES_ID;
        _arMtb2rFbg[u1FbgId].ucFbgId= MTB2R_INVALID_FBG_ID;
    }
    return MTR_OK;
}

static MT_RESULT_T _MTB2R_Set3DInfo(unsigned long arg)
{
    MTAL_IOCTL_3ARG_T rArg;
    UCHAR u1B2rId;
    UINT8 u13DType;
    BOOL fg3DEnable;

    USR_SPACE_ACCESS_VALIDATE_3ARG(arg);
    COPY_FROM_USER_3ARG(arg, rArg);

    u1B2rId = (UCHAR)rArg.ai4Arg[0];
    u13DType = (UINT8)rArg.ai4Arg[1];
    fg3DEnable = (BOOL)rArg.ai4Arg[2];

    VDP_Set3DInfo(u1B2rId, u13DType, fg3DEnable);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_SetChpterEnable(unsigned long arg)
{
#if !defined(DIVX_PLUS_CER) || !defined(CC_B2R_CHAPTER_CHG) 
    return MTR_NOT_OK;

#else
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_CHAPTER_T *prChapterUsr;
    MTB2R_CHAPTER_T rChapterKer;
    VDP_CHAPTER_T    rChapter;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)rArg.ai4Arg[0];
    prChapterUsr = (MTB2R_CHAPTER_T *)rArg.ai4Arg[1];

    USR_SPACE_ACCESS_VALIDATE_ARG(prChapterUsr, MTB2R_CHAPTER_T);
    COPY_FROM_USER_ARG(prChapterUsr, rChapterKer, MTB2R_CHAPTER_T);

    x_memset(&rChapter, 0, sizeof(rChapter));

    rChapter.fgIsPending     = rChapterKer.fgIsPending;
    rChapter.u8StartPts      = rChapterKer.u8StartPts;
    rChapter.u8EndPts        = rChapterKer.u8EndPts;
    rChapter.fgFirstSetChapter = rChapterKer.fgFirstSetChapter;

    return (VDP_SetChpterEnable(&rChapter))? MTR_OK : MTR_NOT_OK;
#endif
}

static MT_RESULT_T _MTB2R_SetMirror(unsigned long arg)
{
	MTAL_IOCTL_2ARG_T rArg;
    UCHAR ucVdpId;
    BOOL fgOn;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UCHAR)rArg.ai4Arg[0];
    fgOn = (BOOL)rArg.ai4Arg[1];

    VDP_SetB2RMirror(ucVdpId, fgOn);

    return MTR_OK;
}

static MT_RESULT_T _MTB2R_AudTrigger(unsigned long arg)
{
    MTAL_IOCTL_2ARG_T rArg;
    UINT8 ucVdpId;
    MTB2R_TRIG_AUD_CFG_T* prAudTrgInfo;
    MTB2R_TRIG_AUD_CFG_T  rAudTrgInfo;
    MT_RESULT_T eRetVal = MTR_OK;

    x_memset(&rAudTrgInfo,0,sizeof(MTB2R_TRIG_AUD_CFG_T));

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    prAudTrgInfo = (MTB2R_TRIG_AUD_CFG_T*)(rArg.ai4Arg[1]);

    USR_SPACE_ACCESS_VALIDATE_ARG(prAudTrgInfo, MTB2R_TRIG_AUD_CFG_T);
    COPY_FROM_USER_ARG(prAudTrgInfo, rAudTrgInfo, MTB2R_TRIG_AUD_CFG_T);
    
    if (B2R_AudTrigger(ucVdpId,(VDP_TRIG_AUD_CFG_T*)&rAudTrgInfo) != B2R_OK)
    {
        eRetVal = MTR_NOT_OK;
    }

    return eRetVal;
}

static B2R_CB_FUNC_ENUM_T _MTB2R_CBEnum_to_VDPCBEnum(MTB2R_CB_FUNC_ENUM_T eMTB2REnum)
{
    B2R_CB_FUNC_ENUM_T eReturn = B2R_CB_FUNC_NS;

    switch (eMTB2REnum)
    {
        case MTB2R_CB_FUNC_TRIG_AUD_TO_PLAY:
            eReturn = B2R_CB_FUNC_TRIG_AUD_TO_PLAY;
            break;            

        case MTB2R_CB_FUNC_EOS:
            eReturn = B2R_CB_FUNC_EOS;
            break;
            
        case MTB2R_CB_FUNC_PTS_RENDER:
            eReturn = B2R_CB_FUNC_PTS_RENDER;
            break;
            
        default:
            eReturn = B2R_CB_FUNC_NS;
            break;
    }

    return eReturn;
}

static void _B2R_TrigAudCallback(UINT32 u4VdpId, UINT64 u8Arg1, UINT32 u4Arg2, UINT64 u8Arg3)
{
    MTB2R_CB_T  rB2rCbT;

    rB2rCbT.u4Arg1 = u4VdpId;
    rB2rCbT.u4Arg2 = (UINT32)u8Arg1;
    rB2rCbT.u4Arg3 = u4Arg2;
    rB2rCbT.u4Arg4 = (UINT32)u8Arg3;
    
    _CB_PutEvent(CB_MTAL_B2R_AUD_START_TO_PLAY, sizeof(MTB2R_CB_T), (void*)&rB2rCbT);
}

static void _B2R_EosCallback(UINT32 u4VdpId, UINT64 u8Arg1, UINT32 u4Arg2, UINT64 u8Arg3)
{
    MTB2R_CB_T  rB2rCbT;

    rB2rCbT.u4Arg1 = u4VdpId;
    rB2rCbT.u4Arg2 = (UINT32)u8Arg1;
    rB2rCbT.u4Arg3 = u4Arg2;
    rB2rCbT.u4Arg4 = (UINT32)u8Arg3;
    
    _CB_PutEvent(CB_MTAL_B2R_EOS, sizeof(MTB2R_CB_T), (void*)&rB2rCbT);
}

static void _B2R_PtsCallback(UINT32 u4VdpId, UINT64 u8Arg1, UINT32 u4Arg2, UINT64 u8Arg3)
{
    MTB2R_CB_T  rB2rCbT;

    rB2rCbT.u4Arg1 = u4VdpId;
    rB2rCbT.u4Arg2 = (UINT32)u8Arg1;
    rB2rCbT.u4Arg3 = u4Arg2;
    rB2rCbT.u4Arg4 = (UINT32)u8Arg3;
    
    _CB_PutEvent(CB_MTAL_PTS_RENDER, sizeof(MTB2R_CB_T), (void*)&rB2rCbT);
}

static MT_RESULT_T _MTB2R_RegCbFunc(unsigned long arg)
{
    INT32  i4Ret = MTR_OK;
    UINT8 ucVdpId;
    MTAL_IOCTL_3ARG_T rArg;
    MTB2R_CB_FUNC_ENUM_T eFuncType;
    MTB2R_REG_CB_OBJ_T  r_reg_obj;
    MTB2R_REG_CB_OBJ_T* pr_reg_obj;

    x_memset(&r_reg_obj, 0, sizeof(MTB2R_REG_CB_OBJ_T));

    USR_SPACE_ACCESS_VALIDATE_3ARG(arg);
    COPY_FROM_USER_3ARG(arg, rArg);

    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    eFuncType = (MTB2R_CB_FUNC_ENUM_T)rArg.ai4Arg[1];
    pr_reg_obj = (MTB2R_REG_CB_OBJ_T*)rArg.ai4Arg[2];

    MTB2R_PRINT(" - eFuncType = %d\n",
        eFuncType);

    USR_SPACE_ACCESS_VALIDATE_ARG(pr_reg_obj, MTB2R_REG_CB_OBJ_T);
    COPY_FROM_USER_ARG(pr_reg_obj, r_reg_obj, MTB2R_REG_CB_OBJ_T);

    switch (eFuncType)
    {
        case MTB2R_CB_FUNC_TRIG_AUD_TO_PLAY:
            i4Ret = B2R_RegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType), 
                (UINT32)_B2R_TrigAudCallback, (UINT32)&r_reg_obj);
            break;                        

        case MTB2R_CB_FUNC_EOS:
            i4Ret = B2R_RegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType),
                (UINT32)_B2R_EosCallback, (UINT32)&r_reg_obj);
            break; 

        case MTB2R_CB_FUNC_PTS_RENDER:
            i4Ret = B2R_RegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType), 
                (UINT32)_B2R_PtsCallback, (UINT32)&r_reg_obj);
            break; 
            
        default:
            i4Ret = MTR_NOT_OK;
            break;
    }
    
    return i4Ret;
}

static MT_RESULT_T _MTB2R_UnRegCbFunc(unsigned long arg)
{
    INT32  i4Ret = MTR_OK;
    UINT8 ucVdpId;
    MTAL_IOCTL_2ARG_T rArg;
    MTB2R_CB_FUNC_ENUM_T eFuncType;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);
    ucVdpId = (UINT8)(rArg.ai4Arg[0]);
    eFuncType = (MTB2R_CB_FUNC_ENUM_T)rArg.ai4Arg[1];

    MTB2R_PRINT(" - eFuncType = %d\n",
        eFuncType);

    switch (eFuncType)
    {
        case MTB2R_CB_FUNC_TRIG_AUD_TO_PLAY:
            i4Ret = B2R_UnRegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType));
            break;                        

        case MTB2R_CB_FUNC_EOS:
            i4Ret = B2R_UnRegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType));
            break; 

        case MTB2R_CB_FUNC_PTS_RENDER:
            i4Ret = B2R_UnRegCbFunc(ucVdpId, _MTB2R_CBEnum_to_VDPCBEnum(eFuncType));
            break; 
            
        default:
            i4Ret = MTR_NOT_OK;
            break;
    }
    
    return i4Ret;
}

static MT_RESULT_T _MTB2R_SetPatten(unsigned long arg)
{
	MTAL_IOCTL_2ARG_T rArg;
    UCHAR ucVdpId;
    BOOL fgOn;

    USR_SPACE_ACCESS_VALIDATE_2ARG(arg);
    COPY_FROM_USER_2ARG(arg, rArg);

    ucVdpId = (UCHAR)rArg.ai4Arg[0];
    fgOn = (BOOL)rArg.ai4Arg[1];

    if(fgOn)
    {
        VDP_Pattern(ucVdpId, 1, 0, 0);
    }
    else
    {
        VDP_Pattern(ucVdpId, 98, 0, 0);
    }

    return MTR_OK;
}

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------



int mtal_ioctl_mtb2r(struct inode *inode, struct file *file, unsigned int cmd,
                     unsigned long arg)
{
    int i4Ret = 0;

    switch (cmd)
    {
    case MTAL_IO_B2R_GET_PTS:
        return _MTB2R_GetPts(arg);
    case MTAL_IO_B2R_GET_STEP_FORWARD:
        return _MTB2R_GetStepForward(arg);
    case MTAL_IO_B2R_GET_POS_INFO:
        return _MTB2R_GetPosInfo(arg);
    case MTAL_IO_B2R_GET_PIC_INFO:
        return _MTB2R_GetPicInfo(arg);
    case MTAL_IO_B2R_GET_PLAY_MODE:
        return _MTB2R_GetPlayMode(arg);
    case MTAL_IO_B2R_SET_GameMode:
         return _MTB2R_SetGameMode(arg);
    case MTAL_IO_B2R_GET_SLOW_FORWARD:
        return _MTB2R_GetSlowForward(arg);
    case MTAL_IO_B2R_SET_AB_INFO:
        return _MTB2R_SetABInfo(arg);
    case MTAL_IO_B2R_SET_THUMBNAIL_MODE:
        return _MTB2R_SetThumbnailMode(arg);
    case MTAL_IO_B2R_SET_SEEK:
        return _MTB2R_SetSeek(arg);
  #if defined(CC_MAPLE_CUST_DRV)
     case MTAL_IO_B2R_SET_SYC_MODE:
        return _MTB2R_SetSyncMode2(arg);
  #endif
    case MTAL_IO_B2R_SET_PAUSE_MM:
        return _MTB2R_SetPauseMM(arg);
    case MTAL_IO_B2R_SET_STEP_FORWARD:
        return _MTB2R_SetStepForward(arg);
    case MTAL_IO_B2R_SET_FB_NO_TIMEOUT:
        return _MTB2R_SetFBNoTimeout(arg);
    case MTAL_IO_B2R_SET_SPEED:
        return _MTB2R_SetSpeed(arg);
    case MTAL_IO_B2R_SET_TRICK_MODE:
        return _MTB2R_SetTrickMode(arg);
    case MTAL_IO_B2R_SET_INPUT:
        return _MTB2R_SetInput(arg);
    case MTAL_IO_B2R_SET_SLOW_FORWARD:
        return _MTB2R_SetSlowForward(arg);
    case MTAL_IO_B2R_GET_CAPTURE_INFO:
        return _MTB2R_GetCaptureInfo(arg);
    case MTAL_IO_B2R_GET_CAPTURE_INFO2:
        return _MTB2R_GetCaptureInfo2(arg);
    case MTAL_IO_B2R_SET_CB_ATTACH_ID:
        return _MTB2R_SetCbAttachedId(arg);
    case MTAL_IO_B2R_SELECT_GROUP_TYPE:
        return _MTB2R_SelectGroupType(arg);
    case MTAL_IO_B2R_GET_EMPTY_FRAME_BUFFER:
        return _MTB2R_GetEmptyFrameBuffer(arg);
    case MTAL_IO_B2R_SET_SEQ_HDR:
        return _MTB2R_SetSeqHdr(arg);
    case MTAL_IO_B2R_SET_DISP_FRAME:
        return _MTB2R_SetDispFrame(arg);
    case MTAL_IO_B2R_FLUSH_FRAME:
        return _MTB2R_FlushFrame(arg);
    case MTAL_IO_B2R_RELEASE_FBG:
        return _MTB2R_ReleaseFbg(arg);
    case MTAL_IO_B2R_FREE_FRAME_BUFFER:
        return _MTB2R_FreeFrameBuffer(arg);
    case MTAL_IO_B2R_GET_DISP_STABLE:
        return _MTB2R_GetDispDrvStable(arg);
    case MTAL_IO_B2R_SET_3D_INFO:
        return _MTB2R_Set3DInfo(arg);
    case MTAL_IO_B2R_SET_CHPTER_ENABLE:
        return _MTB2R_SetChpterEnable(arg);
	case MTAL_IO_B2R_SET_MIRROR:
        return _MTB2R_SetMirror(arg);
 //   #ifdef CC_B2R_RM_SUPPORT
    case MTAL_IO_B2R_RM_CALLBACK:
        return _MTVB2R_Reg_Callback();
    case MTAL_IO_B2R_RM_CONFLICT_DONE:
        return  _MTB2R_RmSet(arg);
  //  #endif
    case MTAL_IO_B2R_SET_AUD_TRIGGER:
        return _MTB2R_AudTrigger(arg);
    case MTAL_IO_B2R_REG_CB:
        return _MTB2R_RegCbFunc(arg);
    case MTAL_IO_B2R_SET_PAT:
        return _MTB2R_SetPatten(arg);
    case MTAL_IO_B2R_UNREG_CB:
        return _MTB2R_UnRegCbFunc(arg);
    default:
        break;
    }
    return i4Ret;
}
