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

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date$
 * $RCSfile: fbm_pool.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file fbm_pool.c
 *  Brief of file fbm_pool.c.
 *  FBM Pool Management
 */


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

#include "x_lint.h"
#include "fbm_pool.h"
#include "fbm_pool_config.h"
#include "fbm_debug.h"

#ifdef CC_SRM_ON
#include "srm_drvif.h"
#endif
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_SVP_SUPPORT)
#include "tz_if.h"
#endif

LINT_EXT_HEADER_BEGIN
#include "source_table.h"
#include "x_assert.h"
#include "x_hal_5381.h"
#include "drvcust_if.h"
#include "x_mid.h"
#include "x_dram.h"
#include "x_bim.h"
LINT_EXT_HEADER_END

#if defined(CC_ENABLE_CMA_SUPPORT)
//cma
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/soc/mediatek/x_linux.h>
#include <linux/platform_device.h>
//
#endif


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

//#define FBM_MPEG_POOL_MID_EN

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

// FBP Status
#define FBP_STATUS_UNKNOWN                          0xFF
#define FBP_STATUS_EMPTY                            0
#define FBP_STATUS_USED                             1
#define FBP_STATUS_OCCUPY                           2

// FBP Maximum Number
#define FBP_MAX_DISASSEMBLY                         4
#define FBP_MAX_NS                                  (FBG_MAX_NS * 3)

// Maximun residual pool number
#define FBM_RESIDUAL_POOL_NS                        4

//---------------------------------------------------------------------------
// Type definitions
//---------------------------------------------------------------------------

// Frame Buffer Pool
typedef struct
{
    UCHAR ucType;
    UCHAR ucStatus;
    UCHAR ucInheritance;

    UCHAR aucOccupyList[FBP_MAX_DISASSEMBLY];

    UINT32 u4Size;
    UPTR u4Addr;
    UINT32 u4AddrC;
    UINT32 u4MpegTotalYSize;
    UINT32 u4MpegTotalCSize;
    FBM_POOL_TYPE_T eFbmPoolType;
} FBP_T;

// Frame Buffer Pool Configuration
typedef struct
{
    UCHAR ucType;
    UPTR u4Addr;
    UPTR u4AddrC;
    UINT32 u4MpegTotalYSize;
    UINT32 u4MpegTotalCSize;
    FBM_POOL_TYPE_T eFbmPoolType;
} FBP_CONF_T;


//---------------------------------------------------------------------------
// Macro definitions
//---------------------------------------------------------------------------

#define FBM_MEMSET(addr, value, len)                    \
    VERIFY(x_memset((addr), value, len) == (addr))

#define FBM_POOL_MUTEX_LOCK()                              \
    VERIFY(x_sema_lock(_hFbmPoolMutex, X_SEMA_OPTION_WAIT) == OSR_OK)

#define FBM_POOL_MUTEX_UNLOCK()                            \
    VERIFY(x_sema_unlock(_hFbmPoolMutex) == OSR_OK)

#define FBM_CHECK_POOL_INDEX(idx)                                              \
    do                                                                         \
    {                                                                          \
        if ((idx) >= FBM_POOL_TYPE_NS)                                         \
        {                                                                      \
            ASSERT(0);                                                         \
            return NULL;                                                       \
        }                                                                      \
    }                                                                          \
    while (0)

//---------------------------------------------------------------------------
// Imported variables
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Imported functions
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Static function forward declarations
//---------------------------------------------------------------------------

#ifdef CC_SRM_ON
static VOID _FBM_SrmCtrlCb(UINT32 u4Arg1, UINT32 u4Arg2, UINT32 u4Arg3, UINT32 u4Arg4);
#endif
enum
{
    FBM_MULTI_TV,
    FBM_MULIT_MM,
    FBM_MULIT_NETWORK,
};
//---------------------------------------------------------------------------
// Static variables
//---------------------------------------------------------------------------
static POOL_ARRANGE_INFO_T arPoolArrangeInfo[FBM_POOL_TYPE_NS];
#if defined(CC_EDB_FBM_SHARE_MEM)
UINT32 _gu4EDBSize = 0xc00000;
UINT32 _gu4EDBAddr = 0xffffffff;
#endif
// Frame Buffer Memory Pool Type List
static POOL_LIST_T _arPoolList[] =
{
    //DMX
    {
        "DMX",
        FBM_POOL_TYPE_DMX,
        FBM_DMX_ADDR_ALIGMENT, FBM_DMX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //TDC
    {
        "TDC",
        FBM_POOL_TYPE_TDC,
        FBM_TDC_ADDR_ALIGMENT, 0,
        0,
        0,
        720, 576,
        FBM_POOL_INHERIT
    },

    //TDC2
    {
        "TDC_2",
        FBM_POOL_TYPE_TDC_2,
        FBM_TDC_ADDR_ALIGMENT, 0,
        0,
        0,
        720, 576,
        FBM_POOL_INHERIT
    },

    //VBI
    {
        "VBI",
        FBM_POOL_TYPE_VBI,
        FBM_VBI_ADDR_ALIGMENT, 0,
        0,
        FBM_VBI_POOL_SIZE,
        0, 0,
        FBM_POOL_INHERIT
    },

    //VBI_2
    {
        "VBI_2",
        FBM_POOL_TYPE_VBI_2,
        FBM_VBI_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG
    {
        "MPEG",
        FBM_POOL_TYPE_MPEG,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MJC_1
    {
        "MJC_1",
        FBM_POOL_TYPE_MJC_1,
        FBM_MJC_ADDR_ALIGMENT, FBM_MJC_SIZE_ALIGMENT,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MPEG_TV
    {
        "MPEG_TV",
        FBM_POOL_TYPE_MPEG_TV,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG_NET
    {
        "MPEG_NET",
        FBM_POOL_TYPE_MPEG_NET,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SCPOS (Main)
    {
        "SCPOS_MAIN",
        FBM_POOL_TYPE_SCPOS_MAIN,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        1440, 576,
        FBM_POOL_INHERIT
    },

    //DMX_TV
    {
        "DMX_TV",
        FBM_POOL_TYPE_DMX_TV,
        FBM_DMX_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //DMX_NET
    {
        "DMX_NET",
        FBM_POOL_TYPE_DMX_NET,
        FBM_DMX_ADDR_ALIGMENT, 0,
        0,
        0,
        720, 576,
        FBM_POOL_INHERIT
    },

    //FEEDER_NET
    {
        "FEEDER_NET",
        FBM_POOL_TYPE_FEEDER_NET,
        FBM_FEEDER_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SCPOS (Pip)
    {
        "SCPOS_PIP",
        FBM_POOL_TYPE_SCPOS_PIP,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        960, 540,
        FBM_POOL_INHERIT
    },

    //Feeder
    {
        "Feeder",
        FBM_POOL_TYPE_FEEDER,
        FBM_FEEDER_ADDR_ALIGMENT, FBM_FEEDER_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //Feeder MMP (for turnkey MMP)
    {
        "Feeder_MMP",
        FBM_POOL_TYPE_FEEDER_MMP,
        FBM_FEEDER_ADDR_ALIGMENT, FBM_FEEDER_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MDDI_1
    {
        "MDDI_1",
        FBM_POOL_TYPE_MDDI_1,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //PQ_MM
    {
        "PQ_MM",
        FBM_POOL_TYPE_PQ_MM,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //PQ_NET
    {
        "PQ_NET",
        FBM_POOL_TYPE_PQ_NET,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //PQ_TV
    {
        "PQ_TV",
        FBM_POOL_TYPE_PQ_TV,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //NET SWAP
    {
        "NET_SWAP",
        FBM_POOL_TYPE_NET_SWAP,
        0, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //TDC_DYN
    {
        "TDC_DYN",
        FBM_POOL_TYPE_TDC_DYN,
        FBM_TDC_ADDR_ALIGMENT, 0,
        0,
        0,
        720, 576,
        FBM_POOL_INHERIT
    },

    //SCPOS_DYN_MAIN
    {
        "SCPOS_DYN_MAIN",
        FBM_POOL_TYPE_SCPOS_DYN_MAIN,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MDDI_DYN_MAIN
    {
        "MDDI_DYN_MAIN",
        FBM_POOL_TYPE_MDDI_DYN_MAIN,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },
    //SCPOS_DYN_SUB
    {
        "SCPOS_DYN_SUB",
        FBM_POOL_TYPE_SCPOS_DYN_SUB,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MDDI_DYN_SUB
    {
        "MDDI_DYN_SUB",
        FBM_POOL_TYPE_MDDI_DYN_SUB,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MDDI (Pip)
    {
        "MDDI_P",
        FBM_POOL_TYPE_MDDI_PIP,
        FBM_MDDI_ADDR_ALIGMENT, 0,
        0,
        0,
        960, 1080,
        FBM_POOL_INHERIT
    },

    //NR_1
    {
        "NR_1",
        FBM_POOL_TYPE_NR_1,
        FBM_NR_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //DSP
    {
        "DSP",
        FBM_POOL_TYPE_DSP,
        FBM_DSP_ADDR_ALIGMENT, 0,
        0,
        FBM_DSP_POOL_SIZE,
        0, 0,
        FBM_POOL_INHERIT
    },

    //B2R
    {
        "B2R",
        FBM_POOL_TYPE_B2R,
        FBM_B2R_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1088,
        FBM_POOL_INHERIT
    },

    //JPEG
    {
        "JPEG",
        FBM_POOL_TYPE_JPEG,
        FBM_JPEG_ADDR_ALIGMENT, 0,
        0,
        FBM_JPEG_POOL_SIZE,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //OSD
    {
        "JPEG-OSD1",
        FBM_POOL_TYPE_JPEG_OSD1,
        FBM_OSD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //OSD
    {
        "JPEG-OSD2",
        FBM_POOL_TYPE_JPEG_OSD2,
        FBM_OSD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //OSD
    {
        "JPEG-OSD3",
        FBM_POOL_TYPE_JPEG_OSD3,
        FBM_OSD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //OSD
    {
        "JPEG-OSD4",
        FBM_POOL_TYPE_JPEG_OSD4,
        FBM_OSD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //PQ_TOOL
    {
        "PQ-TOOL",
        FBM_POOL_TYPE_PQ_TOOL,
        FBM_PQ_TOOL_ADDR_ALIGMENT, FBM_PQ_TOOL_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //OD
    {
        "OD",
        FBM_POOL_TYPE_OD,
        FBM_OD_ADDR_ALIGMENT, FBM_OD_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //VENC
    {
        "VENC",
        FBM_POOL_TYPE_VENC,
        FBM_VENC_ADDR_ALIGMENT, FBM_VENC_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SWDMX
    {
        "SWDMX",
        FBM_POOL_TYPE_SWDMX,
        FBM_SWDMX_ADDR_ALIGMENT, FBM_SWDMX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FACEDET
    {
        "FACEDET",
        FBM_POOL_TYPE_FACEDET,
        FBM_FD_ADDR_ALIGMENT, FBM_FD_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FBM_POOL_TYPE_MPEG_FREE
    {
        "FBM_POOL_TYPE_MPEG_FREE",
        FBM_POOL_TYPE_MPEG_FREE,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FBM_POOL_TYPE_DIVA
    {
        "FBM_POOL_TYPE_DIVA",
        FBM_POOL_TYPE_DIVA,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //Feeder2
    {
        "Feeder2",
        FBM_POOL_TYPE_FEEDER2,
        FBM_FEEDER_ADDR_ALIGMENT, FBM_FEEDER_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //DMX2
    {
        "DMX2",
        FBM_POOL_TYPE_DMX2,
        FBM_DMX_ADDR_ALIGMENT, FBM_DMX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG2
    {
        "MPEG2",
        FBM_POOL_TYPE_MPEG2,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //PVR
    {
        "PVR",
        FBM_POOL_TYPE_PVR,
        FBM_PVR_ADDR_ALIGMENT, FBM_PVR_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //PVR2
    {
        "PVR2",
        FBM_POOL_TYPE_PVR2,
        FBM_PVR2_ADDR_ALIGMENT, FBM_PVR2_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //JPG_VDP
    {
        "JPG_VDP",
        FBM_POOL_TYPE_JPG_VDP,
        FBM_JPG_VDP_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },
    //PNG
    {
        "PNG",
        FBM_POOL_TYPE_PNG,
        FBM_PNG_ADDR_ALIGMENT, FBM_PNG_SIZE_ALIGMENT,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    // DIVX
    {
        "DIVX",
        FBM_POOL_TYPE_DIVX,
        FBM_DIVX_ADDR_ALIGMENT, FBM_DIVX_SIZE_ALIGMENT,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },

    //MPEG3
    {
        "MPEG3",
        FBM_POOL_TYPE_MPEG3,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },
    //Video screen Shot
    {
        "VSS",
        FBM_POOL_TYPE_VSS,
        FBM_VSS_ADDR_ALIGMENT, FBM_VSS_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //DMXPID
    {
        "DMXPID",
        FBM_POOL_TYPE_DMXPID,
        FBM_DMXPID_ADDR_ALIGMENT, 64-1,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //IMGRZ_3D_KR
    {
        "IMGRZ_3D_KR",
        FBM_POOL_TYPE_IMGRZ_3D_KR,
        63, 63,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FBM_POOL_TYPE_DRM
    {
        "DRM",
        FBM_POOL_TYPE_DRM,
        FBM_DRM_ADDR_ALIGMENT, 4096-1,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FBM_POOL_TYPE_MUXER
    {
        "MUXER",
        FBM_POOL_TYPE_MUXER,
        FBM_MUXER_ADDR_ALIGMENT, 2048-1,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //FBM_POOL_TYPE_PQ_3DC
    {
        "PQ_3DC",
        FBM_POOL_TYPE_PQ_3DC,
        FBM_PQ_3DC_ADDR_ALIGMENT, FBM_PQ_3DC_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //PQ_PSCAN
    {
        "PQ_PSCAN",
        FBM_POOL_TYPE_PQ_PSCAN,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SUBTITLE
    {
        "SUBTITLE",
        FBM_POOL_TYPE_SUBTITLE,
        FBM_SUBTITLE_ADDR_ALIGMENT, 4096-1,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //DMX3
    {
        "DMX3",
        FBM_POOL_TYPE_DMX3,
        FBM_DMX_ADDR_ALIGMENT, FBM_DMX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //FEEDER3
    {
        "Feeder3",
        FBM_POOL_TYPE_FEEDER3,
        FBM_FEEDER_ADDR_ALIGMENT, FBM_FEEDER_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //EDB
    {
        "EDB",
        FBM_POOL_TYPE_EDB,
        FBM_EDB_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },
    //TVE
    {
        "TVE",
        FBM_POOL_TYPE_TVE,
        FBM_TVE_ADDR_ALIGMENT, 0,
        0,
        0,
        720, 576,
        FBM_POOL_INHERIT
    },

    //4K*2K
    {
        "4K*2K ",
        FBM_POOL_TYPE_4K_2K_SCALER,
        FBM_SCPOS_ADDR_ALIGMENT, 0,
        0,
        0,
        3840, 2160,
        FBM_POOL_INHERIT
    },
    //DSP_BIN
    {
        "DSP_BIN",
        FBM_POOL_TYPE_DSP_BIN,
        FBM_DSP_BIN_ADDR_ALIGMENT, FBM_DSP_BIN_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //photo share
    {
        "photo_share ",
        FBM_POOL_TYPE_PHOTO_SHARE,
        4096-1, 4096-1,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //BEIC
    {
        "BEIC",
        FBM_POOL_TYPE_BEIC,
        FBM_VENC_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MPEG4
    {
        "MPEG4",
        FBM_POOL_TYPE_MPEG4,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        1920, 1080,
        FBM_POOL_INHERIT
    },
    //Feeder4
    {
        "Feeder4",
        FBM_POOL_TYPE_FEEDER4,
        FBM_FEEDER_ADDR_ALIGMENT, FBM_FEEDER_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //DMX4
    {
        "DMX4",
        FBM_POOL_TYPE_DMX4,
        FBM_DMX_ADDR_ALIGMENT, FBM_DMX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG1_C
    {
        "MPEG_C",
        FBM_POOL_TYPE_MPEG_C,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG2_C
    {
        "MPEG2_C",
        FBM_POOL_TYPE_MPEG2_C,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },


    //MPEG3_C
    {
        "MPEG3_C",
        FBM_POOL_TYPE_MPEG3_C,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //MPEG4_C
    {
        "MPEG4_C",
        FBM_POOL_TYPE_MPEG4_C,
        FBM_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //W2D/R2R
    {
        "W2D_R2R",
        FBM_POOL_TYPE_W2D_R2R,
        FBM_W2D_R2R_ADDR_ALIGMENT, FBM_W2D_R2R_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //W2D/R2R_Y
    {
        "W2D_R2R_Y",
        FBM_POOL_TYPE_W2D_R2R_Y,
        FBM_W2D_R2R_ADDR_ALIGMENT, FBM_W2D_R2R_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SCPOS_PIP2
    {
        "SCPOS_PIP2",
        FBM_POOL_TYPE_SCPOS_PIP2,
        FBM_SCPOS_ADDR_ALIGMENT, FBM_SCPOS_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //SRS
    {
        "SRS",
        FBM_POOL_TYPE_SRS,
        FBM_SRS_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //Remux
    {
        "Remux",
        FBM_POOL_TYPE_REMUX,
        FBM_REMUX_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //hw_demod
    {
        "hw_demod",
        FBM_POOL_TYPE_HW_DEMOD,
        FBM_HW_DEMOD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //secure feeder
    {
        "secure feeder",
        FBM_POOL_TYPE_SECURE_FEEDER,
        FBM_SECURE_FEEDER_ADDR_ALIGMENT , 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //rest Mem
    {
        "REST_MEM",
        FBM_POOL_TYPE_REST_MEM,
        0x1000 -1 , 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //W2D/R2R CHA
    {
        "W2D_R2R_CHA",
        FBM_POOL_TYPE_W2D_R2R_CHA,
        FBM_W2D_R2R_ADDR_ALIGMENT, FBM_W2D_R2R_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //W2D/R2R CHA
    {
        "GFX",
        FBM_POOL_TYPE_GFX,
        FBM_GFX_ADDR_ALIGMENT, FBM_GFX_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS1
    {
        "SEAML1",
        FBM_POOL_TYPE_SEAML1,
        FBM_SEAML1_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS2
    {
        "SEAML2",
        FBM_POOL_TYPE_SEAML2,
        FBM_SEAML2_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS3
    {
        "SEAML3",
        FBM_POOL_TYPE_SEAML3,
        FBM_SEAML3_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS4
    {
        "SEAML4",
        FBM_POOL_TYPE_SEAML4,
        FBM_SEAML4_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS1_C
    {
        "SEAML1_C",
        FBM_POOL_TYPE_SEAML1_C,
        FBM_SEAML1_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS2_C
    {
        "SEAML2_C",
        FBM_POOL_TYPE_SEAML2_C,
        FBM_SEAML2_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS3_C
    {
        "SEAML3_C",
        FBM_POOL_TYPE_SEAML3_C,
        FBM_SEAML3_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SEAMLESS4_C
    {
        "SEAML4_C",
        FBM_POOL_TYPE_SEAML4_C,
        FBM_SEAML4_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //VENC OUT
    {
        "VENC_OUT",
        FBM_POOL_TYPE_VENC_OUT,
        FBM_VENC_ADDR_ALIGMENT, FBM_VENC_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SLT_GFX
    {
        "SLT_GFX",
        FBM_POOL_TYPE_SLT_GFX,
        FBM_SLT_GFX_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //dram hotboot calibration in channelA
    {
        "CALIBR_A",
        FBM_POOL_TYPE_DRAMHOTBOOTCALIBR_A,
        FBM_CALIBRATION_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //dram hotboot calibration in channelB
    {
        "CALIBR_B",
        FBM_POOL_TYPE_DRAMHOTBOOTCALIBR_B,
        FBM_CALIBRATION_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //dram hotboot calibration in channelC
    {
        "CALIBR_C",
        FBM_POOL_TYPE_DRAMHOTBOOTCALIBR_C,
        FBM_CALIBRATION_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //VDEC LAX1
    {
        "VDEC_LAX1",
        FBM_POOL_TYPE_LAX1,
        FBM_LAX1_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //VDEC LAX2
    {
        "VDEC_LAX2",
        FBM_POOL_TYPE_LAX2,
        FBM_LAX2_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC1
    {
        "MJC1",
        FBM_POOL_TYPE_MJC1,
        FBM_MJC1_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC2
    {
        "MJC2",
        FBM_POOL_TYPE_MJC2,
        FBM_MJC2_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC3
    {
        "MJC3",
        FBM_POOL_TYPE_MJC3,
        FBM_MJC3_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC1_C
    {
        "MJC1_C",
        FBM_POOL_TYPE_MJC1_C,
        FBM_MJC1_C_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC2_C
    {
        "MJC2_C",
        FBM_POOL_TYPE_MJC2_C,
        FBM_MJC2_C_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC3_C
    {
        "MJC3_C",
        FBM_POOL_TYPE_MJC3_C,
        FBM_MJC3_C_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC_MV
    {
        "MJCMV",
        FBM_POOL_TYPE_MJCMV,
        FBM_MJCMV_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //TNR_DYN_MAIN
    {
        "TNR_DYN_MAIN",
        FBM_POOL_TYPE_TNR_DYN_MAIN,
        FBM_TNR_ADDR_ALIGMENT, 0,
        0,
        0,
        3840, 2160,
        FBM_POOL_INHERIT
    },
    //DYN_MPEG
    {
        "DYN_MPEG",
        FBM_POOL_TYPE_DYN_MPEG,
        FBM_DYN_MPEG_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //DYN_MPEG2
    {
        "DYN_MPEG2",
        FBM_POOL_TYPE_DYN_MPEG2,
        FBM_DYN_MPEG2_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //PAD
    {
        "PAD",
        FBM_POOL_TYPE_PAD,
        FBM_PAD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //RAMOOPS
    {
        "RAMOOPS",
        FBM_POOL_TYPE_RAMOOPS,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MTDFB
    {
        "MTDFB",
        FBM_POOL_TYPE_MTDFB,
        FBM_MTDFB_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MTFB
    {
        "MTFB",
        FBM_POOL_TYPE_MTFB,
        FBM_MTFB_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-EWS
    {
        "SHMEWS",
        FBM_POOL_TYPE_SHMEWS,
        FBM_SHMEWS_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-TSRQUE
    {
        "SHMTSRQUE",
        FBM_POOL_TYPE_SHMTSRQUE,
        FBM_SHMTSRQUE_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-ISDBCC
    {
        "SHMISDBCC",
        FBM_POOL_TYPE_SHMISDBCC,
        FBM_SHMISDBCC_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-SSMA
    {
        "SHMSSMA",
        FBM_POOL_TYPE_SHMSSMA,
        FBM_SHMSSMA_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-VBIF
    {
        "SHMVBIF",
        FBM_POOL_TYPE_SHMVBIF,
        FBM_SHMVBIF_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-ATV TIMESHIFT
    {
        "SHMATVTS",
        FBM_POOL_TYPE_SHMATVTS,
        FBM_SHMATVTS_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-MUXER
    {
        "SHMMUXER",
        FBM_POOL_TYPE_SHMMUXER,
        FBM_SHMMUXER_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-THUMBNAIL
    {
        "THUMBNAIL",
        FBM_POOL_TYPE_THUMBNAIL,
        FBM_THUMBNAIL_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //SHM-SOUNDCLIP
    {
        "SOUNDCLIP",
        FBM_POOL_TYPE_SOUNDCLIP,
        FBM_SOUNDCLIP_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //DTCPIP
    {
        "DTCPIP",
        FBM_POOL_TYPE_DTCPIP,
        FBM_DTCPIP_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //VDEC LAX3
    {
        "VDEC_LAX3",
        FBM_POOL_TYPE_LAX3,
        FBM_LAX3_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //VDEC LAX4
    {
        "VDEC_LAX4",
        FBM_POOL_TYPE_LAX4,
        FBM_LAX4_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJCALL
    {
        "MJCALL",
        FBM_POOL_TYPE_MJCALL,
        FBM_MJCALL_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //W2D/R2R_CR
    {
        "W2D_R2R_CR",
        FBM_POOL_TYPE_W2D_R2R_CR,
        FBM_W2D_R2R_ADDR_ALIGMENT, FBM_W2D_R2R_SIZE_ALIGMENT,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC_R20
    {
        "MJC_R20",
        FBM_POOL_TYPE_MJC_R20,
        FBM_MJC_R20_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC_R21
    {
        "MJC_R21",
        FBM_POOL_TYPE_MJC_R21,
        FBM_MJC_R21_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //LD
    {
        "LD",
        FBM_POOL_TYPE_LD,
        FBM_LD_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //3DLUT
    {
        "3DLUT",
        FBM_POOL_TYPE_3DLUT,
        FBM_3DLUT_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //ATSC30ALP
    {
        "ATSC30ALP",
        FBM_POOL_TYPE_ATSC30ALP,
        FBM_ATSC30ALP_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //MJC_R20_SHM
    {
        "MJC_R20_SHM",
        FBM_POOL_TYPE_MJC_R20_SHM,
        FBM_MJC_R20_SHM_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    //HDMI_SHM
    {
        "HDMI_SHM",
        FBM_POOL_TYPE_HDMI_SHM,
        FBM_HDMI_SHM_ADDR_ALIGMENT, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
    {
        "TOTAL2",
        FBM_POOL_TYPE_TOTAL2,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    {
        "TOTAL3",
        FBM_POOL_TYPE_TOTAL3,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },

    //TOTAL
    {
        "TOTAL",
        FBM_POOL_TYPE_TOTAL,
        0, 0,
        0,
        0,
        0, 0,
        FBM_POOL_INHERIT
    },
};

static const UINT32 _u4PoolListNs = (UINT32)FBM_POOL_TYPE_NS;


//mt539x Frame Buffer Group Type List, size of _arFbpList[n] > size of _arFbpList[n + 1]
static FBP_LIST_T _arFbpAllList[] =
{
#ifdef CC_SUPPORT_PHOTO8K
    {
        FBM_FBG_TYPE_8K,
        0,
        0,
        FBM_FBG_TYPE_8K_Y_SIZE,
        FBM_FBG_TYPE_8K_C_SIZE,
        FBM_FBG_8K_H,
        FBM_FBG_8K_V
    },
#endif
#ifdef FBM_4K2K_JPG_SUPPORT
    {
        FBM_FBG_TYPE_4K2K_JPEG,
        FBM_FBG_TYPE_4K2K_JPEG_SIZE,
        FBM_FBG_TYPE_4K2K_JPEG_C_SIZE,
        FBM_FBG_JPEG_4K2K_Y_SIZE,
        FBM_FBG_JPEG_4K2K_C_SIZE,
        FBM_FBG_4K_JPEG_H,
        FBM_FBG_4K_JPEG_V
    },
#endif
#ifdef FBM_4K2K_SUPPORT
    {
        FBM_FBG_TYPE_4K2K_EXTRA,
        FBM_FBG_TYPE_4K2K_7FB_SIZE_PART2,
        FBM_FBG_TYPE_4K2K_7FB_SIZE_C_PART2,
        FBM_FBG_TYPE_4K2K_Y_SIZE,
        FBM_FBG_TYPE_4K2K_C_SIZE,
        FBM_FBG_4K2K_H,
        FBM_FBG_4K2K_V
    },
    {
        FBM_FBG_TYPE_4K2K,
        FBM_FBG_TYPE_4K2K_7FB_SIZE_PART1,
        FBM_FBG_TYPE_4K2K_7FB_SIZE_C_PART1,
        FBM_FBG_TYPE_4K2K_Y_SIZE,
        FBM_FBG_TYPE_4K2K_C_SIZE,
        FBM_FBG_4K2K_H,
        FBM_FBG_4K2K_V
    },
#endif
    {
        FBM_FBG_TYPE_SBSHD,
        FBM_FBG_TYPE_1080HD_H264_SIZE*2,
        FBM_FBG_TYPE_SBSHD_Y_SIZE,
        FBM_FBG_TYPE_SBSHD_C_SIZE,
        FBM_FBG_SBSHD_H,
        FBM_FBG_SBSHD_V
    },
    {
        FBM_FBG_TYPE_TNBHD,
        FBM_FBG_TYPE_1080HD_H264_SIZE*2,
        FBM_FBG_TYPE_1080HD_H264_C_SIZE*2,
        FBM_FBG_TYPE_TNBHD_Y_SIZE,
        FBM_FBG_TYPE_TNBHD_C_SIZE,
        FBM_FBG_TNBHD_H,
        FBM_FBG_TNBHD_V
    },
    {
        FBM_FBG_TYPE_1080HD,
        FBM_FBG_TYPE_1080HD_H265_SIZE,
        FBM_FBG_TYPE_1080HD_H265_C_SIZE,
        FBM_FBG_TYPE_1080HD_Y_SIZE,
        FBM_FBG_TYPE_1080HD_C_SIZE,
        FBM_FBG_1080HD_H,
        FBM_FBG_1080HD_V
    },
    {
        FBM_FBG_TYPE_720HD,
        FBM_FBG_TYPE_720HD_H265_SIZE,
        FBM_FBG_TYPE_720HD_H265_C_SIZE,
        FBM_FBG_TYPE_720HD_Y_SIZE,
        FBM_FBG_TYPE_720HD_C_SIZE,
        FBM_FBG_720HD_H,
        FBM_FBG_720HD_V
    },
    {
        FBM_FBG_TYPE_PAL,
        FBM_FBG_TYPE_PAL_H265_SIZE,
        FBM_FBG_TYPE_PAL_H265_C_SIZE,
        FBM_FBG_TYPE_PAL_Y_SIZE,
        FBM_FBG_TYPE_PAL_C_SIZE,
        FBM_FBG_PAL_H,
        FBM_FBG_PAL_V
    },

};




static FBP_LIST_T* _arFbpList = NULL;

static UCHAR _ucFbpListNs = 0;

// Frame Buffer Pool Configuration
// 1 HD System
#if defined(CC_FBM_FOUR_INST_SUPPORT) || defined (CC_FBM_TWO_4K2K)
#define FBM_FBP_NS 4
#elif defined(CC_FBM_TWO_FBP) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB) || defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_SUPPORT_4K2K)
#define FBM_FBP_NS 2
#else
#define FBM_FBP_NS 1
#endif

static FBP_CONF_T _arFbpConf[FBM_FBP_NS] =
{
    {FBM_FBG_TYPE_1080HD,   (UPTR)NULL},
};

static UCHAR _ucFbpConfNs = FBM_FBP_NS;

// frame buffer pool structure
static FBP_T *_prFbp[FBP_MAX_NS];

// frame buffer pool number
static UCHAR _ucFbpNs = 0;

static FBM_POOL_T _arPool[FBM_POOL_TYPE_NONE];

#if defined(CC_ENABLE_CMA_SUPPORT)
static CMA_POOL_T _cmaPool[FBM_POOL_TYPE_NONE];
#endif


#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_SVP_SUPPORT)
FBM_POOL_T _arPoolTZ[FBM_POOL_TYPE_TZ_NS];
#endif

//  frame buffer pool memory address
static UPTR u4FbMallocAddr = (UPTR)NULL;

#ifndef CC_MEM_TOOL
// FBM call back function
static FBM_CB_FUNC_T* _prFbmCbFunc = NULL;
#endif

// Current Frame Buffer Pool
static FBM_POOL_T _rCurrentMpeg;

static HANDLE_T _hFbmPoolMutex;

static UINT32 _u4SumOfRoot;

//---------------------------------------------------------------------------
// Static functions
//---------------------------------------------------------------------------

/*----------------------------------------------------------------------------
 * Function:
 *
 * Description:
 *      Enable Memory Intrusion Detection for RO region
 *
 * Inputs: -
 *
 * Outputs: -
 *
 * Returns: -
 *---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
// Inter-file functions
//---------------------------------------------------------------------------

UPTR FBM_GetCHBStartAddr(void)
{
    UINT32 u4Val;
    UPTR   u4Addr;
    u4Val =(IO_READ32(DRAM_DMARB_BASE, 0x0) >> 20) & 0x7;
    switch(u4Val)
    {
#if defined(CC_MT5891)
        case 0x3:
            u4Addr=0x20000000;
            break;
        case 0x4:
            u4Addr=0x40000000;
            break;
        case 0x5:
            u4Addr=0x40000000;
            break;
        default:
            u4Addr=0x40000000;
            break;
#elif defined(CC_MT5886)
        case 0x2:
            u4Addr=0x20000000;
            break;
        case 0x3:
            u4Addr=0x20000000;
            break;
        case 0x4:
            u4Addr=0x40000000;
            break;
        case 0x5:
            u4Addr=0x40000000;
            break;
        default:
            u4Addr=0x40000000;
            break;
#elif defined(CC_MT5893)
        case 0x2:
            u4Addr=0x100000000;// 4Gbyte
            break;
        default:
            u4Addr=0x100000000;// 4Gbyte
            break;
#else
        case 0x1:
            u4Addr=0x4000000;
            break;
        case 0x2:
            u4Addr=0x8000000;
            break;
        case 0x3:
            u4Addr=0x10000000;
            break;
        case 0x4:
            u4Addr=0x20000000;
            break;
        case 0x5:
            u4Addr=0x40000000;
            break;
        default:
            u4Addr=0x40000000;
            break;
#endif
    }
    return u4Addr;
}

UPTR FBM_GetCHCStartAddr(void)
{
    UINT32 u4Val;
    UPTR   u4Addr;
    u4Val =(IO_READ32(DRAM_DMARB_BASE, 0x0) >> 20) & 0x7;
    switch(u4Val)
    {
#if defined(CC_MT5891)
        case 0x3:
            u4Addr=0x40000000;
            break;
        case 0x4:
            u4Addr=0x60000000;
            break;
        case 0x5:
            u4Addr=0x80000000;
            break;
        default:
            u4Addr=0x80000000;
            break;
#elif defined(CC_MT5886)
        case 0x2:
            u4Addr=0x60000000;
            break;
        case 0x3:
            u4Addr=0x40000000;
            break;
        case 0x4:
            u4Addr=0x60000000;
            break;
        case 0x5:
            u4Addr=0x80000000;
            break;
        default:
            u4Addr=0x80000000;
            break;
#else
        case 0x1:
            u4Addr=0x8000000;
            break;
        case 0x2:
            u4Addr=0x10000000;
            break;
        case 0x3:
            u4Addr=0x20000000;
            break;
        case 0x4:
            u4Addr=0x40000000;
            break;
        case 0x5:
            u4Addr=0x80000000;
            break;
        default:
            u4Addr=0x80000000;
            break;
#endif
    }
    return u4Addr;
}

//-------------------------------------------------------------------------
/** _FBM_PoolInit
 *  Initialize this FBM pool
 *  @retval NONE
 */
//-------------------------------------------------------------------------
FBM_POOL_T* _FBM_PoolInit(VOID)
{
    UINT32 u4PoolIdx;
    UINT32 u4ListIdx;
    UINT32 u4MpegSize;
    UINT32 u4CSizeTotal;
    UINT32 u4PoolTpIdx;
    UINT32 u4PoolTpIdx2;
    UINT32 u4Size = 0;
    //UINT32 u4LastPoolIdx = 0;
    //UINT32 u4LastPoolSize = 0;

    UPTR u4FbmStartAddr;
#if defined(CC_FBM_2ND_CHANNEL)
    UPTR u4FbmStartAddr2;
#endif
#if defined(CC_FBM_3ND_CHANNEL)
    UPTR u4FbmStartAddr3;
#endif
    // create fbm semaphore
    VERIFY(x_sema_create(&_hFbmPoolMutex, X_SEMA_TYPE_MUTEX, X_SEMA_STATE_UNLOCK) == OSR_OK);

#if defined(CC_ENABLE_CMA_SUPPORT)
    FBM_MEMSET(_cmaPool, 0x0, FBM_POOL_TYPE_NONE * sizeof(CMA_POOL_T));
#endif

#ifndef CC_MEM_TOOL
    _prFbmCbFunc = FBM_GetCbFuncTbl();
#endif

    if (_FBM_NPTV_VIDEO_CONF == NULL)
    {
        _FBM_NPTV_VIDEO_CONF = (FBM_POOL_T (*)[FBM_VIDEO_AGENT_MAX])x_mem_alloc(sizeof(FBM_POOL_T)*FBM_VIDEO_AGENT_MAX*FBM_TYPE_ENV_MAX);
        if (_FBM_NPTV_VIDEO_CONF == NULL)
        {
            LOG(0, "Alloc buf instance fail \n");
            ASSERT(0);

            return NULL;
        }
        x_memset((void *)_FBM_NPTV_VIDEO_CONF, 0, sizeof(FBM_POOL_T)*FBM_VIDEO_AGENT_MAX*FBM_TYPE_ENV_MAX);
    }

#if defined(CC_DYNAMIC_FBMSRM_CONF)
    //if(0==DRVCUST_InitQuery(eGet2KModelSupport,&bSonyModelType))
    {
        if((FBMDynIs4KMode()))//if(bSonyModelType==0) //
        {
            SRMFBM_SetConf(FBM_MEM_CFG_MT5890_3DTV_4K);
            SRMFBM_CHB_SetConf(FBM_MEM_CFG_MT5890_3DTV_4K_CHB);
            SRMFBM_CHC_SetConf(FBM_MEM_CFG_MT5890_3DTV_4K_CHC);
        }
        else
        {
            SRMFBM_SetConf(FBM_MEM_CFG_MT5890_3DTV_2K80);
            SRMFBM_CHB_SetConf(FBM_MEM_CFG_MT5890_3DTV_2K80_CHB);
            SRMFBM_CHC_SetConf(FBM_MEM_CFG_MT5890_3DTV_2K80_CHC);
        }
    }
    u4FbmStartAddr = BSP_GetMemSize()- SRMFBM_GetConf();
#if defined(CC_FBM_2ND_CHANNEL)
#if defined(CC_TRUSTZONE_IN_CHB)
    u4FbmStartAddr2 = DRAM_CHB_START_ADDR + BSP_GetChBMemSize() - SRMFBM_CHB_GetConf() - DRVCUST_OptGet(eTrustzoneMemSize);
#else
    u4FbmStartAddr2 = DRAM_CHB_START_ADDR;
#endif
#endif

#if defined(CC_FBM_3ND_CHANNEL)
    u4FbmStartAddr3 = DRAM_CHC_START_ADDR;
#endif

#else
    u4FbmStartAddr = DRVCUST_OptGet(eFbmMemAddr);
#if defined(CC_FBM_2ND_CHANNEL)
    u4FbmStartAddr2 = DRVCUST_OptGet(eFbmMemChBStart);
#endif

#if defined(CC_FBM_3ND_CHANNEL)
    u4FbmStartAddr3 = DRAM_CHC_START_ADDR;
#endif
#endif
#ifdef CC_SRM_ON
    // Reg SRM Callback Function
    SRM_Init();
    // SRM_Pause();
    SRM_RegisterCB(SRM_MPEG_PIP_CTRL, _FBM_SrmCtrlCb);
#endif

    // double check
    for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
    {
        if (u4ListIdx != (UINT32)_arPoolList[u4ListIdx].eType)
        {
            LOG(0,"u4ListIdx %d eType %d\n",
                    u4ListIdx,
                    _arPoolList[u4ListIdx].eType);

            VERIFY(0);
        }
    }
    {
        _arFbpList = _arFbpAllList;
        _ucFbpListNs = sizeof(_arFbpAllList)/sizeof(FBP_LIST_T);

        LOG(0,"_ucFbpListNs %d\n",_ucFbpListNs);

        _arFbpConf[0].ucType = FBM_FBG_TYPE_1080HD;
    }

    for (u4ListIdx = 0; u4ListIdx < (UINT32) FBM_FBP_NS; u4ListIdx++)
    {
#ifdef FBM_4K2K_SUPPORT

        _arFbpConf[u4ListIdx].u4Addr = 0;

        if (u4ListIdx == 0)
        {
            _arFbpConf[u4ListIdx].ucType = FBM_FBG_TYPE_4K2K;

        }

        if (u4ListIdx == 1)
        {
            _arFbpConf[u4ListIdx].ucType = FBM_FBG_TYPE_4K2K_EXTRA;
        }
#else
        _arFbpConf[u4ListIdx].ucType = FBM_FBG_TYPE_1080HD;
        _arFbpConf[u4ListIdx].u4Addr = 0;
#endif
    }

#if defined(CC_FBM_INT_TWO_FBP)
    LOG(0,"please use CC_FBM_TWO_FBP_SHARED_WITH_DFB instead of CC_FBM_INT_TWO_FBP \n");
#error
#endif

    // init pool arrange info
    for (u4ListIdx = 0; u4ListIdx < (UINT32) FBM_POOL_TYPE_NS; u4ListIdx++)
    {
        arPoolArrangeInfo[u4ListIdx].eMode = FBM_POOL_ARRANGE_AFTER;
        arPoolArrangeInfo[u4ListIdx].ePool1 = FBM_POOL_TYPE_TOTAL;
        arPoolArrangeInfo[u4ListIdx].ePool2 = FBM_POOL_TYPE_TOTAL;
        arPoolArrangeInfo[u4ListIdx].u4Offset = 0;
        arPoolArrangeInfo[u4ListIdx].u1Ready = 0;
    }

    //    FBM_ConfigurePool(&_arPoolList, &arPoolArrangeInfo);
    FBM_ConfigurePool(_arPoolList, arPoolArrangeInfo);

    // Calculate mpeg total frame buffer size
    u4MpegSize = 0;
    u4CSizeTotal = 0;

#if defined(CC_FBM_TWO_FBP) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB) || defined(CC_VOMX_TV_COEXIST)
    for (u4PoolIdx = 0; u4PoolIdx < 1; u4PoolIdx++)
#else
        for (u4PoolIdx = 0; u4PoolIdx < _ucFbpConfNs; u4PoolIdx++)
#endif
        {
            for (u4ListIdx = 0; u4ListIdx < _ucFbpListNs; u4ListIdx++)
            {
                if (_arFbpConf[u4PoolIdx].ucType == _arFbpList[u4ListIdx].ucType)
                {
                    u4MpegSize += _arFbpList[u4ListIdx].u4Size;
                    u4CSizeTotal += _arFbpList[u4ListIdx].u4CTotalSize;
                }
            }
        }

#if defined(CC_SUPPORT_H264_10BIT)
    {
        u4MpegSize = u4MpegSize + (u4MpegSize >> 2); // 10bit: compact mode
        u4CSizeTotal =u4CSizeTotal + (u4CSizeTotal >> 2);
        LOG(1,"support compact mode (10bit) for h264 total Size 0x%x u4CSizeTotal 0x%0x\n",u4MpegSize,u4CSizeTotal);
    }
#endif



    LOG(0,"Before 4k2k, MPEG1 (Y+MV)Size:0x%x; (C)Size 0x%x MPEG2 (Y+MV)Size:0x%x (C)Size 0x%x\n",
            _arPoolList[FBM_POOL_TYPE_MPEG].u4PoolSize,
            _arPoolList[FBM_POOL_TYPE_MPEG_C].u4PoolSize,
            _arPoolList[FBM_POOL_TYPE_MPEG2].u4PoolSize,
            _arPoolList[FBM_POOL_TYPE_MPEG2_C].u4PoolSize);
    // change the default pool Conf. note the place of the opration!!!
    // after calculates the MPEG1/2 pool size and before  _arFbpConf[x].ucType is been used!
    if (u4FbMallocAddr == (UPTR)NULL)
    {
        UPTR u4Start;
        UPTR u4End;
        UINT32 u4MaxAddrAlign;
        UINT32 u4ReservedSize;
        UINT32 u4Ready;

        // Calculate Total Size
        u4Size = 0;
        for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
        {
            if ((_arPoolList[u4ListIdx].u4Inherit == FBM_POOL_ROOT) &&
                    (_arPoolList[u4ListIdx].eType != FBM_POOL_TYPE_TOTAL))
            {
                u4Size += _arPoolList[u4ListIdx].u4PoolSize;
            }
        }
        _u4SumOfRoot = u4Size;
        u4ReservedSize = DRVCUST_OptGet(eFbmMemSize);
        if (u4ReservedSize < u4Size)
        {
            LOG(0,"FBM size is not enough before allocate, reserved=0x%x, required=0x%x\n", u4ReservedSize, u4Size);
            for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
            {
                if ((_arPoolList[u4ListIdx].u4Inherit == FBM_POOL_ROOT) &&
                        (_arPoolList[u4ListIdx].eType != FBM_POOL_TYPE_TOTAL)&&
                        (_arPoolList[u4ListIdx].u4PoolSize != 0))
                {
                    LOG(0,"FBM Root, %s , size=0x%x \n",_arPoolList[u4ListIdx].szName, _arPoolList[u4ListIdx].u4PoolSize);
                }
            }
            ASSERT(0);
        }

        // handle total pool
        u4MaxAddrAlign = 0;
        for (u4PoolTpIdx = 0; u4PoolTpIdx < (UINT32)FBM_POOL_TYPE_NS; u4PoolTpIdx++)
        {
            if (_arPoolList[u4PoolTpIdx].u4AddrAlign > u4MaxAddrAlign)
            {
                u4MaxAddrAlign = _arPoolList[u4PoolTpIdx].u4AddrAlign;
            }
        }
        // _arPool[FBM_POOL_TYPE_TOTAL].u4Addr = FBM_ALIGN_MASK((UINT32)(u4FbmStartAddr)-u4MaxAddrAlign, u4MaxAddrAlign); // keep it for history...
        _arPool[FBM_POOL_TYPE_TOTAL].u4Addr = FBM_ALIGN_MASK((UPTR)(u4FbmStartAddr), u4MaxAddrAlign);
#ifdef CC_DYNAMIC_FBMSRM_CONF
        _arPool[FBM_POOL_TYPE_TOTAL].u4Size = (UINT32)SRMFBM_GetConf();
        arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL].u1Ready = 1;

#if defined(CC_FBM_2ND_CHANNEL)
        _arPool[FBM_POOL_TYPE_TOTAL2].u4Addr = u4FbmStartAddr2;
        _arPool[FBM_POOL_TYPE_TOTAL2].u4Size = (UINT32)SRMFBM_CHB_GetConf();
        arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL2].u1Ready = 1;
#endif
#if defined(CC_FBM_3ND_CHANNEL)
        _arPool[FBM_POOL_TYPE_TOTAL3].u4Addr = u4FbmStartAddr3;
        _arPool[FBM_POOL_TYPE_TOTAL3].u4Size = (UINT32)SRMFBM_CHC_GetConf();
        arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL3].u1Ready = 1;
#endif
#else
        _arPool[FBM_POOL_TYPE_TOTAL].u4Size = (UINT32)DRVCUST_OptGet(eFbmMemSize);
        arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL].u1Ready = 1;

#if defined(CC_FBM_2ND_CHANNEL)
        _arPool[FBM_POOL_TYPE_TOTAL2].u4Addr = u4FbmStartAddr2;
        _arPool[FBM_POOL_TYPE_TOTAL2].u4Size = (UINT32)DRVCUST_OptGet(eFbmMemChBSize);
        arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL2].u1Ready = 1;
#endif
#if defined(CC_FBM_3ND_CHANNEL)
        if(IS_IC_5861())
        {
            _arPool[FBM_POOL_TYPE_TOTAL3].u4Addr = 0;
            _arPool[FBM_POOL_TYPE_TOTAL3].u4Size = 0;
            arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL3].u1Ready = 0;
        }
        else
        {
            _arPool[FBM_POOL_TYPE_TOTAL3].u4Addr = u4FbmStartAddr3;
            _arPool[FBM_POOL_TYPE_TOTAL3].u4Size = (UINT32)DRVCUST_OptGet(eFbmMemChCSize);
            arPoolArrangeInfo[FBM_POOL_TYPE_TOTAL3].u1Ready = 1;
        }
#endif
#endif
        // handle non-inherit pool
        do
        {
            for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
            {
                _arPool[u4ListIdx].fgAlloced = FALSE;
                if ((_arPoolList[u4ListIdx].u4Inherit == FBM_POOL_ROOT) &&
                        (arPoolArrangeInfo[u4ListIdx].u1Ready == 0))
                {
                    if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_AFTER)
                    {
                        FBM_POOL_TYPE_T eAheadPool;
                        eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;
                        if ((UINT32)eAheadPool >= FBM_POOL_TYPE_NS)
                        {
                            ASSERT(TRUE);
                            continue;
                        }

                        if (eAheadPool == FBM_POOL_TYPE_TOTAL)
                        {
                            // start from the begining
                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4FbmStartAddr, _arPoolList[u4ListIdx].u4AddrAlign);
                            _arPool[FBM_POOL_TYPE_TOTAL].u4Addr = _arPool[u4ListIdx].u4Addr;
                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#if defined(CC_FBM_2ND_CHANNEL)
                        else if (eAheadPool == FBM_POOL_TYPE_TOTAL2)
                        {
                            // start from the begining
                            _arPool[u4ListIdx].u4Addr = u4FbmStartAddr2;;

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#endif
#if defined(CC_FBM_3ND_CHANNEL)
                        else if (eAheadPool == FBM_POOL_TYPE_TOTAL3)
                        {
                            // start from the begining
                            _arPool[u4ListIdx].u4Addr = u4FbmStartAddr3;;

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#endif

                        else
                        {
                            // after another pool
                            // check 'ahead pool' ready or not
                            if (arPoolArrangeInfo[eAheadPool].u1Ready != 0)
                            {
                                u4Start = _arPool[eAheadPool].u4Addr;
                                u4Start += _arPool[eAheadPool].u4Size;
                                u4Start += FBM_POOL_PADDING_SIZE;

                                _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                                arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                                _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                                _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                                _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                                _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                                _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                            }

                            ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool);
                        }
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_BEFORE)
                    {
                        FBM_POOL_TYPE_T eBehindPool;
                        eBehindPool = arPoolArrangeInfo[u4ListIdx].ePool1;

                        // check 'behind pool' ready or not
                        if (eBehindPool == FBM_POOL_TYPE_NS)
                        {
#if defined(CC_MT5891) || defined(CC_MT5886)
#if defined(CC_DYNAMIC_FBMSRM_CONF)
                            u4Start = u4FbmStartAddr + SRMFBM_GetConf();
#else
                            u4Start = DRVCUST_OptGet(eFbmMemChBStart)+DRVCUST_OptGet(eFbmMemChBSize);
#endif
#else
                            u4Start = u4FbmStartAddr + u4ReservedSize;
#endif
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
#if !defined(CC_MT5891) && !defined(CC_MT5886)
                            u4Start -= FBM_POOL_PADDING_SIZE;
#endif

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
                        else if (eBehindPool == FBM_POOL_TYPE_NS_A)
                        {
                            u4FbmStartAddr = FBM_ALIGN_MASK(u4FbmStartAddr, FBM_PAGE_SIZE-1);
                            u4Start = u4FbmStartAddr + DRVCUST_OptGet(eFbmMemSize);//u4Start = BSP_GetMemSize();
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#if 0 // defined(CC_FBM_2ND_CHANNEL)
                        else if (eBehindPool == FBM_POOL_TYPE_TOTAL2)
                        {
                            _arPool[u4ListIdx].u4Addr = u4FbmStartAddr2 + BSP_GetChBMemSize() - _arPoolList[u4ListIdx].u4PoolSize;

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#endif
                        else if (arPoolArrangeInfo[eBehindPool].u1Ready != 0)
                        {
                            u4Start = _arPool[eBehindPool].u4Addr;
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eBehindPool);
                    }
                    else
                    {
                        // only after mode for non-inherit pool
#if !defined(CC_MT5891) && !defined(CC_MT5886)
                        ASSERT(0);
#endif
#if defined(CC_MT5891) || defined(CC_MT5886)
                        if ((arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_BETWEEN))
                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;//config late
#endif
                    }
                }
            }

            // check all non-inherit pool ready
            u4Ready = 1;
            for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
            {
                if ((_arPoolList[u4ListIdx].u4Inherit == FBM_POOL_ROOT) &&
                        (arPoolArrangeInfo[u4ListIdx].u1Ready == 0))
                {
                    u4Ready = 0;
                }
            }
        }
        while (u4Ready == 0);
#if defined(CC_MT5891) || defined(CC_MT5886)
        for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
        {
            if ((arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_BETWEEN))
            {
                FBM_POOL_TYPE_T eAheadPool;
                eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;
                //Printf("eAheadPool:0x%x\n",eAheadPool);
                if ((UINT32)eAheadPool >= FBM_POOL_TYPE_NS)
                {
                    ASSERT(TRUE);
                    continue;
                }

                u4Start = _arPool[eAheadPool].u4Addr;
                //Printf("u4Start1:0x%x\n",u4Start);
                u4Start += _arPool[eAheadPool].u4Size;
                //Printf("_arPool[eAheadPool].u4Size:0x%x\n",_arPool[eAheadPool].u4Size);
                u4Start += FBM_POOL_PADDING_SIZE;

                _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                //Printf("_arPool[u4ListIdx].u4Addr:0x%x\n",_arPool[u4ListIdx].u4Addr);

                arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                _arPool[u4ListIdx].u4Size = DRVCUST_OptGet(eFbmMemChBStart)+DRVCUST_OptGet(eFbmMemChBSize) - FBM_DRAMHOTBOOTCALIBR_SIZE - _arPool[u4ListIdx].u4Addr-FBM_POOL_PADDING_SIZE;
                //Printf("_arPool[u4ListIdx].u4Size:0x%x\n",_arPool[u4ListIdx].u4Size);
                _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;

            }
        }
#endif
        // handle inherit pool
        do
        {
            for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
            {
                if ((_arPoolList[u4ListIdx].u4Inherit == FBM_POOL_INHERIT) &&
                        (arPoolArrangeInfo[u4ListIdx].u1Ready == 0))
                {
                    if ((_arPoolList[u4ListIdx].u4PoolSize == 0) &&
                            (arPoolArrangeInfo[u4ListIdx].eMode != FBM_POOL_ARRANGE_BETWEEN) &&
                            (arPoolArrangeInfo[u4ListIdx].eMode != FBM_POOL_ARRANGE_SHARE_ALL))
                    {
                        arPoolArrangeInfo[u4ListIdx].u1Ready = 1;
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_SHARE)
                    {
                        FBM_POOL_TYPE_T eAheadPool;
                        eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;

                        FBM_CHECK_POOL_INDEX(eAheadPool);

                        // check 'ahead pool' ready or not
                        if (arPoolArrangeInfo[eAheadPool].u1Ready != 0)
                        {
#if !defined(CC_MT5886) //for mjc&scpos switch
                            ASSERT(_arPool[eAheadPool].u4Size > _arPoolList[u4ListIdx].u4PoolSize);
#endif

                            u4Start = _arPool[eAheadPool].u4Addr;

                            if (arPoolArrangeInfo[u4ListIdx].u4Offset != 0)
                            {
                                u4Start += arPoolArrangeInfo[u4ListIdx].u4Offset;
                                u4Start += FBM_POOL_PADDING_SIZE;
                            }

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool);
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_SHARE_ALL)
                    {
                        FBM_POOL_TYPE_T eAheadPool;
                        FBM_POOL_TYPE_T eAheadPool2;
                        eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;
                        eAheadPool2 = arPoolArrangeInfo[u4ListIdx].ePool2;

                        FBM_CHECK_POOL_INDEX(eAheadPool);
                        FBM_CHECK_POOL_INDEX(eAheadPool2);

                        // check 'ahead pool' ready or not
                        if (arPoolArrangeInfo[eAheadPool].u1Ready != 0)
                        {
                            if ((arPoolArrangeInfo[u4ListIdx].u4Offset == 0) &&
                                    (eAheadPool != eAheadPool2))
                            {
                                // check 'ahead pool' ready or not
                                if (arPoolArrangeInfo[eAheadPool2].u1Ready != 0)
                                {
                                    u4Start = _arPool[eAheadPool].u4Addr;
                                    u4Start += _arPool[eAheadPool2].u4Size;
                                    u4Start += FBM_POOL_PADDING_SIZE;

                                    _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                                    arPoolArrangeInfo[u4ListIdx].u1Ready = 1;
                                }

                                ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool2);
                            }
                            else
                            {
                                u4Start = _arPool[eAheadPool].u4Addr;

                                if (arPoolArrangeInfo[u4ListIdx].u4Offset != 0)
                                {
                                    u4Start += arPoolArrangeInfo[u4ListIdx].u4Offset;
                                    u4Start += FBM_POOL_PADDING_SIZE;
                                }

                                _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                                arPoolArrangeInfo[u4ListIdx].u1Ready = 1;
                            }

                            if (arPoolArrangeInfo[u4ListIdx].u1Ready != 0)
                            {
                                if ((_arPool[eAheadPool].u4Addr > _arPool[u4ListIdx].u4Addr) ||
                                        ((_arPool[u4ListIdx].u4Addr - _arPool[eAheadPool].u4Addr) > _arPoolList[eAheadPool].u4PoolSize))
                                {
                                    _arPool[u4ListIdx].u4Size = 0;
                                }
                                else
                                {
                                    _arPool[u4ListIdx].u4Size = _arPoolList[eAheadPool].u4PoolSize -
                                        (_arPool[u4ListIdx].u4Addr - _arPool[eAheadPool].u4Addr);
                                }

                                // Size Alignment
                                _arPool[u4ListIdx].u4Size = (_arPool[u4ListIdx].u4Size & (~(_arPoolList[u4ListIdx].u4SizeAlign)));

                                _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                                _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                                _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                                _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                            }
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool);
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_AFTER)
                    {
                        FBM_POOL_TYPE_T eAheadPool;
                        eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;

                        FBM_CHECK_POOL_INDEX(eAheadPool);

                        // check 'ahead pool' ready or not
                        if (arPoolArrangeInfo[eAheadPool].u1Ready != 0)
                        {
                            if (eAheadPool == FBM_POOL_TYPE_TOTAL)
                            {
                                _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4FbmStartAddr, _arPoolList[u4ListIdx].u4AddrAlign);
                            }
#if defined(CC_FBM_2ND_CHANNEL)
                            else if (eAheadPool == FBM_POOL_TYPE_TOTAL2)
                            {
                                _arPool[u4ListIdx].u4Addr = u4FbmStartAddr2;;
                            }
#endif
#if defined(CC_FBM_3ND_CHANNEL)
                            else if (eAheadPool == FBM_POOL_TYPE_TOTAL3)
                            {
                                _arPool[u4ListIdx].u4Addr = u4FbmStartAddr3;
                            }
#endif

                            else
                            {
                                u4Start = _arPool[eAheadPool].u4Addr;
                                u4Start += _arPool[eAheadPool].u4Size;
                                u4Start += FBM_POOL_PADDING_SIZE;

                                _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);
                            }

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool);
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_BEFORE)
                    {
                        FBM_POOL_TYPE_T eBehindPool;
                        eBehindPool = arPoolArrangeInfo[u4ListIdx].ePool1;

                        // check 'behind pool' ready or not
                        if (eBehindPool == FBM_POOL_TYPE_NS)
                        {
                            u4Start = u4FbmStartAddr + u4ReservedSize;
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#if defined(CC_FBM_2ND_CHANNEL)
                        else if (eBehindPool == FBM_POOL_TYPE_TOTAL2)
                        {
                            u4Start = u4FbmStartAddr2 + BSP_GetChBMemSize() - _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            //u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#endif
#if defined(CC_FBM_3ND_CHANNEL)
                        else if (eBehindPool == FBM_POOL_TYPE_TOTAL3)
                        {
                            u4Start = u4FbmStartAddr2 + BSP_GetChCMemSize() - _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            //u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
#endif

                        else if (arPoolArrangeInfo[eBehindPool].u1Ready != 0)
                        {
                            u4Start = _arPool[eBehindPool].u4Addr;
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eBehindPool);
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_ALLIGN_END)
                    {
                        FBM_POOL_TYPE_T eAllignEndPool;
                        eAllignEndPool = arPoolArrangeInfo[u4ListIdx].ePool1;

                        // check 'behind pool' ready or not
                        if (eAllignEndPool == FBM_POOL_TYPE_NS)
                        {
                            u4Start = u4FbmStartAddr + u4ReservedSize;
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
                        else if (arPoolArrangeInfo[eAllignEndPool].u1Ready != 0)
                        {
                            u4Start = _arPool[eAllignEndPool].u4Addr;
                            u4Start += _arPool[eAllignEndPool].u4Size;
                            u4Start -= _arPoolList[u4ListIdx].u4PoolSize;
                            u4Start -= _arPoolList[u4ListIdx].u4AddrAlign;
                            //u4Start -= FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            _arPool[u4ListIdx].u4Size = _arPoolList[u4ListIdx].u4PoolSize;
                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAllignEndPool);
                    }
                    else if (arPoolArrangeInfo[u4ListIdx].eMode == FBM_POOL_ARRANGE_BETWEEN)
                    {
                        FBM_POOL_TYPE_T eAheadPool;
                        FBM_POOL_TYPE_T eBehindPool;

                        eAheadPool = arPoolArrangeInfo[u4ListIdx].ePool1;
                        eBehindPool = arPoolArrangeInfo[u4ListIdx].ePool2;

                        // check 'ahead pool' & 'behind pool' ready or not

                        if ((eAheadPool == FBM_POOL_TYPE_NS) &&
                                (eBehindPool < FBM_POOL_TYPE_NS) &&
                                (arPoolArrangeInfo[eBehindPool].u1Ready != 0))
                        {
                            // share between u4FbmStartAddr

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4FbmStartAddr, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            if (_arPool[eBehindPool].u4Addr > _arPool[u4ListIdx].u4Addr)
                            {
                                _arPool[u4ListIdx].u4Size = _arPool[eBehindPool].u4Addr - _arPool[u4ListIdx].u4Addr;
                            }
                            else
                            {
                                _arPool[u4ListIdx].u4Size = 0;
                            }

                            // Size Alignment
                            _arPool[u4ListIdx].u4Size = (_arPool[u4ListIdx].u4Size & (~(_arPoolList[u4ListIdx].u4SizeAlign)));

                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }
                        else if ((eAheadPool < FBM_POOL_TYPE_NS) &&
                                (eBehindPool < FBM_POOL_TYPE_NS) &&
                                (arPoolArrangeInfo[eAheadPool].u1Ready != 0) &&
                                (arPoolArrangeInfo[eBehindPool].u1Ready != 0))
                        {
                            u4Start = _arPool[eAheadPool].u4Addr;
                            u4Start += _arPool[eAheadPool].u4Size;
                            u4Start += FBM_POOL_PADDING_SIZE;

                            _arPool[u4ListIdx].u4Addr = FBM_ALIGN_MASK(u4Start, _arPoolList[u4ListIdx].u4AddrAlign);

                            arPoolArrangeInfo[u4ListIdx].u1Ready = 1;

                            if (_arPool[eBehindPool].u4Addr > _arPool[u4ListIdx].u4Addr)
                            {
                                _arPool[u4ListIdx].u4Size = _arPool[eBehindPool].u4Addr - _arPool[u4ListIdx].u4Addr;
                            }
                            else
                            {
                                _arPool[u4ListIdx].u4Size = 0;
                            }

                            // Size Alignment
                            _arPool[u4ListIdx].u4Size = (_arPool[u4ListIdx].u4Size & (~(_arPoolList[u4ListIdx].u4SizeAlign)));

                            _arPool[u4ListIdx].u4Mode = _arPoolList[u4ListIdx].u4Mode;
                            _arPool[u4ListIdx].u4Width= _arPoolList[u4ListIdx].u4Width;
                            _arPool[u4ListIdx].u4Height = _arPoolList[u4ListIdx].u4Height;
                            _arPool[u4ListIdx].u4Inherit = _arPoolList[u4ListIdx].u4Inherit;
                        }

                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eAheadPool);
                        ASSERT((FBM_POOL_TYPE_T)u4ListIdx != eBehindPool);
                        ASSERT(eAheadPool != eBehindPool);
                    }
                    else
                    {
                        ASSERT(0);
                    }

                    _arPool[u4ListIdx].u4Mode |= FBM_POOL_MODE_SHARE;
                }
            }

            // check all non-inherit pool ready
            u4Ready = 1;
            for (u4ListIdx = 0; u4ListIdx < _u4PoolListNs; u4ListIdx++)
            {
                if ((_arPoolList[u4ListIdx].u4Inherit != 0) &&
                        (arPoolArrangeInfo[u4ListIdx].u1Ready == 0))
                {
                    u4Ready = 0;
                }
            }
        }
        while (u4Ready == 0);

        // check DSP 16MB Boundary Issue
        if (_arPool[FBM_POOL_TYPE_DSP].u4Size != 0)
        {
            u4Start = (_arPool[FBM_POOL_TYPE_DSP].u4Addr & 0xFF000000);
            u4End = ((_arPool[FBM_POOL_TYPE_DSP].u4Addr + _arPool[FBM_POOL_TYPE_DSP].u4Size) & 0xFF000000);

            if (u4Start != u4End)
            {
                LOG (0, "u4Addr=0x%x,u4Size=0x%x\n", _arPool[FBM_POOL_TYPE_DSP].u4Addr, _arPool[FBM_POOL_TYPE_DSP].u4Size);
                VERIFY(u4Start == u4End);
            }
        }
        // handle null pool and inhery pool
        for (u4PoolTpIdx = 0; u4PoolTpIdx < (UINT32)FBM_POOL_TYPE_NS; u4PoolTpIdx++)
        {
            if (_arPool[u4PoolTpIdx].u4Addr == (UPTR)NULL)
            {
                _arPool[u4PoolTpIdx].u4Addr = FBM_ALIGN_MASK((UPTR)(u4FbmStartAddr),
                        _arPoolList[u4PoolTpIdx].u4AddrAlign);
            }
            if ((_arPool[u4PoolTpIdx].u4Inherit == (UINT32)FBM_POOL_INHERIT)&&( _arPool[u4PoolTpIdx].u4Addr< u4FbmStartAddr))
            {
                LOG(0,"FBM inhert is before fbm start address , id =0x%x, start address=0x%x\n", u4PoolTpIdx, u4FbmStartAddr);
                //VERIFY(0);
            }
        }
        // handle root pool overlay
        for (u4PoolTpIdx = 0; u4PoolTpIdx < (UINT32)FBM_POOL_TYPE_TOTAL2; u4PoolTpIdx++)
        {
            for(u4PoolTpIdx2=u4PoolTpIdx+1; u4PoolTpIdx2<(UINT32)FBM_POOL_TYPE_TOTAL2; u4PoolTpIdx2++)
            {
                if((_arPoolList[u4PoolTpIdx].u4Inherit == FBM_POOL_ROOT)
                        &&(_arPoolList[u4PoolTpIdx2].u4Inherit == FBM_POOL_ROOT)
                        &&(_arPool[u4PoolTpIdx].u4Size!=0)
                        &&(_arPool[u4PoolTpIdx2].u4Size!=0))
                {
                    if(((_arPool[u4PoolTpIdx].u4Addr >= _arPool[u4PoolTpIdx2].u4Addr)&&
                                (_arPool[u4PoolTpIdx2].u4Addr + _arPool[u4PoolTpIdx2].u4Size > _arPool[u4PoolTpIdx].u4Addr))
                            ||((_arPool[u4PoolTpIdx].u4Addr <= _arPool[u4PoolTpIdx2].u4Addr)&&
                                (_arPool[u4PoolTpIdx].u4Addr + _arPool[u4PoolTpIdx].u4Size > _arPool[u4PoolTpIdx2].u4Addr)))
                    {
                        LOG(0,"FBM root  is overlap, u4PoolTpIdx=0x%x, u4PoolTpIdx2=0x%x\n", u4PoolTpIdx, u4PoolTpIdx2);
                        VERIFY(0);
                    }
                }
            }
        }
    }

    // handle MPEG pool
    if (_arPool[FBM_POOL_TYPE_MPEG].u4Addr != (UPTR)NULL)
    {
        _arFbpConf[0].u4Addr = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG].u4Addr, FBM_FMG_Y_ALIGMENT);
        _arFbpConf[0].u4AddrC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG_C].u4Addr, FBM_FMG_C_ALIGMENT);
        _arFbpConf[0].u4MpegTotalYSize = _arPool[FBM_POOL_TYPE_MPEG].u4Size;
        _arFbpConf[0].u4MpegTotalCSize = _arPool[FBM_POOL_TYPE_MPEG_C].u4Size;
        _arFbpConf[0].eFbmPoolType = FBM_POOL_TYPE_MPEG;


#ifdef CC_FBM_TWO_FBP
        _arFbpConf[1].u4Addr = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG].u4Addr + (FBM_FBG_TYPE_1080HD_H264_SIZE>>1), FBM_FMG_Y_ALIGMENT);
        _arFbpConf[1].u4AddrC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG_C].u4Addr,FBM_FMG_C_ALIGMENT);
        _arFbpConf[1].u4MpegTotalYSize = _arPool[FBM_POOL_TYPE_MPEG].u4Size;
        _arFbpConf[1].u4MpegTotalCSize = _arPool[FBM_POOL_TYPE_MPEG_C].u4Size;
        _arFbpConf[1].eFbmPoolType = FBM_POOL_TYPE_MPEG;

#endif
#if (defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB) || defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_SUPPORT_4K2K)) && (FBM_FBP_NS>=2)
        _arFbpConf[1].u4Addr = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG2].u4Addr, FBM_FMG_Y_ALIGMENT);
        _arFbpConf[1].u4AddrC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG2_C].u4Addr, FBM_FMG_C_ALIGMENT);
        _arFbpConf[1].u4MpegTotalYSize = _arPool[FBM_POOL_TYPE_MPEG2].u4Size;
        _arFbpConf[1].u4MpegTotalCSize = _arPool[FBM_POOL_TYPE_MPEG2_C].u4Size;
        _arFbpConf[1].eFbmPoolType = FBM_POOL_TYPE_MPEG2;
#endif

#if FBM_FBP_NS>=3
        _arFbpConf[2].u4Addr = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG3].u4Addr, FBM_FMG_Y_ALIGMENT);
        _arFbpConf[2].u4AddrC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG3_C].u4Addr, FBM_FMG_C_ALIGMENT);
        _arFbpConf[2].u4MpegTotalYSize = _arPool[FBM_POOL_TYPE_MPEG3].u4Size;
        _arFbpConf[2].u4MpegTotalCSize = _arPool[FBM_POOL_TYPE_MPEG3_C].u4Size;
        _arFbpConf[2].eFbmPoolType = FBM_POOL_TYPE_MPEG3;
#if FBM_FBP_NS==4
        _arFbpConf[3].u4Addr = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG4].u4Addr, FBM_FMG_Y_ALIGMENT);
        _arFbpConf[3].u4AddrC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG4_C].u4Addr, FBM_FMG_C_ALIGMENT);
        _arFbpConf[3].u4MpegTotalYSize = _arPool[FBM_POOL_TYPE_MPEG4].u4Size;
        _arFbpConf[3].u4MpegTotalCSize = _arPool[FBM_POOL_TYPE_MPEG4_C].u4Size;
        _arFbpConf[3].eFbmPoolType = FBM_POOL_TYPE_MPEG4;
#endif //FBM_FBP_NS==4
#endif //FBM_FBP_NS>=3

#if 0 //refine mpeg memory layout
        // Set Address to _arFbpConf
        for (u4PoolIdx = 0; u4PoolIdx < _ucFbpConfNs; u4PoolIdx++)
        {
            for (u4ListIdx = 0; u4ListIdx < _ucFbpListNs; u4ListIdx++)
            {
                if (_arFbpConf[u4PoolIdx].ucType == _arFbpList[u4ListIdx].ucType)
                {
                    if (_arFbpConf[u4PoolIdx].u4Addr == NULL)
                    {
                        _arFbpConf[u4PoolIdx].u4Addr = _arFbpConf[u4LastPoolIdx].u4Addr + u4LastPoolSize;
                    }
                    u4LastPoolSize = _arFbpList[u4ListIdx].u4Size;
                    u4LastPoolIdx = u4PoolIdx;
                }
            }
        }
#endif
        FBM_GetPanelModel();

        // Configure frame buffer pool (Type, Addr, Status, ...)
        _ucFbpNs = _ucFbpConfNs;

        for (u4PoolIdx = 0; u4PoolIdx < _ucFbpConfNs; u4PoolIdx++)
        {
            _prFbp[u4PoolIdx] = (FBP_T *)x_mem_alloc(sizeof(FBP_T));
            if (_prFbp[u4PoolIdx] != NULL)
            {
                _prFbp[u4PoolIdx]->ucType = _arFbpConf[u4PoolIdx].ucType;
                _prFbp[u4PoolIdx]->u4Addr = _arFbpConf[u4PoolIdx].u4Addr;
                _prFbp[u4PoolIdx]->u4AddrC = _arFbpConf[u4PoolIdx].u4AddrC;
                _prFbp[u4PoolIdx]->u4MpegTotalYSize = _arFbpConf[u4PoolIdx].u4MpegTotalYSize;
                _prFbp[u4PoolIdx]->u4MpegTotalCSize = _arFbpConf[u4PoolIdx].u4MpegTotalCSize;
                _prFbp[u4PoolIdx]->eFbmPoolType = _arFbpConf[u4PoolIdx].eFbmPoolType;
                _prFbp[u4PoolIdx]->ucStatus = FBP_STATUS_EMPTY;
                _prFbp[u4PoolIdx]->ucInheritance = FBP_MAX_NS;
                _prFbp[u4PoolIdx]->u4Size = 0;
                FBM_MEMSET((VOID *)_prFbp[u4PoolIdx]->aucOccupyList, FBP_MAX_NS, FBP_MAX_DISASSEMBLY);

            }

        }

        // Configure MPEG frame buffer pool (Size)
        for (u4PoolIdx = 0; u4PoolIdx < _ucFbpNs; u4PoolIdx++)
        {
            for (u4ListIdx = 0; u4ListIdx < _ucFbpListNs; u4ListIdx++)
            {
                if (_prFbp[u4PoolIdx]->ucType == _arFbpList[u4ListIdx].ucType)
                {
                    _prFbp[u4PoolIdx]->u4Size = _arFbpList[u4ListIdx].u4Size;
                }
            }
        }

        for (u4PoolIdx = 0; u4PoolIdx < _ucFbpConfNs; u4PoolIdx++)
        {
            if (_prFbp[u4PoolIdx] != NULL)
            {
                LOG(0, "FBP(%d) Type %d Addr 0x%08x AddrC 0x%08x Size 0x%08x TotalYSize 0x%x TotalCSize 0x%x PoolType %d\n",
                        u4PoolIdx,
                        _prFbp[u4PoolIdx]->ucType,
                        _prFbp[u4PoolIdx]->u4Addr,
                        _prFbp[u4PoolIdx]->u4AddrC,
                        _prFbp[u4PoolIdx]->u4Size,
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize,
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize,
                        _prFbp[u4PoolIdx]->eFbmPoolType);

            }
        }

    }
#ifndef CC_MEM_TOOL
    //#ifndef __KERNEL__
#if !defined(CC_FBM_2ND_CHANNEL) && !defined(__KERNEL__)
    // Pad the interval between pools
    for (u4PoolTpIdx = 0; u4PoolTpIdx < (UINT32)FBM_POOL_TYPE_NS; u4PoolTpIdx++)
    {
        UINT32 u4PadAddr;
        UINT32 u4PadLen;

        if ((_arPool[u4PoolTpIdx].u4Inherit == FBM_POOL_ROOT) &&
                (_arPool[u4PoolTpIdx].u4Addr > u4FbmStartAddr))
        {
            u4PadAddr = _arPool[u4PoolTpIdx].u4Addr - FBM_POOL_PADDING_SIZE;
            u4PadLen = FBM_POOL_PADDING_SIZE;

            FBM_MEMSET((VOID*)u4PadAddr, FBM_POOL_PADDING, u4PadLen);
        }
    }
#endif
#endif
#if defined(CC_EDB_FBM_SHARE_MEM)
    _gu4EDBAddr=_arPool[FBM_POOL_TYPE_EDB].u4Addr+(_arPool[FBM_POOL_TYPE_EDB].u4Size-_gu4EDBSize);
#endif

#ifndef USERDRV_KERNEL_MOD
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT)
    {
        TZ_FBM_Initialization(_arPool,sizeof(_arPool));
    }
#endif
#endif

    return (_arPool);
}

// this is customization part.

UINT32 FBM_GetPanelModel(VOID)
{
#if FBM_FBP_NS==4
    _ucFbpConfNs = 4;
#else
    _ucFbpConfNs = 3;
#endif
    LOG(0,"Panel Model(%d)\n",_ucFbpConfNs);

    return _ucFbpConfNs;
}

//-------------------------------------------------------------------------
/** _FBM_GetPoolList
 *  Get pool list
 *  @param  pprFbpList   FBP pool list point to pointer.
 *  @param  pucFbpNs   FBP pool list pointer number.
 *  @return NONE.
 */
//-------------------------------------------------------------------------
VOID _FBM_GetPoolList(FBP_LIST_T** pprFbpList, UCHAR* pucFbpNs)
{
    ASSERT(pprFbpList != NULL);
    ASSERT(pucFbpNs != NULL);

    *pucFbpNs = _ucFbpListNs;
    *pprFbpList = _arFbpList;
}

//-------------------------------------------------------------------------
/** _FBM_PoolAllocate
 *  Allocate FBM pool
 *  @param  ucFbgType   Pool type.
 *  @param  pu4FbMemoryPool   Pool address pointer.
 *  @return Pool size.
 *          If fail, return 0.
 */
//-------------------------------------------------------------------------
UINT32 _FBM_PoolAllocate(MPEG_POOL_INFO_T *prMpegPoolInfo)
{
    UINT32 u4PoolIdx;
    BOOL   fgFound = FALSE;
    FBM_POOL_T* prFbmPool = NULL;
    if (prMpegPoolInfo == NULL)
    {
        return 0;
    }

#if defined(CC_MT5886)
    if(prMpegPoolInfo->fgUseDynBuf)
    {
        prFbmPool = FBM_Alloc(FBM_TYPE_DYN_MPEG);
        if(prFbmPool && prFbmPool->ePoolType == FBM_POOL_TYPE_DYN_MPEG)
        {
            prMpegPoolInfo->u4FbMemoryPool = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_DYN_MPEG].u4Addr, FBM_FMG_Y_ALIGMENT);
            prMpegPoolInfo->u4FbMemoryPoolC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG_C].u4Addr, FBM_FMG_C_ALIGMENT);
            prMpegPoolInfo->u4MpegTotalYSize =	_arPool[FBM_POOL_TYPE_DYN_MPEG].u4Size;
            prMpegPoolInfo->u4MpegTotalCSize =	_arPool[FBM_POOL_TYPE_MPEG_C].u4Size;
            return prMpegPoolInfo->u4MpegTotalYSize;
        }
        else if(prFbmPool && prFbmPool->ePoolType == FBM_POOL_TYPE_DYN_MPEG2)
        {
            prMpegPoolInfo->u4FbMemoryPool = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_DYN_MPEG2].u4Addr, FBM_FMG_Y_ALIGMENT);
            prMpegPoolInfo->u4FbMemoryPoolC = FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_MPEG2_C].u4Addr, FBM_FMG_C_ALIGMENT);
            prMpegPoolInfo->u4MpegTotalYSize =	_arPool[FBM_POOL_TYPE_DYN_MPEG2].u4Size;
            prMpegPoolInfo->u4MpegTotalCSize =	_arPool[FBM_POOL_TYPE_MPEG2_C].u4Size;
            return prMpegPoolInfo->u4MpegTotalYSize;
        }

    }
    else
#endif
    {
        prFbmPool = FBM_Alloc(FBM_TYPE_MPEG);
    }


    if (prFbmPool ==  NULL)
    {
        LOG(0,"alloc Fbm Pool fail\n");
        return 0;
    }

    for (u4PoolIdx = 0; u4PoolIdx < _ucFbpConfNs; u4PoolIdx++)
    {
        if (_prFbp[u4PoolIdx] != NULL)
        {
            if (_prFbp[u4PoolIdx]->eFbmPoolType == prFbmPool->ePoolType)
            {
#if defined(CC_ENABLE_CMA_SUPPORT) //if cma support replace the fbm mpeg pool
                _prFbp[u4PoolIdx]->u4Addr = CMA_GetPool((UCHAR)prFbmPool->ePoolType)->u4PhyAlignAddr;
                _prFbp[u4PoolIdx]->u4MpegTotalYSize = CMA_GetPool((UCHAR)prFbmPool->ePoolType)->u4Size;
                if(_prFbp[u4PoolIdx]->u4Addr == 0)
                {
                    LOG(0, "CMA can't alloc this Y memory [y_type=%d].\n", prFbmPool->ePoolType);
                    fgFound = FALSE;
                    break;
                }
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT) // if tz support should allocate y and c buffer together in the same channel.
                //for TZ case, it should allocate both y and c buffer, depends on TZ mid region.
                switch(prFbmPool->ePoolType)
                {
                    case FBM_POOL_TYPE_MPEG:
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize = CMA_MPEG_Y_SIZE;
                        _prFbp[u4PoolIdx]->u4AddrC = _prFbp[u4PoolIdx]->u4Addr + CMA_MPEG_Y_SIZE;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_MPEG_C_SIZE;
                        break;
                    case FBM_POOL_TYPE_MPEG2:
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize = CMA_MPEG_Y2_SIZE;
                        _prFbp[u4PoolIdx]->u4AddrC = _prFbp[u4PoolIdx]->u4Addr + CMA_MPEG_Y2_SIZE;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_MPEG_C2_SIZE;
                        break;
                    case FBM_POOL_TYPE_MPEG3:
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize = CMA_MPEG_Y3_SIZE;
                        _prFbp[u4PoolIdx]->u4AddrC = _prFbp[u4PoolIdx]->u4Addr + CMA_MPEG_Y3_SIZE;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_MPEG_C3_SIZE;
                        break;
                    case FBM_POOL_TYPE_MPEG4:
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize = CMA_MPEG_Y4_SIZE;
                        _prFbp[u4PoolIdx]->u4AddrC = _prFbp[u4PoolIdx]->u4Addr + CMA_MPEG_Y4_SIZE;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_MPEG_C4_SIZE;
                        break;
                    default:
                        LOG(0, "Can't find this pool type.\n");
                        _prFbp[u4PoolIdx]->u4AddrC = 0;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = 0;
                        break;
                }
#else

                _prFbp[u4PoolIdx]->u4AddrC = 0;
                _prFbp[u4PoolIdx]->u4MpegTotalCSize = 0;
                //to be fixed, some case may no need to allocate mpegc buffer

                switch(prFbmPool->ePoolType)
                {
                    case FBM_POOL_TYPE_MPEG:
                        _prFbp[u4PoolIdx]->u4AddrC = CMA_GetPool(FBM_POOL_TYPE_MPEG_C)->u4PhyAlignAddr;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_GetPool(FBM_POOL_TYPE_MPEG_C)->u4Size;
                        break;
                    case FBM_POOL_TYPE_MPEG2:
                        _prFbp[u4PoolIdx]->u4AddrC = CMA_GetPool(FBM_POOL_TYPE_MPEG2_C)->u4PhyAlignAddr;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_GetPool(FBM_POOL_TYPE_MPEG2_C)->u4Size;
                        break;
                    case FBM_POOL_TYPE_MPEG3:
                        _prFbp[u4PoolIdx]->u4AddrC = CMA_GetPool(FBM_POOL_TYPE_MPEG3_C)->u4PhyAlignAddr;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_GetPool(FBM_POOL_TYPE_MPEG3_C)->u4Size;
                        break;
                    case FBM_POOL_TYPE_MPEG4:
                        _prFbp[u4PoolIdx]->u4AddrC = CMA_GetPool(FBM_POOL_TYPE_MPEG4_C)->u4PhyAlignAddr;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = CMA_GetPool(FBM_POOL_TYPE_MPEG4_C)->u4Size;
                        break;
                    default:
                        LOG(0, "Can't find this pool type.\n");
                        _prFbp[u4PoolIdx]->u4AddrC = 0;
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize = 0;
                        break;
                }
                if(_prFbp[u4PoolIdx]->u4AddrC == 0)
                {
                    LOG(0, "CMA can't alloc this C memory [free y_type=%d].\n", prFbmPool->ePoolType);
                    fgFound = FALSE;
                    //CMA_FreePool(prFbmPool->ePoolType);
                    break;
                }

#endif
                LOG(0, "-> CMA-FBP(%d) Init_Type %d Addr 0x%08x AddrC 0x%08x Size 0x%08x TotalYSize 0x%x TotalCSize 0x%x PoolType %d\n",
                        u4PoolIdx,
                        _prFbp[u4PoolIdx]->ucType,
                        _prFbp[u4PoolIdx]->u4Addr,
                        _prFbp[u4PoolIdx]->u4AddrC,
                        _prFbp[u4PoolIdx]->u4Size,
                        _prFbp[u4PoolIdx]->u4MpegTotalYSize,
                        _prFbp[u4PoolIdx]->u4MpegTotalCSize,
                        _prFbp[u4PoolIdx]->eFbmPoolType);
#endif
                fgFound = TRUE;
                break;
            }
        }
    }
    if (fgFound)
    {
        _prFbp[u4PoolIdx]->ucStatus = FBP_STATUS_USED;
        prMpegPoolInfo->u4FbMemoryPool = _prFbp[u4PoolIdx]->u4Addr;
        prMpegPoolInfo->u4FbMemoryPoolC = _prFbp[u4PoolIdx]->u4AddrC;
        prMpegPoolInfo->u4MpegTotalYSize =  _prFbp[u4PoolIdx]->u4MpegTotalYSize;
        prMpegPoolInfo->u4MpegTotalCSize =  _prFbp[u4PoolIdx]->u4MpegTotalCSize;
        return prMpegPoolInfo->u4MpegTotalYSize;
    }
    else
    {
        LOG(0,"Can not Allocate MPEG pool type=%d\n", prFbmPool->ePoolType);
        FBM_Free(prFbmPool);
        return 0;
    }

    return 0;
}


//-------------------------------------------------------------------------
/** _FBM_PoolRelease
 *  Release FBM pool
 *  @param  u4FbMemoryPool   Pool address.
 *  @return NONE
 */
//-------------------------------------------------------------------------
VOID _FBM_PoolRelease(UPTR u4FbMemoryPool)
{
    UINT32 u4PoolIdx;
    FBM_POOL_T *prFbmPool = NULL;

#if defined(CC_MT5886)
    if (u4FbMemoryPool == FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_DYN_MPEG].u4Addr, FBM_FMG_Y_ALIGMENT))
    {
        prFbmPool = FBM_GetPoolInfo((UCHAR)FBM_POOL_TYPE_DYN_MPEG);
        FBM_Free(prFbmPool);
        LOG(2,"Release Fbm Pool FBM_POOL_TYPE_DYN_MPEG\n");
        return;
    }
    else if (u4FbMemoryPool == FBM_ALIGN_MASK(_arPool[FBM_POOL_TYPE_DYN_MPEG2].u4Addr, FBM_FMG_Y_ALIGMENT))
    {
        prFbmPool = FBM_GetPoolInfo((UCHAR)FBM_POOL_TYPE_DYN_MPEG2);
        FBM_Free(prFbmPool);
        LOG(2,"Release Fbm Pool FBM_POOL_TYPE_DYN_MPEG2\n");
        return;
    }
#endif

    for (u4PoolIdx = 0; u4PoolIdx < FBP_MAX_NS; u4PoolIdx++)
    {
        if ((_prFbp[u4PoolIdx] != NULL) &&
                (_prFbp[u4PoolIdx]->u4Addr == u4FbMemoryPool) &&
                (_prFbp[u4PoolIdx]->ucStatus == FBP_STATUS_USED))
        {
            if (_prFbp[u4PoolIdx]->eFbmPoolType < FBM_POOL_TYPE_NS)
            {
                prFbmPool = FBM_GetPoolInfo((UCHAR)_prFbp[u4PoolIdx]->eFbmPoolType);
                FBM_Free(prFbmPool);
                LOG(2,"Release Fbm Pool Type(%d)\n",_prFbp[u4PoolIdx]->eFbmPoolType);
            }
            _prFbp[u4PoolIdx]->ucStatus = FBP_STATUS_EMPTY;
            u4PoolIdx = FBP_MAX_NS;
        }
    }
}


//-------------------------------------------------------------------------
/** _FBM_PoolStatus
 *  Print FBM pool status
 *  @return NONE
 */
//-------------------------------------------------------------------------
VOID _FBM_PoolStatus(VOID)
{
    UCHAR ucIdx;

    LOG(0, "\n");
    LOG(0, "Sum of Root: 0x%x(%dM)\n", _u4SumOfRoot,_u4SumOfRoot/0x100000);

    //    FBM_PrintPoolInfo(&_arPool, &_arPoolList);
    FBM_PrintPoolInfo(_arPool, _arPoolList);

    for (ucIdx = 0; ucIdx < FBP_MAX_NS; ucIdx++)
    {
        if (_prFbp[ucIdx] != NULL)
        {
            LOG(1, "MPEG Pool(%d) T(%d) S(%d) Addr(0x%08x, 0x%08x)",
                    ucIdx,
                    _prFbp[ucIdx]->ucType,
                    _prFbp[ucIdx]->ucStatus,
                    _prFbp[ucIdx]->u4Addr,
                    _prFbp[ucIdx]->u4Size);

            if (_prFbp[ucIdx]->ucInheritance != FBP_MAX_NS)
            {
                LOG(1, " Inherit(%d)", _prFbp[ucIdx]->ucInheritance);
            }

            if (_prFbp[ucIdx]->ucStatus == FBP_STATUS_OCCUPY)
            {
                LOG(1, " Occupy(%d,%d,%d,%d)\n",
                        _prFbp[ucIdx]->aucOccupyList[0],
                        _prFbp[ucIdx]->aucOccupyList[1],
                        _prFbp[ucIdx]->aucOccupyList[2],
                        _prFbp[ucIdx]->aucOccupyList[3]);
            }
            else
            {
                LOG(1, "\n");
            }
        }
    }
    SRM_QueryStatus();
}

/**
 * FBM SRM control call back
 *
 * @param VOID
 * @return VOID
 */
#ifdef CC_SRM_ON
static VOID _FBM_SrmCtrlCb(UINT32 u4Arg1, UINT32 u4Arg2, UINT32 u4Arg3, UINT32 u4Arg4)
{
    UCHAR u4Idx;
    // cyj.porting
#if 0
    if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5392F_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391F_FHD60_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5392H_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391H_FHD60_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_64MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360_VERF_64MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360x64MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362B_VERF_128MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362B_VERF_64MB) ||
            (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360B_VERF_64MB))
#endif
    {
        static UINT32 u4CurrentMpegMode = FBM_POOL_MODE_MPEG_NO_COMP;

        LOG(3, "[SRM] MPEG CTRL vdp%d 0x%x %d %d\n", u4Arg1, u4Arg2, u4Arg3, u4Arg4);

        if ((u4CurrentMpegMode &  FBM_POOL_MODE_MPEG_NO_COMP) !=
                (u4Arg2 & FBM_POOL_MODE_MPEG_NO_COMP))
        {
            UINT32 u4Notify = 0;
            UINT32 u4PoolIdx;

            u4CurrentMpegMode = u4Arg2;

            for (u4PoolIdx = 0; u4PoolIdx < FBP_MAX_NS; u4PoolIdx++)
            {
                if ((_prFbp[u4PoolIdx] != NULL) &&
                        (_prFbp[u4PoolIdx]->ucStatus == FBP_STATUS_USED) &&
                        (_prFbp[u4PoolIdx]->ucType == FBM_FBG_TYPE_1080HD))
                {
                    u4Notify = 1;
                }
            }

            if (u4Notify != 0)
            {
                // Mode Change, Notify MPEG to reallocate FBM
                for (u4Idx = 0; u4Idx < FBG_MAX_NS; u4Idx++)
                {
                    FBM_SetFrameBufferFlag(u4Idx, FBM_FLAG_RELEASE_FBG);
                }
            }
        }

        FBM_POOL_MUTEX_LOCK();

        if (u4Arg2 & FBM_POOL_MODE_MPEG_NO_COMP)
        {
            // cyj.porting
#if 0
            if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5392B_EU_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5392H_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391H_FHD60_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391_VERF) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362B_VERF_128MB))
            {
                _arFbpList = _arFbpH264List;
                _ucFbpListNs = _ucFbpH264ListNs;
            }
            else if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5392B_US_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5392F_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391F_FHD60_128MB))
            {
                _arFbpList = _arFbpCqamDbkList;
                _ucFbpListNs = _ucFbpCqamDbkListNs;
            }
            else if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360x64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362B_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360B_VERF_64MB))
#endif
            {
                // _arFbpList = _arFbpH264List64M;
                //  _ucFbpListNs = _ucFbpH264List64MNs;
            }
        }
        else if (u4Arg2 & FBM_POOL_MODE_MPEG_COMP_50)
        {
            // cyj.porting
#if 0
            if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5392H_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391H_FHD60_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391_VERF) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_128MB))
            {
                _arFbpList = _arFbpH264PipList;
                _ucFbpListNs = _ucFbpH264PipListNs;
            }
            else if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5392F_128MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5391F_FHD60_128MB))
            {
                _arFbpList = _arFbpMPEG2PipList;
                _ucFbpListNs = _ucFbpMPEG2PipListNs;
            }
            else if ((SRMFBM_GetConf() == FBM_MEM_CFG_MT5362_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360x64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5362B_VERF_64MB) ||
                    (SRMFBM_GetConf() == FBM_MEM_CFG_MT5360B_VERF_64MB))
#endif
            {
                //_arFbpList = _arFbpH264PipList64M;
                // _ucFbpListNs = sizeof(_arFbpH264PipList64M)/sizeof(FBP_LIST_T);

            }
        }
        else
        {
            //ASSERT(0);
        }
        FBM_POOL_MUTEX_UNLOCK();
    }
}
#endif

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

//-------------------------------------------------------------------------
/** FBM_SelectGroupType
 *  Choice FBM Type according to size
 *  @param  u4Width   width.
 *  @param  u4Height   height.
 *  @return FBG type.
 */
//-------------------------------------------------------------------------
UCHAR FBM_SelectGroupType(UINT32 u4Width, UINT32 u4Height)
{
    UINT32 u4Idx = 0;

    UINT32 u4TargetWidth = 0xFFFFFFFF;
    UINT32 u4TargetHeight = 0xFFFFFFFF;
    UCHAR ucTargetType = FBM_FBG_TYPE_UNKNOWN;

    FBM_POOL_MUTEX_LOCK();
    for (u4Idx = 0; u4Idx < _ucFbpListNs; u4Idx++)
    {
        if(_arFbpList[u4Idx].u4Width * _arFbpList[u4Idx].u4Height >=
                FBM_ALIGN_MASK(u4Width, FBM_B2R_H_PITCH) *
                FBM_ALIGN_MASK(u4Height, FBM_B2R_H_PITCH))
        {
            if((u4TargetWidth == 0xFFFFFFFF) ||
                    (_arFbpList[u4Idx].u4Width * _arFbpList[u4Idx].u4Height <
                     FBM_ALIGN_MASK(u4TargetWidth, FBM_B2R_H_PITCH) *
                     FBM_ALIGN_MASK(u4TargetHeight, FBM_B2R_H_PITCH)))
            {
                ucTargetType = _arFbpList[u4Idx].ucType;

                u4TargetWidth = _arFbpList[u4Idx].u4Width;
                u4TargetHeight = _arFbpList[u4Idx].u4Height;
            }
        }
    }
#ifdef FBM_4K2K_SUPPORT

    LOG(2, "Select(%d, %d) Type(%d) \n", u4Width, u4Height, ucTargetType);
    if ((ucTargetType == FBM_FBG_TYPE_4K2K_EXTRA) || (ucTargetType == FBM_FBG_TYPE_4K2K) || (ucTargetType == FBM_FBG_TYPE_4K2K_JPEG))
    {
        ucTargetType = FBM_FBG_TYPE_4K2K;
    }
#endif
    FBM_POOL_MUTEX_UNLOCK();

    //LOG(0, "Select(%d, %d) Type(%d)Big(0x%x)\n", u4Width, u4Height, ucTargetType);

    return ucTargetType;
}

UCHAR FBM_ChangePoolInfo(UCHAR ucPoolType)
{
    switch(ucPoolType)
    {
        case FBM_POOL_TYPE_SCPOS_MAIN:
            if(SRM_GetCurrFBMMode()==FBM_MMMODE)
            {
                ucPoolType = FBM_POOL_TYPE_PQ_MM;
            }
            else if(SRM_GetCurrFBMMode()==FBM_NETMODE)
            {
                ucPoolType = FBM_POOL_TYPE_PQ_NET;
            }
            else if(SRM_GetCurrFBMMode()==FBM_TVMODE)
            {
                ucPoolType = FBM_POOL_TYPE_PQ_TV;
            }
            break;
        case FBM_POOL_TYPE_FEEDER:
            if(SRM_GetCurrFBMMode()==FBM_MMMODE)
            {
                ucPoolType = FBM_POOL_TYPE_FEEDER;
            }
            else if(SRM_GetCurrFBMMode()==FBM_NETMODE)
            {
                ucPoolType = FBM_POOL_TYPE_FEEDER_NET;
            }
            break;
        default:
            break;
    }
    return ucPoolType;
}
//-------------------------------------------------------------------------
/** FBM_GetPoolInfo
 *  Get Pool Info
 *  @param  ucPoolType
 *  @return NONE.
 */
//-------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD
FBM_POOL_T* FBM_GetPoolInfo(UCHAR ucPoolType)
{
#if defined(CC_MT5880)
    static FBM_POOL_T _arPool_temp;
#endif
#ifndef CC_MEM_TOOL
    if (FBM_CHECK_CB_FUNC_VERIFY(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_POOL_CHANGE], _prFbmCbFunc->au4CbFuncCRC[FBM_CB_FUNC_POOL_CHANGE]))
    {
        ((FBM_CB_POOL_CHANGE_FUNC)_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_POOL_CHANGE])((FBM_POOL_TYPE_T)ucPoolType);
    }
    else
    {
        ASSERT(_prFbmCbFunc->au4CbFunc[FBM_CB_FUNC_POOL_CHANGE] == 0);
    }
#endif
    return (&_arPool[ucPoolType]);
}
#endif
//-------------------------------------------------------------------------
/** FBM_GetPoolMpeg
 *  Get MPEG Pool Info
 *  @param NONE
 *  @return NONE.
 */
//-------------------------------------------------------------------------

FBM_POOL_T* FBM_GetPoolMpeg(VOID)
{
    UCHAR ucIdx;

    for (ucIdx = 0; ucIdx < FBP_MAX_NS; ucIdx++)
    {
        if (_prFbp[ucIdx] != NULL)
        {
            if (_prFbp[ucIdx]->ucStatus == FBP_STATUS_USED)
            {
                _rCurrentMpeg = _arPool[(UCHAR)FBM_POOL_TYPE_MPEG];

                _rCurrentMpeg.u4Addr = _prFbp[ucIdx]->u4Addr;
                _rCurrentMpeg.u4Size = _prFbp[ucIdx]->u4Size;

                return &_rCurrentMpeg;
            }
        }
    }

    return FBM_GetPoolInfo((UCHAR)FBM_POOL_TYPE_MPEG);
}

CHAR* FBM_GetPoolName(UCHAR ucPoolType)
{
    return _arPoolList[ucPoolType].szName;
}

UINT32 FBM_GetPoolSize(UCHAR ucPoolType)
{
    return _arPoolList[ucPoolType].u4PoolSize;
}
#if defined(CC_EDB_FBM_SHARE_MEM)

VOID FBM_SetEDBSize(UINT8 u1EDBSize)
{
    if(u1EDBSize>12)
        _gu4EDBSize=0xc00000;
    else
        _gu4EDBSize=(u1EDBSize<<20);

#if defined(CC_EDB_FBM_SHARE_MEM)
    _gu4EDBAddr=_arPool[FBM_POOL_TYPE_EDB].u4Addr+(_arPool[FBM_POOL_TYPE_EDB].u4Size-_gu4EDBSize);
    _arPool[FBM_POOL_TYPE_DMX].u4Size=FBM_DMX_H264_SIZE + FBM_EDB_POOL_SIZE - _gu4EDBSize;
#endif
}

VOID FBM_GetEDBAddr(UINT32* pu4EDBAddr)
{
    *pu4EDBAddr = _gu4EDBAddr;
}
#endif

VOID FBM_LaxPoolAllocPolicy(BOOL fgIsAllocTwoPool, FBM_TYPE_T *pLaxPoolGroup, FBM_POOL_LAT_T* prLatPoolAlloc)
{
    FBM_POOL_T *prFbmPool1 = NULL;
    FBM_POOL_T *prFbmPool2 = NULL;

    if(fgIsAllocTwoPool)
    {
        prFbmPool1 = FBM_Alloc(pLaxPoolGroup[FBM_LAT_POOL_UESED]);
        if((NULL == prFbmPool1)||(prFbmPool1->u4Size == 0))
        {
            if((prFbmPool1)&&(prFbmPool1->u4Size == 0))
            {
                FBM_Free(prFbmPool1);
            }
            LOG(0, "Alloc LAX1 Pool Failed\n");
            prFbmPool1 = NULL;
            goto ERROR;
        }

        prFbmPool2 = FBM_Alloc(pLaxPoolGroup[FBM_LAT_POOL_BACKUP]);
        if((NULL == prFbmPool2)||(prFbmPool2->u4Size == 0))
        {
            LOG(0, "Alloc LAX2 Pool Failed\n");
            FBM_Free(prFbmPool1);
            if((prFbmPool2)&&(prFbmPool2->u4Size == 0))
            {
                FBM_Free(prFbmPool2);
            }
            prFbmPool1 = NULL;
            prFbmPool2 = NULL;
            goto ERROR;
        }

        prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED] = prFbmPool1;
        prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_BACKUP] = prFbmPool2;
        prLatPoolAlloc->u4Addr = prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED]->u4Addr;
        prLatPoolAlloc->u4Size = prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED]->u4Size;
    }
    else
    {
        prFbmPool1 = FBM_Alloc(pLaxPoolGroup[FBM_LAT_POOL_UESED]);
        if((!prFbmPool1)||(prFbmPool1->u4Size == 0))
        {
            prFbmPool1 = FBM_Alloc(pLaxPoolGroup[FBM_LAT_POOL_BACKUP]);
            if((!prFbmPool1)||(prFbmPool1->u4Size == 0))
            {
                if((prFbmPool1)&&(prFbmPool1->u4Size == 0))
                {
                    FBM_Free(prFbmPool1);
                }
                prFbmPool1 = NULL;
            }
            else
            {
                prLatPoolAlloc->u4Size = prFbmPool1->u4Size;
            }
        }
        else
        {
            prLatPoolAlloc->u4Size = (prFbmPool1->u4Size)/(FBM_LAT_POOL_ALLOC_MAX);/*Share use one lax pool*/
        }

        if(NULL != prFbmPool1)
        {
            prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED] = prFbmPool1;
            prLatPoolAlloc->u4Addr = prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED]->u4Addr;
        }
        else
        {
            goto ERROR;
        }
    }

    return ;

ERROR:
    prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_UESED] = NULL;
    prLatPoolAlloc->pLATPoolAlloc[FBM_LAT_POOL_BACKUP] = NULL;
    prLatPoolAlloc->u4Addr = 0;
    prLatPoolAlloc->u4Size = 0;
    return ;
}

//-------------------------------------------------------------------------
/** FBM_Alloc
 *  Get unused Pool Info
 *  @param FBM Type
 *  @return Pool Info Struct, NULL if any error.
 */
//-------------------------------------------------------------------------
VOID FBM_AllocLax(BOOL fgNeedAllocTwoLaxPool, FBM_POOL_LAT_T* prLatPoolAlloc)
{
    FBM_TYPE_T LaxPoolGroup[FBM_LAT_POOL_ALLOC_MAX] = {0};
    UINT32 *pLaxPoolGroup = &(LaxPoolGroup[FBM_LAT_POOL_UESED]);

    LaxPoolGroup[FBM_LAT_POOL_UESED] = FBM_TYPE_LAX1;
    LaxPoolGroup[FBM_LAT_POOL_BACKUP] = FBM_TYPE_LAX2;


    prLatPoolAlloc->u4Addr = 0;
    prLatPoolAlloc->u4Size = 0;

    FBM_LaxPoolAllocPolicy(fgNeedAllocTwoLaxPool, pLaxPoolGroup, prLatPoolAlloc);

    if((0 == prLatPoolAlloc->u4Addr)||(0 == prLatPoolAlloc->u4Size))
    {
        LaxPoolGroup[FBM_LAT_POOL_UESED] = FBM_TYPE_LAX3;
        LaxPoolGroup[FBM_LAT_POOL_BACKUP] = FBM_TYPE_LAX4;

        FBM_LaxPoolAllocPolicy(fgNeedAllocTwoLaxPool, pLaxPoolGroup, prLatPoolAlloc);
    }

    if((0 == prLatPoolAlloc->u4Addr)||(0 == prLatPoolAlloc->u4Size))
    {
        LOG(0, "Error Alloc Pool[0x%p~0x%p,size 0x%x]\n", prLatPoolAlloc->u4Addr,
                prLatPoolAlloc->u4Addr+prLatPoolAlloc->u4Size,
                prLatPoolAlloc->u4Size);
    }

    return ;
}


FBM_POOL_T* FBM_Alloc(UCHAR ucFbmType)
{
    UCHAR ucPoolType = FBM_POOL_TYPE_NONE;
    FBM_POOL_T *prFbmPool = NULL;
    UINT32 u4TZDMXAddr, u4TZDMXSize, u4TZDMX2Addr, u4TZDMX2Size;

    FBM_POOL_MUTEX_LOCK();

    switch(ucFbmType)
    {
        case FBM_TYPE_SML:
            {
                if(!_arPool[FBM_POOL_TYPE_SEAML1].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML1].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML1;
                }
#if defined(CC_FBM_TWO_FBP)||defined(CC_FBM_SUPPORT_4K2K)
                else if(!_arPool[FBM_POOL_TYPE_SEAML2].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML2].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML2;
                }
#endif
#if defined(CC_FBM_TWO_4K2K)||defined(CC_FBM_FOUR_INST_SUPPORT)
                else if(!_arPool[FBM_POOL_TYPE_SEAML3].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML3].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML3;
                }
                else if(!_arPool[FBM_POOL_TYPE_SEAML4].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML4].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML4;
                }
#endif
                break;
            }
        case FBM_TYPE_SML_C:
            {
                if(!_arPool[FBM_POOL_TYPE_SEAML1_C].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML1_C].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML1_C;
                }
#if defined(CC_FBM_TWO_FBP)||defined(CC_FBM_SUPPORT_4K2K)
                else if(!_arPool[FBM_POOL_TYPE_SEAML2_C].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML2_C].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML2_C;
                }
#endif
#if defined(CC_FBM_TWO_4K2K)||defined(CC_FBM_FOUR_INST_SUPPORT)
                else if(!_arPool[FBM_POOL_TYPE_SEAML3_C].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML3_C].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML3_C;
                }
                else if(!_arPool[FBM_POOL_TYPE_SEAML4_C].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_SEAML4_C].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_SEAML4_C;
                }
#endif
                break;
            }
        case FBM_TYPE_MPEG:
            if(!_arPool[FBM_POOL_TYPE_MPEG].fgAlloced && !_arPool[FBM_POOL_TYPE_DYN_MPEG].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG;
            }
#if defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB) ||defined(CC_FBM_SUPPORT_4K2K) || defined(CC_FBM_TWO_FBP)
            else if(!_arPool[FBM_POOL_TYPE_MPEG2].fgAlloced && !_arPool[FBM_POOL_TYPE_DYN_MPEG2].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG2].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG2;
            }
#endif
#if defined(CC_FBM_TWO_4K2K)||defined(CC_FBM_FOUR_INST_SUPPORT)
            else if(!_arPool[FBM_POOL_TYPE_MPEG3].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG3].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG3;
            }
            else if(!_arPool[FBM_POOL_TYPE_MPEG4].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG4].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG4;
            }
#endif

            break;
        case FBM_TYPE_DYN_MPEG:
            if(!_arPool[FBM_POOL_TYPE_DYN_MPEG].fgAlloced && !_arPool[FBM_POOL_TYPE_MPEG].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DYN_MPEG].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DYN_MPEG;
                LOG(0,"FBM alloc FBM_POOL_TYPE_DYN_MPEG\n");
            }
#if defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB)||defined(CC_FBM_SUPPORT_4K2K) || defined(CC_FBM_TWO_FBP)
            else if(!_arPool[FBM_POOL_TYPE_DYN_MPEG2].fgAlloced && !_arPool[FBM_POOL_TYPE_MPEG2].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DYN_MPEG2].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DYN_MPEG2;
                LOG(0,"FBM alloc FBM_POOL_TYPE_DYN_MPEG2\n");
            }
#endif
#if defined(CC_FBM_TWO_4K2K)||defined(CC_FBM_FOUR_INST_SUPPORT)
            else if(!_arPool[FBM_POOL_TYPE_MPEG3].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG3].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG3;
            }
            else if(!_arPool[FBM_POOL_TYPE_MPEG4].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_MPEG4].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_MPEG4;
            }
#endif

            break;
        case FBM_TYPE_FEEDER:
            if(!_arPool[FBM_POOL_TYPE_FEEDER].fgAlloced)
            {
                LOG(0,"FBM alloc Feeder\n");
                _arPool[FBM_POOL_TYPE_FEEDER].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_FEEDER;
            }
#if defined(CC_FBM_TWO_FBP) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB)
            else if(!_arPool[FBM_POOL_TYPE_FEEDER2].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_FEEDER2].fgAlloced = TRUE;
                LOG(0,"FBM alloc Feeder2 \n");
                ucPoolType = FBM_POOL_TYPE_FEEDER2;
            }
#endif
#if defined(CC_FBM_FOUR_INST_SUPPORT)
            else if(!_arPool[FBM_POOL_TYPE_FEEDER3].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_FEEDER3].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_FEEDER3;
                LOG(0,"FBM alloc Feeder3 \n");

            }
            else if(!_arPool[FBM_POOL_TYPE_FEEDER4].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_FEEDER4].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_FEEDER4;
                LOG(0,"FBM alloc Feeder4 \n");
            }
#endif
            break;
        case FBM_TYPE_DMX:
            if(!_arPool[FBM_POOL_TYPE_DMX].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DMX].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DMX;
            }
#if defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB)
            else if(!_arPool[FBM_POOL_TYPE_DMX2].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DMX2].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DMX2;
            }
#endif
#if defined(CC_FBM_FOUR_INST_SUPPORT)
            else if(!_arPool[FBM_POOL_TYPE_DMX3].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DMX3].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DMX3;
            }
            else if(!_arPool[FBM_POOL_TYPE_DMX4].fgAlloced)
            {
                _arPool[FBM_POOL_TYPE_DMX4].fgAlloced = TRUE;
                ucPoolType = FBM_POOL_TYPE_DMX4;
            }
#endif
            break;
        case FBM_TYPE_TZ_DMX:
            ucPoolType = FBM_POOL_TYPE_TZ_NONE;
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_SVP_SUPPORT)
            if(!_arPoolTZ[FBM_POOL_TYPE_TZ_DMX].fgAlloced)
            {
                if(TZ_DMX_GetSecureVfifo(&u4TZDMXAddr,&u4TZDMXSize))
                {
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX].u4Addr = u4TZDMXAddr;
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX].u4Size = u4TZDMXSize;
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_TZ_DMX;
                }
            }
#if defined(CC_VOMX_TV_COEXIST) || defined(CC_FBM_TWO_FBP_SHARED_WITH_DFB)
            else if(!_arPoolTZ[FBM_POOL_TYPE_TZ_DMX2].fgAlloced)
            {
                if(TZ_DMX_GetSecureVfifo2(&u4TZDMX2Addr,&u4TZDMX2Size))
                {
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX2].u4Addr = u4TZDMX2Addr;
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX2].u4Size = u4TZDMX2Size;
                    _arPoolTZ[FBM_POOL_TYPE_TZ_DMX2].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_TZ_DMX2;
                }
            }
#endif
#endif
            break;

        case FBM_TYPE_LAX1:
            {
                if(!_arPool[FBM_POOL_TYPE_LAX1].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_LAX1].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_LAX1;
                }
                break;
            }

        case FBM_TYPE_LAX2:
            {
                if(!_arPool[FBM_POOL_TYPE_LAX2].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_LAX2].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_LAX2;
                }
                break;
            }

        case FBM_TYPE_LAX3:
            {
                if(!_arPool[FBM_POOL_TYPE_LAX3].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_LAX3].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_LAX3;
                }
                break;
            }

        case FBM_TYPE_LAX4:
            {
                if(!_arPool[FBM_POOL_TYPE_LAX4].fgAlloced)
                {
                    _arPool[FBM_POOL_TYPE_LAX4].fgAlloced = TRUE;
                    ucPoolType = FBM_POOL_TYPE_LAX4;
                }
                break;
            }

        default:
            break;
    }

    FBM_POOL_MUTEX_UNLOCK();

    if (ucFbmType == FBM_TYPE_TZ_DMX)
    {
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_SVP_SUPPORT)
        if (ucPoolType != FBM_POOL_TYPE_TZ_NONE)
        {
            prFbmPool = &_arPoolTZ[ucPoolType];
            prFbmPool->ePoolType = (FBM_POOL_TYPE_T)ucPoolType;
        }
#endif
    }
    else
    {
        if (ucPoolType != FBM_POOL_TYPE_NONE)
        {
            prFbmPool = FBM_GetPoolInfo((UCHAR)ucPoolType);
            prFbmPool->ePoolType = (FBM_POOL_TYPE_T)ucPoolType;

            LOG(1," FBM Alloc Pool Type 0x%x\n",prFbmPool->ePoolType);
        }
    }

    return prFbmPool;
}

#if (defined(CC_S_PLATFORM) || defined(CC_FBM_CONFIG_WITH_3DTV_4K_SUPPORT))
FBM_POOL_T* FBM_AllocEx(FBM_TYPE_T eFbmType,FBM_ALLOC_PAR_T *prPar)
{
    FBM_POOL_T *prFbmPool = NULL;
    if (prPar == NULL)
    {
        LOG(0,"Para is Null\n");
        return NULL;
    }
    prFbmPool = FBM_Alloc((UCHAR)eFbmType);
    if (prFbmPool != NULL)
    {
        prFbmPool->eFbmMpegType = prPar->eFbmMpegType;
        LOG(0,"Photo Alloc Fbm Type %d\n",prFbmPool->ePoolType);
    }
    return prFbmPool;
}

BOOL FBM_Query(FBM_POOL_TYPE_T eFbmPoolType,FBM_ALLOC_PAR_T *prPar)
{
    BOOL fgAllocated = FALSE;
    if (eFbmPoolType >= FBM_POOL_TYPE_NS)
    {
        return FALSE;
    }

    LOG(0,"FBM_Query eFbmPoolType(%d) fgAlloced %d\n",eFbmPoolType,_arPool[eFbmPoolType].fgAlloced);

    if(_arPool[eFbmPoolType].fgAlloced)
    {
        fgAllocated = TRUE;
        prPar->eFbmMpegType = _arPool[eFbmPoolType].eFbmMpegType;
    }
    return fgAllocated;
}
#endif
//-------------------------------------------------------------------------
/** FBM_Free
 *  Free used Pool
 *  @param FBM Type
 *  @return 0 if success.
 */
//-------------------------------------------------------------------------

UINT32 FBM_FreeLax(FBM_POOL_LAT_T* prLatPoolAlloc)
{
    UINT32 u4LaxPoolIdx = 0;

    prLatPoolAlloc->u4Addr = 0;
    prLatPoolAlloc->u4Size = 0;
    for(u4LaxPoolIdx = 0; u4LaxPoolIdx < FBM_LAT_POOL_ALLOC_MAX; u4LaxPoolIdx++)
    {
        if(prLatPoolAlloc->pLATPoolAlloc[u4LaxPoolIdx])
        {
            FBM_Free(prLatPoolAlloc->pLATPoolAlloc[u4LaxPoolIdx]);
            prLatPoolAlloc->pLATPoolAlloc[u4LaxPoolIdx] = NULL;
        }
    }

    return 0;
}

UINT32 FBM_Free(FBM_POOL_T* pAllocedPool)
{
    if(NULL == pAllocedPool)
        return (UINT32)(-1);
    if(pAllocedPool->fgAlloced)
        pAllocedPool->fgAlloced = FALSE;

#if defined(CC_ENABLE_CMA_SUPPORT)
    LOG(0,"FBM free poolType = %d \n",pAllocedPool->ePoolType);

    //free cma memory
    CMA_FreePool((UCHAR)pAllocedPool->ePoolType);

#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT)
    //for tz secure buffer, y-c-buffer continuous
    //do nothing
#else
    //release mpeg c here.
    //_arFbg[u4FbgId].fg4k2KPoolAlocate
    //c address and size
    switch(pAllocedPool->ePoolType)
    {
        case FBM_POOL_TYPE_MPEG:
            CMA_FreePool(FBM_POOL_TYPE_MPEG_C);
            break;
        case FBM_POOL_TYPE_MPEG2:
            CMA_FreePool(FBM_POOL_TYPE_MPEG2_C);
            break;
        case FBM_POOL_TYPE_MPEG3:
            CMA_FreePool(FBM_POOL_TYPE_MPEG3_C);
            break;
        case FBM_POOL_TYPE_MPEG4:
            CMA_FreePool(FBM_POOL_TYPE_MPEG4_C);
            break;
        default:
            LOG(1, "default do nothing.\n");
            break;
    }
#endif
#else
    LOG(1,"FBM free addr 0x%x\n",pAllocedPool->u4Addr);
#endif

    return 0;
}

#if defined(CC_ENABLE_CMA_SUPPORT)
//CMA Alloc
//4k byte alignment,may hw module or mmap need this
#define CMA_PAGE_SHIFT 12
#define CMA_PAGE_SIZE (1UL << CMA_PAGE_SHIFT)
#define CMA_PAGE_MASK (~(CMA_PAGE_SIZE-1))
#define CMA_PAGE_ALIGN(addr) (((addr)+CMA_PAGE_SIZE-1) & CMA_PAGE_MASK)

extern struct platform_device mt53xx_fbm_chA_device;
extern struct platform_device mt53xx_fbm_chB_device;

CMA_POOL_T* CMA_GetPool(UCHAR ucPoolType)
{
    UPTR u4TempAddr = 0;
    HAL_TIME_T TimeST, TimeED, TimeDiff;

#ifndef CONFIG_64BIT
    struct dma_attrs attr;

    init_dma_attrs(&attr);
    dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING,&attr);
#endif

    if(_cmaPool[ucPoolType].u4PhyAddr == 0)
    {
        //==================channel A======================
        //jpeg.
        if(ucPoolType == FBM_POOL_TYPE_JPEG)
        {
            _cmaPool[ucPoolType].u4Size = FBM_JPEG_POOL_SIZE;
            _cmaPool[ucPoolType].u1ChNum = 0;
        }
        //png.
        else if(ucPoolType == FBM_POOL_TYPE_PNG)
        {
            _cmaPool[ucPoolType].u4Size = FBM_PNG_POOL_SIZE;
            _cmaPool[ucPoolType].u1ChNum = 0;
        }
        //vdp.
        else if(ucPoolType == FBM_POOL_TYPE_JPG_VDP)
        {
            _cmaPool[ucPoolType].u4Size = FBM_JPEVDP_POOL_SIZE;
            _cmaPool[ucPoolType].u1ChNum = 0;
        }
        //vss.
        else if(ucPoolType == FBM_POOL_TYPE_VSS)
        {
            _cmaPool[ucPoolType].u4Size = FBM_VSS_POOL_SIZE;
            _cmaPool[ucPoolType].u1ChNum = 0;
        }

        //==================channel B======================

#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT)   //for secure buffer
        //mpeg y/c
        else if(ucPoolType == FBM_POOL_TYPE_MPEG)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_Y_SIZE+CMA_MPEG_C_SIZE;//netflix
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG2)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_Y2_SIZE + CMA_MPEG_C2_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG_C)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_C_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG2_C)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_C2_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
#else
        //mpeg y/c
        else if(ucPoolType == FBM_POOL_TYPE_MPEG)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_Y_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG2)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_Y2_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG_C)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_C_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
        else if(ucPoolType == FBM_POOL_TYPE_MPEG2_C)
        {
            _cmaPool[ucPoolType].u4Size = CMA_MPEG_C2_SIZE;
#if defined(CC_MT5863)
            _cmaPool[ucPoolType].u1ChNum = 0;
#else
            _cmaPool[ucPoolType].u1ChNum = 1;
#endif
        }
#endif

        //==================channel C======================


        //default 2M
        else
        {
            _cmaPool[ucPoolType].u4Size = 0x200000;
            _cmaPool[ucPoolType].u1ChNum = 0;
        }
        //measure time
        HAL_GetTime(&TimeST);

        _cmaPool[ucPoolType].u4Size += CMA_PAGE_SIZE;
        //_cmaPool[ucPoolType].u4Inherit = x_mem_alloc_nocache(_cmaPool[ucPoolType].u4Size+CMA_PAGE_SIZE, &u4TempAddr);
        if(_cmaPool[ucPoolType].u1ChNum == 0) //chA alloc dma buffer
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_coherent(&(mt53xx_fbm_chA_device.dev), _cmaPool[ucPoolType].u4Size, &u4TempAddr, GFP_KERNEL|GFP_DMA|__GFP_REPEAT);
        else if(_cmaPool[ucPoolType].u1ChNum == 1) //chB alloc dma buffer
        {
#ifdef CONFIG_64BIT
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_coherent(&(mt53xx_fbm_chB_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT);
#else
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_attrs(&(mt53xx_fbm_chB_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT,&attr);
#endif
        }
        else
            LOG(0,"CMA_Alloc chC buffer!!\n");
        HAL_GetTime(&TimeED);
        if((_cmaPool[ucPoolType].u4VirtAddr) == 0)
        {
            LOG(0,"CMA_Alloc ch%d fail,ucPoolType = %d\n",_cmaPool[ucPoolType].u1ChNum,ucPoolType);
            _cmaPool[ucPoolType].u4Size = 0;
            _cmaPool[ucPoolType].u4PhyAlignAddr = 0;
            _cmaPool[ucPoolType].u4VirtAlignAddr = 0;
        }
        else
        {
            _cmaPool[ucPoolType].u4PhyAddr =u4TempAddr;
            LOG(0,"CMA_Alloc OK,ch:%d ucPoolType:%d u4PhyAddr:0x%x  u4Size:0x%x\n",_cmaPool[ucPoolType].u1ChNum,ucPoolType,u4TempAddr,_cmaPool[ucPoolType].u4Size);
            _cmaPool[ucPoolType].u4PhyAlignAddr = CMA_PAGE_ALIGN(u4TempAddr);
            LOG(0,"CMA_Alloc align u4PhyAddr:0x%x \n",_cmaPool[ucPoolType].u4PhyAlignAddr);
#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT)
            if(ucPoolType == FBM_POOL_TYPE_MPEG)
            {
                BOOL fgRet = FALSE;
                //enable tz protectRegion
                fgRet = TZ_SVP_AddProtectRegion(_cmaPool[ucPoolType].u4PhyAlignAddr,(_cmaPool[ucPoolType].u4PhyAlignAddr+_cmaPool[ucPoolType].u4Size));
                if(!fgRet)
                    LOG(0,"TZ_SVP_AddProtectRegion fail!\n");
            }
#endif
        }
        HAL_GetDeltaTime(&TimeDiff, &TimeST, &TimeED);
        LOG(0,"CMA_Alloc time consume: %u.%06u\n", TimeDiff.u4Seconds, TimeDiff.u4Micros);
        return (&_cmaPool[ucPoolType]);
    }
    else
    {
        LOG(0,"CMA_Alloc have alloc,ch:%d ucPoolType:%d align u4PhyAddr:0x%x  u4Size:0x%x\n",_cmaPool[ucPoolType].u1ChNum,ucPoolType,_cmaPool[ucPoolType].u4PhyAlignAddr,_cmaPool[ucPoolType].u4Size);
        return (&_cmaPool[ucPoolType]);
    }

}

//CMA Free
UINT32 CMA_FreePool(UCHAR ucPoolType)
{
#ifndef CONFIG_64BIT
    struct dma_attrs attr;

    init_dma_attrs(&attr);
    dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING,&attr);
#endif

    if(_cmaPool[ucPoolType].u4PhyAddr != 0 || _cmaPool[ucPoolType].u4VirtAddr != 0)
    {
        LOG(0,"CMA_FreePool free ch:%d ucPoolType:%d u4PhyAddr:0x%x  u4Size:0x%x\n",_cmaPool[ucPoolType].u1ChNum,ucPoolType,_cmaPool[ucPoolType].u4PhyAddr,_cmaPool[ucPoolType].u4Size);
        //x_mem_free((VOID*)(_cmaPool[ucPoolType].u4Inherit));
        if(_cmaPool[ucPoolType].u1ChNum == 0)
            dma_free_coherent(&(mt53xx_fbm_chA_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr);
        else if(_cmaPool[ucPoolType].u1ChNum == 1)
        {
#ifdef CONFIG_64BIT
            dma_free_coherent(&(mt53xx_fbm_chB_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr);
#else
            dma_free_attrs(&(mt53xx_fbm_chB_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr,&attr);
#endif
        }
        else
            LOG(0,"CMA_free chC buffer!!\n");

#if defined(CC_TRUSTZONE_SUPPORT) && defined(CC_TVP_SUPPORT)
        if(ucPoolType == FBM_POOL_TYPE_MPEG)
        {
            BOOL fgRet = FALSE;
            //disable tz protectRegion
            fgRet = TZ_SVP_RemoveProtectRegion(_cmaPool[ucPoolType].u4PhyAlignAddr,(_cmaPool[ucPoolType].u4PhyAlignAddr+_cmaPool[ucPoolType].u4Size));
            if(!fgRet)
                LOG(0,"TZ_SVP_RemoveProtectRegion fail!\n");
        }
#endif

        _cmaPool[ucPoolType].u4PhyAddr = 0;
        _cmaPool[ucPoolType].u4PhyAlignAddr = 0;
        _cmaPool[ucPoolType].u4VirtAddr = 0;
        _cmaPool[ucPoolType].u4VirtAlignAddr = 0;
        _cmaPool[ucPoolType].u4Size = 0;
        _cmaPool[ucPoolType].u1ChNum = 0;
        return 0;
    }
    else
    {
        LOG(0,"CMA_FreePool not need free ch:%d ucPoolType:%d !!\n",_cmaPool[ucPoolType].u1ChNum,ucPoolType);
        return 0;
    }
}

//CMA query
void CMA_QueryStatus()
{
    UCHAR ucIdx;

    LOG(0, "\n");

    for (ucIdx = 0; ucIdx < FBM_POOL_TYPE_NS; ucIdx++)
    {
        LOG(0, "PoolType[%d] early_PhyAddr[0x%x] Align_PhyAddr[0x%x] VirAddr[0x%x] Size[0x%x]\n",ucIdx, _cmaPool[ucIdx].u4PhyAddr, _cmaPool[ucIdx].u4PhyAlignAddr,_cmaPool[ucIdx].u4VirtAddr,_cmaPool[ucIdx].u4Size);
    }

}
void CMA_Alloc(UCHAR ucPoolType, UCHAR u1ChNum, UINT32 u4Size)
{
    UPTR u4TempAddr = 0;
    UINT16 u8Retry = 0;
    HAL_TIME_T TimeST, TimeED, TimeDiff;

#ifndef CONFIG_64BIT
    struct dma_attrs attr;

    init_dma_attrs(&attr);
    dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING,&attr);
#endif
    LOG(0,"dma_alloc_coherent start!!\n");
    _cmaPool[ucPoolType].u1ChNum = u1ChNum;
    _cmaPool[ucPoolType].u4Size = u4Size;
    //_cmaPool[ucPoolType].u4Inherit = x_mem_alloc_nocache(_cmaPool[ucPoolType].u4Size+CMA_PAGE_SIZE, &u4TempAddr);
    HAL_GetTime(&TimeST);
    while(++u8Retry < 1000)
    {

        if(_cmaPool[ucPoolType].u1ChNum == 0) //chA alloc dma buffer
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_coherent(&(mt53xx_fbm_chA_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT);
        else if(_cmaPool[ucPoolType].u1ChNum == 1) //chB alloc dma buffer
        {
#ifdef CONFIG_64BIT
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_coherent(&(mt53xx_fbm_chB_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT);
#else
            _cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_attrs(&(mt53xx_fbm_chB_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT,&attr);
            //_cmaPool[ucPoolType].u4VirtAddr = (UPTR)dma_alloc_coherent(&(mt53xx_fbm_chB_device.dev), _cmaPool[ucPoolType].u4Size, (dma_addr_t*)(&u4TempAddr), GFP_KERNEL|GFP_DMA|__GFP_REPEAT);
#endif
        }
        else
            LOG(0,"CMA_Alloc chC buffer!!\n");

        if(_cmaPool[ucPoolType].u4VirtAddr != 0)
        {
            break;
        }
        else
        {
            //printk("retry after 1(ms).\n");
            //x_thread_delay(1);
        }
    }

    HAL_GetTime(&TimeED);
    LOG(0,"dma_alloc_coherent end!!\n");

    if(_cmaPool[ucPoolType].u4VirtAddr == 0)
    {
        LOG(0,"CMA_Alloc ch:%d fail, size:0x%x, Retry=0x%x\n",_cmaPool[ucPoolType].u1ChNum,_cmaPool[ucPoolType].u4Size, u8Retry);
    }
    else
    {
        LOG(0,"Try Times=0x%x\n", u8Retry);
        _cmaPool[ucPoolType].u4PhyAddr = u4TempAddr;
        LOG(0,"CMA_Alloc OK,ch:%d u4PhyAddr:0x%lx u4Virtual=0x%lx u4Size:0x%x\n",
                _cmaPool[ucPoolType].u1ChNum,u4TempAddr,_cmaPool[ucPoolType].u4VirtAddr, _cmaPool[ucPoolType].u4Size);
        _cmaPool[ucPoolType].u4PhyAlignAddr = CMA_PAGE_ALIGN(u4TempAddr);
        _cmaPool[ucPoolType].u4VirtAlignAddr = _cmaPool[ucPoolType].u4VirtAddr + _cmaPool[ucPoolType].u4PhyAlignAddr - _cmaPool[ucPoolType].u4PhyAddr;
        LOG(0,"CMA_Alloc align u4PhyAlignAddr:0x%lx, u4VirtAlignAddr=0x%lx\n",_cmaPool[ucPoolType].u4PhyAlignAddr, _cmaPool[ucPoolType].u4VirtAlignAddr);
        //u4TempVirt = VIRTUAL(_cmaPool[ucPoolType].u4PhyAlignAddr);
        //*((UPTR*)u4TempVirt) = 0xffaa11223344aadd;
        //LOG(0,"u4TempVirt = 0x%lx\n, value1=0x%lx\n", u4TempVirt, *((UPTR*)u4TempVirt));
        //LOG(0,"*_cmaPool[ucPoolType].virt = 0x%lx \n", *((UPTR*)_cmaPool[ucPoolType].u4VirtAlignAddr));

    }
    HAL_GetDeltaTime(&TimeDiff, &TimeST, &TimeED);
    LOG(0,"CMA_Alloc time consume: %u.%06u\n", TimeDiff.u4Seconds, TimeDiff.u4Micros);

    return ;
}
UINT32 CMA_Free(UCHAR ucPoolType)
{
    HAL_TIME_T TimeST, TimeED, TimeDiff;
#ifndef CONFIG_64BIT
    struct dma_attrs attr;

    init_dma_attrs(&attr);
    dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING,&attr);
#endif

    if(_cmaPool[ucPoolType].u4PhyAddr != 0 || _cmaPool[ucPoolType].u4VirtAddr != 0)
    {
        LOG(0,"CMA_FreePool free22 ch:%d u4PhyAddr:0x%x  u4Size:0x%x\n",_cmaPool[ucPoolType].u1ChNum,_cmaPool[ucPoolType].u4PhyAddr,_cmaPool[ucPoolType].u4Size);
        HAL_GetTime(&TimeST);
        //x_mem_free((VOID*)(_cmaPool[ucPoolType].u4Inherit));
        if(_cmaPool[ucPoolType].u1ChNum == 0)
            dma_free_coherent(&(mt53xx_fbm_chA_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr);
        else if(_cmaPool[ucPoolType].u1ChNum == 1)
        {
#ifdef CONFIG_64BIT
            dma_free_coherent(&(mt53xx_fbm_chB_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr);
#else
            dma_free_attrs(&(mt53xx_fbm_chB_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr,&attr);
            //dma_free_coherent(&(mt53xx_fbm_chB_device.dev),_cmaPool[ucPoolType].u4Size,(VOID*)(_cmaPool[ucPoolType].u4VirtAddr),_cmaPool[ucPoolType].u4PhyAddr);
#endif
        }
        else
            LOG(0,"CMA_free chC buffer!!\n");

        HAL_GetTime(&TimeED);
        HAL_GetDeltaTime(&TimeDiff, &TimeST, &TimeED);
        LOG(0,"CMA_FreePool time consume: %u.%06u\n", TimeDiff.u4Seconds, TimeDiff.u4Micros);
        _cmaPool[ucPoolType].u4PhyAddr = 0;
        _cmaPool[ucPoolType].u4PhyAlignAddr = 0;
        _cmaPool[ucPoolType].u4VirtAddr = 0;
        _cmaPool[ucPoolType].u4VirtAlignAddr = 0;
        _cmaPool[ucPoolType].u4Size = 0;
        _cmaPool[ucPoolType].u1ChNum = 0;

    }
    else
    {
        LOG(0,"CMA_FreePool null address phy:0x%lx, vir:0x%lx !!\n",_cmaPool[ucPoolType].u4PhyAddr, _cmaPool[ucPoolType].u4VirtAddr);
    }

    return 0;
}

#endif


void FBM_CheckBufferdefine(void)
{
    LOG(1, "0x%08x = FBM_OD_SIZE\n", FBM_OD_SIZE);
    LOG(1, "0x%08x = FBM_JPEVDP_POOL_SIZE\n", FBM_JPEVDP_POOL_SIZE);
    LOG(1, "0x%08x = FBM_DMX_PID_BUF_SIZE\n", FBM_DMX_PID_BUF_SIZE);
    LOG(1, "0x%08x = FBM_VENC_SIZE\n", FBM_VENC_SIZE);
    LOG(1, "0x%08x = FBM_TWO_FBP_SIZE\n", FBM_TWO_FBP_SIZE);
    LOG(1, "0x%08x = FBM_FD_SIZE\n", FBM_FD_SIZE);
    LOG(1, "0x%08x = FBM_DIVX_SIZE\n", FBM_DIVX_SIZE);
    LOG(1, "0x%08x = VOMX_EXTRA_FRAME_BUFFER_SZ\n", VOMX_EXTRA_FRAME_BUFFER_SZ);
    LOG(1, "0x%08x = FBM_SWDMX_SIZE\n", FBM_SWDMX_SIZE);
    LOG(1, "0x%08x = FBM_VSS_SIZE\n", FBM_VSS_SIZE);
    LOG(1, "0x%08x = FBM_DRM_BUF_SIZE\n", FBM_DRM_BUF_SIZE);
    LOG(1, "0x%08x = FBM_MUXER_SIZE\n", FBM_MUXER_SIZE);
    LOG(1, "0x%08x = FBM_IMGRZ_3D_KR_BUF\n", FBM_IMGRZ_3D_KR_BUF);
    LOG(1, "0x%08x = FBM_SLT_EXTRA_SIZE\n", FBM_SLT_EXTRA_SIZE);
    LOG(1, "0x%08x = FBM_PNG_POOL_SIZE\n", FBM_PNG_POOL_SIZE);
    LOG(1, "0x%08x = FBM_TDCAV_POOL_SIZE\n", FBM_TDCAV_POOL_SIZE);
    LOG(1, "0x%08x = FBM_PQ_TOOL_SIZE\n", FBM_PQ_TOOL_SIZE);
    LOG(1, "0x%08x = FBM_DMX_ADD_SIZE\n", FBM_DMX_ADD_SIZE);
    LOG(1, "0x%08x = FBM_MUXER_SIZE\n", FBM_MUXER_SIZE);
    LOG(1, "0x%08x = FBM_TVE_POOL_FBM_SIZE\n", FBM_TVE_POOL_FBM_SIZE);
    LOG(1, "0x%08x = FBM_REDUCE_FBM_DMX_SIZE\n", FBM_REDUCE_FBM_DMX_SIZE);
}
