/* 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: shuo.ding $
 * $Date: 2015/08/19 $
 * $RCSfile: osd_base_hw.c,v $
 * $Revision: #5 $
 *
 *---------------------------------------------------------------------------*/

/** @file osd_base_hw.c
 *  This header file includes function definitions of OSD base hardware...
 */

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

#include "osd_hw.h"
#include "osd_drvif.h"
#include "osd_debug.h"
#include "osd_exp.h"

#include "x_lint.h"
LINT_EXT_HEADER_BEGIN
#include "x_timer.h"
#include "x_hal_5381.h"
LINT_EXT_HEADER_END

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

/*lint -save -e960 */
#if defined(CC_MT5893) || defined(CC_MT5895)
#define OSD_BASE_SETGET_TMPL(NAME, FIELD) \
    INT32 _OSD_BASE_Set##NAME(UINT32 u4Value) \
    { \
        _rOsdBaseReg[0].rField.FIELD = u4Value; \
        _rOsdBaseReg[1].rField.FIELD = u4Value; \
        return (INT32)OSD_RET_OK; \
    } \
    INT32 _OSD_BASE_Get##NAME(UINT32 *pu4Value) \
    { \
        if(pu4Value == NULL) \
        { \
            return -(INT32)OSD_RET_INV_ARG; \
        } \
        *pu4Value = _rOsdBaseReg[0].rField.FIELD; \
        return (INT32)OSD_RET_OK; \
    } \

#define OSD_R_BASE_SETGET_TMPL(NAME, FIELD) \
        INT32 _OSD_R_BASE_Set##NAME(UINT32 u4Value) \
        { \
            _rOsdBaseReg[1].rField.FIELD = u4Value; \
            return (INT32)OSD_RET_OK; \
        } \
        INT32 _OSD_R_BASE_Get##NAME(UINT32 *pu4Value) \
        { \
            if(pu4Value == NULL) \
            { \
                return -(INT32)OSD_RET_INV_ARG; \
            } \
            *pu4Value = _rOsdBaseReg[1].rField.FIELD; \
            return (INT32)OSD_RET_OK; \
        } \

#else
#define OSD_BASE_SETGET_TMPL(NAME, FIELD) \
    INT32 _OSD_BASE_Set##NAME(UINT32 u4Value) \
    { \
        _rOsdBaseReg[0].rField.FIELD = u4Value; \
        return (INT32)OSD_RET_OK; \
    } \
    INT32 _OSD_BASE_Get##NAME(UINT32 *pu4Value) \
    { \
        if(pu4Value == NULL) \
        { \
            return -(INT32)OSD_RET_INV_ARG; \
        } \
        *pu4Value = _rOsdBaseReg[0].rField.FIELD; \
        return (INT32)OSD_RET_OK; \
    } \

#endif
/* above line is intendedly left blanc */
/*lint -restore */

#define OSD_3D_SETGET_TMPL(NAME, FIELD) \
    INT32 _OSD_3D_Set##NAME(UINT32 u4Value) \
    { \
        _rOsd3DReg[0].rField.FIELD = u4Value; \
        return (INT32)OSD_RET_OK; \
    } \
    INT32 _OSD_3D_Get##NAME(UINT32 *pu4Value) \
    { \
        if(pu4Value == NULL) \
        { \
            return -(INT32)OSD_RET_INV_ARG; \
        } \
        *pu4Value = _rOsd3DReg[0].rField.FIELD; \
        return (INT32)OSD_RET_OK; \
    } \


#define OSD_FRC_HEADER_SETGET_TMPL(NAME, FIELD) \
        INT32 _OSD_FRCHeader_Set##NAME(UINT32 u4Value) \
        { \
            _rOsdFrcHeaderReg.rField.FIELD = u4Value; \
            return (INT32)OSD_RET_OK; \
        } \
        INT32 _OSD_FRCHeader_Get##NAME(UINT32 *pu4Value) \
        { \
            if(pu4Value == NULL) \
            { \
                return -(INT32)OSD_RET_INV_ARG; \
            } \
            *pu4Value = _rOsdFrcHeaderReg.rField.FIELD; \
            return (INT32)OSD_RET_OK; \
        } \

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

#if defined(CC_DYNAMIC_IO_ADDRESS)
#ifdef __KERNEL__
#if !defined(CC_UBOOT) && !defined(CC_MTK_LOADER)
#undef IO_VIRT
#define IO_VIRT IO_VIRT_FIX
#endif
#endif
#endif

#if defined(CC_MT5893) || defined(CC_MT5895)
#define OSD_TOP_NUM 2
#else
#define OSD_TOP_NUM 1
#endif

#if defined(CC_MT5891) || defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5895)
static volatile OSD_BASE_UNION_T *_prHwOsdBaseReg[OSD_TOP_NUM] = {NULL};
static volatile OSD_3D_UNION_T *_prHwOsd3DReg[OSD_TOP_NUM] = {NULL};
#else
static volatile OSD_BASE_UNION_T *_prHwOsdBaseReg[OSD_TOP_NUM] = {(OSD_BASE_UNION_T *)OSD_BASE_REG};
static volatile OSD_3D_UNION_T *_prHwOsd3DReg[OSD_TOP_NUM] = {(OSD_3D_UNION_T *)OSD_3D_REG};
#endif
static OSD_BASE_UNION_T _rOsdBaseReg[OSD_TOP_NUM];
static OSD_3D_UNION_T _rOsd3DReg[OSD_TOP_NUM];

#if defined(CC_DYNAMIC_IO_ADDRESS)
#ifdef __KERNEL__
#if !defined(CC_UBOOT) && !defined(CC_MTK_LOADER)
#undef IO_VIRT
#define IO_VIRT IO_VIRT_DYN
#endif
#endif
#endif


static OSD_FRC_HEADER_UNION_T _rOsdFrcHeaderReg;

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



//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
#if defined(CC_MT5891) || defined(CC_MT5886) || defined(CC_MT5863) || defined(CC_MT5893) || defined(CC_MT5895)
void _OSD_Base_Init_Reg(void)
{
#if defined(CC_MT5895)
    _prHwOsdBaseReg[0] = (OSD_BASE_UNION_T *)(OSD_BASE_REG + OFFSET_64BIT_SRE);
    _prHwOsd3DReg[0] = (OSD_3D_UNION_T *)(OSD_3D_REG + OFFSET_64BIT_SRE);
    _prHwOsdBaseReg[1] = (OSD_BASE_UNION_T *)(OSD_RT_BASE_REG + OFFSET_64BIT_SRE);
    _prHwOsd3DReg[1] = (OSD_3D_UNION_T *)(OSD_RT_3D_REG + OFFSET_64BIT_SRE);
#else
    _prHwOsdBaseReg[0] = (OSD_BASE_UNION_T *)(OSD_BASE_REG + OFFSET_64BIT);
    _prHwOsd3DReg[0] = (OSD_3D_UNION_T *)(OSD_3D_REG + OFFSET_64BIT);
#if defined(CC_MT5893) || defined(CC_MT5895)
    _prHwOsdBaseReg[1] = (OSD_BASE_UNION_T *)(OSD_RT_BASE_REG + OFFSET_64BIT);
    _prHwOsd3DReg[1] = (OSD_3D_UNION_T *)(OSD_RT_3D_REG + OFFSET_64BIT);
#endif
#endif
}
#endif

void _OSD_AlwaysUpdateReg(BOOL fgEnable)
{
    UNUSED(fgEnable);
}

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
void _OSD_UpdateReg(void)
{
    if (OSD_PLA_GetAllPanelAvailable())
    {
        return;
    }

    IO_WRITE32MSK(OSD_BASE, 0, 1, 1);
#if defined(CC_MT5893) || defined(CC_MT5895)
    IO_WRITE32MSK(OSD_RT_BASE, 0, 1, 1);
#endif
}

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
INT32 _OSD_BASE_InitRegs(void)
{
    // to prevent trigger FSM reset
    IO_WRITE32(OSD_BASE, 4, 0);
#if defined(CC_MT5893) || defined(CC_MT5895)
    IO_WRITE32(OSD_RT_BASE, 4, 0);
#endif
    // delay to prevent hw crash
#ifndef CC_MTK_FPGA
    HAL_Delay_us(100);
#endif

#if defined(CC_MT5863)
    IO_WRITE32(OSD_BASE, 4, 0x3FF);
    if (IS_IC_5863_ES2())
    {
        IO_WRITE32MSK(OSD_BASE, 0x08, 1<<4, 0x10);  //21008[4]:MCLK_FRAME_RESET
    }
#elif defined(CC_MT5886)
    IO_WRITE32(OSD_BASE, 4, 0x7F);
#elif defined(CC_MT5893) 
    // keep 21004[31:8] to default value for ovl2osd direct mode on husky
    IO_WRITE32MSK(OSD_BASE, 4, 0x3F, 0x3F);
    IO_WRITE32MSK(OSD_RT_BASE, 4, 0x3F, 0x3F);
#elif defined(CC_MT5895)
    // keep 21004[31:8] to default value for ovl2osd direct mode on husky
    IO_WRITE32MSK(OSD_BASE, 4, 0x13F, 0x13F);
    IO_WRITE32MSK(OSD_RT_BASE, 4, 0x13F, 0x13F);
#else
    IO_WRITE32(OSD_BASE, 4, 0x1F);
#endif

    IO_WRITE32(OSD_INT_ENABLE_REG, 0,
        OSD1_CFUD_IEN | OSD2_CFUD_IEN | OSD2_PFUD_IEN | OSD2_VUTO_IEN
        | OSD2_VDTO_IEN | OSD3_CFUD_IEN | OSD3_PFUD_IEN
        | OSD3_VUTO_IEN | OSD3_VDTO_IEN);

    // update 3x3 matrix for YUV-to-RGB
    IO_WRITE32(OSD_BASE, 0x160, 0x01000000);
    IO_WRITE32(OSD_BASE, 0x164, 0x0164034e);
    IO_WRITE32(OSD_BASE, 0x168, 0x01001058);
    IO_WRITE32(OSD_BASE, 0x16c, 0x10b40086);
    IO_WRITE32(OSD_BASE, 0x170, 0x010001c4);
    IO_WRITE32(OSD_BASE, 0x174, 0x0000031e);
    IO_WRITE32(OSD_BASE, 0x260, 0x01000000);
    IO_WRITE32(OSD_BASE, 0x264, 0x0164034e);
    IO_WRITE32(OSD_BASE, 0x268, 0x01001058);
    IO_WRITE32(OSD_BASE, 0x26c, 0x10b40086);
    IO_WRITE32(OSD_BASE, 0x270, 0x010001c4);
    IO_WRITE32(OSD_BASE, 0x274, 0x0000031e);
    IO_WRITE32(OSD_BASE, 0x360, 0x01000000);
    IO_WRITE32(OSD_BASE, 0x364, 0x0164034e);
    IO_WRITE32(OSD_BASE, 0x368, 0x01001058);
    IO_WRITE32(OSD_BASE, 0x36c, 0x10b40086);
    IO_WRITE32(OSD_BASE, 0x370, 0x010001c4);
    IO_WRITE32(OSD_BASE, 0x374, 0x0000031e);

    // set ultra/preultra config based on ESL proposal
    IO_WRITE32MSK(OSD_BASE, 0x194, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_BASE, 0x198, 0x600000, 0xFF0000);
    IO_WRITE32MSK(OSD_BASE, 0x294, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_BASE, 0x298, 0x600000, 0xFF0000);
    IO_WRITE32MSK(OSD_BASE, 0x394, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_BASE, 0x398, 0x600000, 0xFF0000);

#if defined(CC_MT5893) || defined(CC_MT5895)
    IO_WRITE32(OSD_RT_BASE_REG + 0x30, 0,
        OSD1_CFUD_IEN | OSD2_CFUD_IEN | OSD2_PFUD_IEN | OSD2_VUTO_IEN
        | OSD2_VDTO_IEN | OSD3_CFUD_IEN | OSD3_PFUD_IEN
        | OSD3_VUTO_IEN | OSD3_VDTO_IEN);

    // update 3x3 matrix for YUV-to-RGB
    IO_WRITE32(OSD_RT_BASE_REG, 0x160, 0x01000000);
    IO_WRITE32(OSD_RT_BASE_REG, 0x164, 0x0164034e);
    IO_WRITE32(OSD_RT_BASE_REG, 0x168, 0x01001058);
    IO_WRITE32(OSD_RT_BASE_REG, 0x16c, 0x10b40086);
    IO_WRITE32(OSD_RT_BASE_REG, 0x170, 0x010001c4);
    IO_WRITE32(OSD_RT_BASE_REG, 0x174, 0x0000031e);
    IO_WRITE32(OSD_RT_BASE_REG, 0x260, 0x01000000);
    IO_WRITE32(OSD_RT_BASE_REG, 0x264, 0x0164034e);
    IO_WRITE32(OSD_RT_BASE_REG, 0x268, 0x01001058);
    IO_WRITE32(OSD_RT_BASE_REG, 0x26c, 0x10b40086);
    IO_WRITE32(OSD_RT_BASE_REG, 0x270, 0x010001c4);
    IO_WRITE32(OSD_RT_BASE_REG, 0x274, 0x0000031e);
    IO_WRITE32(OSD_RT_BASE_REG, 0x360, 0x01000000);
    IO_WRITE32(OSD_RT_BASE_REG, 0x364, 0x0164034e);
    IO_WRITE32(OSD_RT_BASE_REG, 0x368, 0x01001058);
    IO_WRITE32(OSD_RT_BASE_REG, 0x36c, 0x10b40086);
    IO_WRITE32(OSD_RT_BASE_REG, 0x370, 0x010001c4);
    IO_WRITE32(OSD_RT_BASE_REG, 0x374, 0x0000031e);

    // set ultra/preultra config based on ESL proposal
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x194, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x198, 0x600000, 0xFF0000);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x294, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x298, 0x600000, 0xFF0000);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x394, 0x1A04080, 0x1FFFF80);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x398, 0x600000, 0xFF0000);

    // disable cursor plane burst8 mode
    IO_WRITE32MSK(OSD_BASE_REG, 0x794, 0, 0x80);
    IO_WRITE32MSK(OSD_RT_BASE_REG, 0x794, 0, 0x80);

#endif
#ifdef OSD_RESET_BASE_ZERO
    IO_WRITE32(OSD_BASE, 0, 0);
#if defined(CC_MT5893) || defined(CC_MT5895)
    IO_WRITE32(OSD_RT_BASE_REG, 0, 0);
#endif
#endif
    _OSD_BASE_SwSetReg();
    IGNORE_RET(_OSD_BASE_SetYuvOut(0));
    IGNORE_RET(_OSD_BASE_SetVsWidth(1));
    IGNORE_RET(_OSD_BASE_SetOsd1HStart(0));
    IGNORE_RET(_OSD_BASE_SetOsd2HStart(0));
    IGNORE_RET(_OSD_BASE_SetOsd3HStart(0));
    IGNORE_RET(_OSD_BASE_SetOsd1VStart(0));
    IGNORE_RET(_OSD_BASE_SetOsd2VStart(0));
    IGNORE_RET(_OSD_BASE_SetOsd3VStart(0));
    //For syncing set data function in output stage
    IGNORE_RET(_OSD_BASE_SetOSD2LvdsEn(1));
    IGNORE_RET(_OSD_BASE_SetOSD2LvdsEn(0));
    IGNORE_RET(_OSD_BASE_UpdateHwReg());

    return (INT32) OSD_RET_OK;
}

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
INT32 _OSD_BASE_SwSetReg(void)
{
    INT32 u4Idx = OSD_BASE_SKIP;

    for (; u4Idx < OSD_BASE_REG_NUM; u4Idx++)
    {
        _rOsdBaseReg[0].au4Reg[u4Idx] = _prHwOsdBaseReg[0]->au4Reg[u4Idx];
    }

#if defined(CC_MT5893) || defined(CC_MT5895)
    for (u4Idx = OSD_BASE_SKIP; u4Idx < OSD_BASE_REG_NUM; u4Idx++)
    {
        _rOsdBaseReg[1].au4Reg[u4Idx] = _prHwOsdBaseReg[1]->au4Reg[u4Idx];
    }
#endif

    return (INT32) OSD_RET_OK;
}

INT32 _OSD_BASE_UpdateHwReg(void)
{
    UINT32 u4Idx = OSD_BASE_SKIP;

    for (; u4Idx < OSD_BASE_REG_NUM; u4Idx++)
    {
        if ((u4Idx < OSD_BASE_SKIP_START) || (u4Idx > OSD_BASE_SKIP_END))
        {
            _prHwOsdBaseReg[0]->au4Reg[u4Idx] = _rOsdBaseReg[0].au4Reg[u4Idx];
        }
    }
#if defined(CC_MT5893) || defined(CC_MT5895)
    for (u4Idx = OSD_BASE_SKIP; u4Idx < OSD_BASE_REG_NUM; u4Idx++)
    {
        if ((u4Idx < OSD_BASE_SKIP_START) || (u4Idx > OSD_BASE_SKIP_END))
        {
            _prHwOsdBaseReg[1]->au4Reg[u4Idx] = _rOsdBaseReg[1].au4Reg[u4Idx];
        }
    }
#endif

    _OSD_UpdateReg();
    return (INT32) OSD_RET_OK;
}

INT32 _OSD_COPY_FRCHeader(UPTR upDstAddr)
{
    x_memcpy((void *)upDstAddr, (void *)(UPTR)&_rOsdFrcHeaderReg,
             sizeof(_rOsdFrcHeaderReg));
    return (INT32) OSD_RET_OK;
}

INT32 _OSD_InitFRCHeader(void)
{
    x_memset(&_rOsdFrcHeaderReg, 0x0, sizeof(_rOsdFrcHeaderReg));
    _OSD_FRCHeader_SetFormat(0);
    _OSD_FRCHeader_SetPixOrder(0);
    _OSD_FRCHeader_SetLRindex(0);
    _OSD_FRCHeader_SetBmpindex(0);
    _OSD_FRCHeader_SetFramenum(0);
    _OSD_FRCHeader_SetPrefix(0xA);
    _OSD_FRCHeader_SetBmpHeight(0);
    _OSD_FRCHeader_SetBmpWidth(0);
    _OSD_FRCHeader_SetGlobalAlpha(0xFF);
    _OSD_FRCHeader_SetPixelAlphaEn(0);
    _OSD_FRCHeader_SetGlobalAlphaEn(1);
    _OSD_FRCHeader_SetOsdUpper(1);
    _OSD_FRCHeader_SetDispYOFF(0);
    _OSD_FRCHeader_SetDispXOFF(0);
    _OSD_FRCHeader_SetDispHeight(0);
    _OSD_FRCHeader_SetDispWidth(0);
    return (INT32) OSD_RET_OK;
}

INT32 _OSD_3D_InitRegs(void)
{
    INT32 u4Idx = 0;

    for (; u4Idx < 2; u4Idx++)
    {
        _rOsd3DReg[0].au4Reg[u4Idx] = _prHwOsd3DReg[0]->au4Reg[u4Idx];
    }

    return (INT32)OSD_RET_OK;
}

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
INT32 _OSD_3D_UpdateHwReg(void)
{
    UINT32 u4Idx = 0;

    for (; u4Idx < 2; u4Idx++)
    {
        _prHwOsd3DReg[0]->au4Reg[u4Idx] = _rOsd3DReg[0].au4Reg[u4Idx];
    }
#if defined(CC_MT5893) || defined(CC_MT5895)
    for (u4Idx = 0; u4Idx < 2; u4Idx++)
    {
        _prHwOsd3DReg[1]->au4Reg[u4Idx] = _rOsd3DReg[0].au4Reg[u4Idx];
    }
#endif

    _OSD_UpdateReg();
    return (INT32)OSD_RET_OK;
}

//-----------------------------------------------------------------------------
/** dump osd debug info
 *  @param  void
 *  @return void
 */
//-----------------------------------------------------------------------------
void OSD_BASE_Dump(void)
{
    UINT32 u4IntStatus;
    UINT32 u4TimingSel;
    u4IntStatus = IO_READ32(OSD_INT_STATUS_REG, 0);
    u4TimingSel = OSD_EXP_TimGenVal();
    LOG(0,"\nOSD BASE\n");
    LOG(0,"    OSD TIMING SEL[%d] (0:front timing 1:post timing 2:gfx timing)\n", u4TimingSel);
    LOG(0,"    OSD INTERRUPT=0x%x \n", u4IntStatus);

    if (u4IntStatus == 0)
    {
        LOG(0,"None\n");
    }
    else
    {
        if ((u4IntStatus & OSD_INT) > 0)
        {
            LOG(0,"(OSD_INT)");
        }

        if ((u4IntStatus & OSD1_CFUD_IID) > 0)
        {
            LOG(0,"(OSD1_CFUD_IID)");
        }

        if ((u4IntStatus & OSD2_CFUD_IID) > 0)
        {
            LOG(0,"(OSD2_CFUD_IID)");
        }

        if ((u4IntStatus & OSD2_PFUD_IID) > 0)
        {
            LOG(0,"(OSD2_PFUD_IID)");
        }

        if ((u4IntStatus & OSD2_VUTO_IID) > 0)
        {
            LOG(0,"(OSD2_VUTO_IID)");
        }

        if ((u4IntStatus & OSD2_VDTO_IID) > 0)
        {
            LOG(0,"(OSD2_VDTO_IID)");
        }

        if ((u4IntStatus & OSD3_CFUD_IID) > 0)
        {
            LOG(0,"(OSD3_CFUD_IID)");
        }

        if ((u4IntStatus & OSD3_PFUD_IID) > 0)
        {
            LOG(0,"(OSD3_PFUD_IID)");
        }

        if ((u4IntStatus & OSD3_VUTO_IID) > 0)
        {
            LOG(0,"(OSD3_VUTO_IID)");
        }

        if ((u4IntStatus & OSD3_VDTO_IID) > 0)
        {
            LOG(0,"(OSD3_VDTO_IID)");
        }

        LOG(0,"\n");
        IO_WRITE32(OSD_INT_STATUS_REG, 0, 0);
    }

#if defined(CC_MT5893) || defined(CC_MT5895)
    u4IntStatus = IO_READ32(OSD_RT_BASE_REG + 0x34, 0);
    LOG(0,"\nOSD RIGHT BASE\n");
    LOG(0,"    OSD INTERRUPT=0x%x ", u4IntStatus);

    if (u4IntStatus == 0)
    {
        LOG(0,"None\n");
    }
    else
    {
        if ((u4IntStatus & OSD_INT) > 0)
        {
            LOG(0,"(OSD_INT)");
        }

        if ((u4IntStatus & OSD1_CFUD_IID) > 0)
        {
            LOG(0,"(OSD1_CFUD_IID)");
        }

        if ((u4IntStatus & OSD2_CFUD_IID) > 0)
        {
            LOG(0,"(OSD2_CFUD_IID)");
        }

        if ((u4IntStatus & OSD2_PFUD_IID) > 0)
        {
            LOG(0,"(OSD2_PFUD_IID)");
        }

        if ((u4IntStatus & OSD2_VUTO_IID) > 0)
        {
            LOG(0,"(OSD2_VUTO_IID)");
        }

        if ((u4IntStatus & OSD2_VDTO_IID) > 0)
        {
            LOG(0,"(OSD2_VDTO_IID)");
        }

        if ((u4IntStatus & OSD3_CFUD_IID) > 0)
        {
            LOG(0,"(OSD3_CFUD_IID)");
        }

        if ((u4IntStatus & OSD3_PFUD_IID) > 0)
        {
            LOG(0,"(OSD3_PFUD_IID)");
        }

        if ((u4IntStatus & OSD3_VUTO_IID) > 0)
        {
            LOG(0,"(OSD3_VUTO_IID)");
        }

        if ((u4IntStatus & OSD3_VDTO_IID) > 0)
        {
            LOG(0,"(OSD3_VDTO_IID)");
        }

        LOG(0,"\n");
        IO_WRITE32(OSD_INT_STATUS_REG, 0, 0);
    }
#endif

    LOG(0,"    HCNT_STROBE=%d, VCNT_STROBE=%d\n",
           _prHwOsdBaseReg[0]->rField.u4HcntStrobe,
           _prHwOsdBaseReg[0]->rField.u4VcntStrobe);
    LOG(0,"    HCNT_STATUS=%d, VCNT_STATUS=%d, FIFO MONITOR=0x%x\n",
           _prHwOsdBaseReg[0]->rField.u4HcntStatus,
           _prHwOsdBaseReg[0]->rField.u4VcntStatus,
           IO_READ32(OSD_FIFO_MONITOR_REG, 0));

    if (!_prHwOsd3DReg[0])
    {
        return;
    }

    LOG(0,"    OSD 3D\n");
    LOG(0,"        Shutter LR\n");
    LOG(0,"          SHUTTER_SHIFT_EN=%d, SHUTTER_LR_FLAG=%d\n",
           _prHwOsd3DReg[0]->rField.fgShutterShiftEn,
           _prHwOsd3DReg[0]->rField.fgShutterLRFlag);
    LOG(0,"          TGEN_(LR_EN=%d, LLRR=%d, LR_DLY=%d, LR_INV=%d)\n",
           _prHwOsd3DReg[0]->rField.fgTgenLREn,
           _prHwOsd3DReg[0]->rField.fgTgenLLRREn,
           _prHwOsd3DReg[0]->rField.fgTgenLRDly,
           _prHwOsd3DReg[0]->rField.fgTgenLRInv);
    LOG(0,"        PR\n");
    LOG(0,"          PLANE_SWITCH_EN=%d, PLANE_SWITCH_INV=%d\n",
           _prHwOsd3DReg[0]->rField.fgPlaneSwitchEn,
           _prHwOsd3DReg[0]->rField.fgPlaneSwitchInv);
    LOG(0,"        Line Shift(2D->3D)\n");
    LOG(0,"          _LINE_SHIFT_EN ( OSD1=%d, OSD2=%d, OSD3=%d, CSR=%d )\n",
           _prHwOsd3DReg[0]->rField.fgOsd1LShiftEn,
           _prHwOsd3DReg[0]->rField.fgOsd2LShiftEn,
           _prHwOsd3DReg[0]->rField.fgOsd3LShiftEn,
           _prHwOsd3DReg[0]->rField.fgCsrLShiftEn);
    LOG(0,"          _LINE_SHIFT_INV( OSD1=%d, OSD2=%d, OSD3=%d, CSR=%d )\n",
           _prHwOsd3DReg[0]->rField.fgOsd1LShiftInv,
           _prHwOsd3DReg[0]->rField.fgOsd2LShiftInv,
           _prHwOsd3DReg[0]->rField.fgOsd3LShiftInv,
           _prHwOsd3DReg[0]->rField.fgCsrLShiftInv);
    LOG(0,"          _LINE_SHIFT    ( OSD1=%d, OSD2=%d, OSD3=%d, CSR=%d )\n",
           _prHwOsd3DReg[0]->rField.fgOsd1ShiftValue,
           _prHwOsd3DReg[0]->rField.fgOsd2ShiftValue,
           _prHwOsd3DReg[0]->rField.fgOsd3ShiftValue,
           _prHwOsd3DReg[0]->rField.fgCsrShiftValue);
    return;
}


OSD_BASE_SETGET_TMPL(Update, fgUpdate)
OSD_BASE_SETGET_TMPL(AlwaysUpdate, fgAlwaysUpdate)
OSD_BASE_SETGET_TMPL(ResetFsm, fgResetFsm)
OSD_BASE_SETGET_TMPL(ResetAll, fgResetAll)
OSD_BASE_SETGET_TMPL(FrameReset, fgFrameReset)
OSD_BASE_SETGET_TMPL(HsEdge, fgHsEdge)
OSD_BASE_SETGET_TMPL(VsEdge, fgVsEdge)
OSD_BASE_SETGET_TMPL(FldPol, fgFldPol)
OSD_BASE_SETGET_TMPL(Prgs, fgPrgs)
OSD_BASE_SETGET_TMPL(IntTGen, fgIntTGen)
OSD_BASE_SETGET_TMPL(ChecksumEn, fgChecksumEn)
OSD_BASE_SETGET_TMPL(AutoPos, fgAutoPos)
OSD_BASE_SETGET_TMPL(YuvOut, fgYuvOut)
OSD_BASE_SETGET_TMPL(OSD12Ex, fgOSD12Ex)
OSD_BASE_SETGET_TMPL(SyncSrcSel, fgSyncSrcSel)
OSD_BASE_SETGET_TMPL(ABISTEn, fgABISTEn)
OSD_BASE_SETGET_TMPL(VsWidth, u4VsWidth)
OSD_BASE_SETGET_TMPL(Oht, u4Oht)
OSD_BASE_SETGET_TMPL(Ovt, u4Ovt)
OSD_BASE_SETGET_TMPL(ScrnHStartOsd2, u4ScrnHStartOsd2)
OSD_BASE_SETGET_TMPL(ScrnHStartOsd1, u4ScrnHStartOsd1)
OSD_BASE_SETGET_TMPL(ScrnHStartOsd3, u4ScrnHStartOsd3)
OSD_BASE_SETGET_TMPL(ScrnHStartCSR, u4ScrnHStartCSR)
OSD_BASE_SETGET_TMPL(ScrnVStart, u4ScrnVStart)
#if defined(CC_MT5895)
OSD_BASE_SETGET_TMPL(SrcTimingSel, fgSrcTimingSel)
#endif

OSD_BASE_SETGET_TMPL(Osd1VStart, u4Osd1VStart)
OSD_BASE_SETGET_TMPL(Osd1HStart, u4Osd1HStart)
OSD_BASE_SETGET_TMPL(Osd2VStart, u4Osd2VStart)
OSD_BASE_SETGET_TMPL(Osd2HStart, u4Osd2HStart)
OSD_BASE_SETGET_TMPL(Osd3VStart, u4Osd3VStart)
OSD_BASE_SETGET_TMPL(Osd3HStart, u4Osd3HStart)
OSD_BASE_SETGET_TMPL(CsrHStart, u4CsrHStart)
OSD_BASE_SETGET_TMPL(CsrVStart, u4CsrVStart)
OSD_BASE_SETGET_TMPL(HsWidth, u4HsWidth)
OSD_BASE_SETGET_TMPL(DelayAdj, u4DelayAdj)

#if defined(CC_MT5893) || defined(CC_MT5895)
OSD_R_BASE_SETGET_TMPL(Osd1HStart, u4Osd1HStart)
OSD_R_BASE_SETGET_TMPL(Osd2HStart, u4Osd2HStart)
OSD_R_BASE_SETGET_TMPL(Osd3HStart, u4Osd3HStart)
OSD_R_BASE_SETGET_TMPL(CsrHStart, u4CsrHStart)
OSD_R_BASE_SETGET_TMPL(ScrnHStartOsd2, u4ScrnHStartOsd2)
OSD_R_BASE_SETGET_TMPL(ScrnHStartOsd1, u4ScrnHStartOsd1)
OSD_R_BASE_SETGET_TMPL(ScrnHStartOsd3, u4ScrnHStartOsd3)
OSD_R_BASE_SETGET_TMPL(ScrnHStartCSR, u4ScrnHStartCSR)
#endif

#ifdef OSD_TRANS_CTRL
OSD_BASE_SETGET_TMPL(TransferCtl, fgTransferCtl)
#endif
OSD_BASE_SETGET_TMPL(OSD2LvdsEn, fgOSD2LvdsEn)

OSD_BASE_SETGET_TMPL(OSD1Switch, fgOSD1Switch)
OSD_BASE_SETGET_TMPL(OSD2Switch, fgOSD2Switch)
OSD_BASE_SETGET_TMPL(OSD3Switch, fgOSD3Switch)

#if defined(CC_MT5893) || defined(CC_MT5895)
OSD_BASE_SETGET_TMPL(OvlShareOsdScaler, fgOvlShareOsdScaler)
OSD_BASE_SETGET_TMPL(OvlOsd3FifoRem, fgOvlOsd3FifoRem)
OSD_BASE_SETGET_TMPL(OvlOsd3FifoFullTh, fgOvlOsd3FifoFullTh)
OSD_BASE_SETGET_TMPL(OvlOsd3FifoEmpTh, fgOvlOsd3FifoEmpTh)
#endif

OSD_3D_SETGET_TMPL(TgenLREn, fgTgenLREn)
OSD_3D_SETGET_TMPL(Osd2LShiftEn, fgOsd2LShiftEn)
OSD_3D_SETGET_TMPL(PlaneSwitchEn, fgPlaneSwitchEn)
OSD_3D_SETGET_TMPL(PlaneSwitchInv, fgPlaneSwitchInv)


OSD_3D_SETGET_TMPL(ShutterShiftEn, fgShutterShiftEn)
OSD_3D_SETGET_TMPL(Osd1LShiftEn, fgOsd1LShiftEn)
OSD_3D_SETGET_TMPL(Osd3LShiftEn, fgOsd3LShiftEn)
OSD_3D_SETGET_TMPL(CsrLShiftEn, fgCsrLShiftEn)

OSD_3D_SETGET_TMPL(Osd2LShiftInv, fgOsd2LShiftInv)

OSD_3D_SETGET_TMPL(Osd1ShiftValue, fgOsd1ShiftValue)
OSD_3D_SETGET_TMPL(Osd2ShiftValue, fgOsd2ShiftValue)
OSD_3D_SETGET_TMPL(Osd3ShiftValue, fgOsd3ShiftValue)
OSD_3D_SETGET_TMPL(CsrShiftValue, fgCsrShiftValue)


OSD_FRC_HEADER_SETGET_TMPL(Format, fgFormat)
OSD_FRC_HEADER_SETGET_TMPL(PixOrder, fgPixelOrder)
OSD_FRC_HEADER_SETGET_TMPL(LRindex, fgLR)
OSD_FRC_HEADER_SETGET_TMPL(Bmpindex, fg3DBmp)
OSD_FRC_HEADER_SETGET_TMPL(Framenum, fgOSDFramenum)
OSD_FRC_HEADER_SETGET_TMPL(Prefix, fgOSDPrefix)
OSD_FRC_HEADER_SETGET_TMPL(BmpHeight, fgBmpHeight)
OSD_FRC_HEADER_SETGET_TMPL(BmpWidth, fgBmpWidth)
OSD_FRC_HEADER_SETGET_TMPL(GlobalAlpha, fgGlobalAlpha)
OSD_FRC_HEADER_SETGET_TMPL(PixelAlphaEn, fgPixelAlphaEn)
OSD_FRC_HEADER_SETGET_TMPL(GlobalAlphaEn, fgGlobalAlphaEn)
OSD_FRC_HEADER_SETGET_TMPL(OsdUpper, fgOsdUpper)
OSD_FRC_HEADER_SETGET_TMPL(DispYOFF, fgDispYOFF)
OSD_FRC_HEADER_SETGET_TMPL(DispXOFF, fgDispXOFF)
OSD_FRC_HEADER_SETGET_TMPL(DispHeight, fgDispHeight)
OSD_FRC_HEADER_SETGET_TMPL(DispWidth, fgDispWidth)

