/* 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: osd_scaler_if.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file osd_scaler_if.c
 *  This header file includes public function definitions of OSD scaler.
 */

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

#include "osd_hw.h"
#include "osd_drvif.h"
#include "osd_debug.h"
#include "drvcust_if.h"
#include "panel.h"

LINT_EXT_HEADER_BEGIN
#include "x_ckgen.h"
//#include "hw_scpos.h"
//#include "scpos_reg.h"
LINT_EXT_HEADER_END

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

typedef struct _OSD_SCALER_INFO
{
    UINT32 u4Enable;
    UINT32 u4SrcWidth;
    UINT32 u4SrcHeight;
    UINT32 u4DstWidth;
    UINT32 u4DstHeight;
} OSD_SCALER_INFO;

//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------
static INT32 _ai4ScalerRegion[3] = { (-1), (-1), (-1) };
#ifdef SYS_3D_SUPPORT
static BOOL _fgForceSize = 0;
#endif
static OSD_SCALER_INFO arOsdScalerInfo[OSD_SCALER_MAX_NUM];

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------


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

//-----------------------------------------------------------------------------
/** cinfugure osd scaler
 *  @param  u4Scaler scaler id(only OSD_SCALER_2)
 *  @param  fgEnable enable=TRUE/disable=FALSE
 *  @param  u4SrcWidth osd input width
 *  @param  u4SrcHeight osd input height
 *  @param  u4DstWidth osd output width
 *  @param  u4DstHeight osd output height
 *  @retval OSD_RET_OK success
 */
//-----------------------------------------------------------------------------
#ifndef __USERDRV__
INT32 OSD_SC_Scale(UINT32 u4Scaler, UINT32 u4Enable, UINT32 u4SrcWidth,
                   UINT32 u4SrcHeight, UINT32 u4DstWidth, UINT32 u4DstHeight)
{
#if defined(CC_MT5893) || defined(CC_MT5895)
    INT32 u4RegionID = -1;
    UINT32 u4Plane = 0;
#endif
    OSD_VERIFY_SCALER(u4Scaler);

    CHECK_OSD_INIT();

    if ((OSD_Get_Dbg_Info(3) & 0x1) || (0 == OSD_PLA_CacheScaler(u4Scaler, u4SrcWidth, u4SrcHeight, u4DstWidth, u4DstHeight)))
    {
        return (INT32) OSD_RET_OK;
    }
    OSD_DUMP_LOG("plane:%d, scaler enable:%d, srcWidth:%d, srcHeight:%d, dstWidth:%d, dstHeight:%d\n",
            OSD_SC_GetPlane(u4Scaler) + 1, u4Enable, u4SrcWidth, u4SrcHeight, u4DstWidth, u4DstHeight);
    OSD_Dump_Stack();

    arOsdScalerInfo[u4Scaler].u4Enable = u4Enable;
    arOsdScalerInfo[u4Scaler].u4SrcWidth = u4SrcWidth;
    arOsdScalerInfo[u4Scaler].u4SrcHeight = u4SrcHeight;
    arOsdScalerInfo[u4Scaler].u4DstWidth = u4DstWidth;
    arOsdScalerInfo[u4Scaler].u4DstHeight = u4DstHeight;

#if defined(CC_MT5893) || defined(CC_MT5895)
    if (OSD_IsDualOstgDisplay() && !(OSD_Get_Dbg_Info(0x8) & 0x4))
    {
        u4Plane = OSD_SC_GetPlane(u4Scaler);
        u4RegionID = OSD_PLA_GetFirstRegion(u4Plane > OSD_RT_PLANE_1 ? (u4Plane - 5) : (u4Plane));
        return OSD_PLA_DualOstgFlipTo(u4Plane, u4RegionID);
    }
    else
#endif
    {
        return OSD_SC_DoScale(u4Scaler, u4Enable, u4SrcWidth, u4SrcHeight, u4DstWidth, u4DstHeight);
    }

    return (INT32) OSD_RET_OK;
}

INT32 OSD_SC_DoScale(UINT32 u4Scaler, UINT32 u4Enable, UINT32 u4SrcWidth,
                   UINT32 u4SrcHeight, UINT32 u4DstWidth, UINT32 u4DstHeight)
{
    UINT32 u4Tmp, u4MaxWidth, u4MaxHeight, fgPrgs;
    INT32 u4RegionID = -1;
    UINT32 u4Plane = 0;
    OSD_VERIFY_SCALER(u4Scaler);

    OSD_LockLogoDisplaying(); //for logo is displaying
    u4Plane = OSD_SC_GetPlane(u4Scaler);
    u4RegionID = OSD_PLA_GetFirstRegion(u4Plane);

#if defined(DRV_SUPPORT_EXTMJC) && !defined(CC_MTK_LOADER)

    if (IS_COMPANION_CHIP_ON())
    {
        OSD_LOG_D("drv_extmjc_set_osd_info, u4Enable=%d, u4DstWidth=%d, u4DstHeight=%d\n",
            u4Enable, u4DstWidth, u4DstHeight);
        drv_extmjc_set_osd_info(u4Enable, u4DstWidth, u4DstHeight, NULL);
    }

#endif

    if (IS_PANEL_L12R12)
    {
        u4DstHeight = u4DstHeight << 1;
    }

    u4MaxWidth = OSD_BASE_GetDisplayWidth();
    u4MaxHeight = OSD_BASE_GetDisplayHeight();
/*
#if defined(CC_MT5893) || defined(CC_MT5895)
    if (OSD_IsDualOstgDisplay())
    {
        u4MaxWidth = u4MaxWidth / 2;
    }
#endif
*/
    // add for 8k30 panel, dst height only has 12bit, so max is 4095[using 4090]
    // also, we not limit the max because it will clip source lately
    if (u4DstHeight >= 4096)
    {
        u4DstHeight = 4090;
    }
    if (u4SrcHeight >= 4096)
    {
        u4SrcHeight = 4090;
    }

    IGNORE_RET(_OSD_BASE_GetPrgs(&fgPrgs));
    ASSERT((u4MaxWidth > 0) && (u4MaxHeight > 0));

    // protect if hstart+dst_w > max_w or vstart+dst_h > max_h

    if (u4Scaler == (UINT32)OSD_SCALER_1)
    {
        IGNORE_RET(_OSD_BASE_GetOsd1HStart(&u4Tmp));
        u4MaxWidth -= u4Tmp;
        IGNORE_RET(_OSD_BASE_GetOsd1VStart(&u4Tmp));
        u4MaxHeight -= u4Tmp;
    }

    if (u4Scaler == (UINT32) OSD_SCALER_2)
    {
        IGNORE_RET(_OSD_BASE_GetOsd2HStart(&u4Tmp));
        u4MaxWidth -= u4Tmp;
        IGNORE_RET(_OSD_BASE_GetOsd2VStart(&u4Tmp));
        u4MaxHeight -= u4Tmp;
    }
    else if (u4Scaler == (UINT32) OSD_SCALER_3)
    {
        IGNORE_RET(_OSD_BASE_GetOsd3HStart(&u4Tmp));
        u4MaxWidth -= u4Tmp;
        IGNORE_RET(_OSD_BASE_GetOsd3VStart(&u4Tmp));
        u4MaxHeight -= u4Tmp;
    }

    if (u4SrcWidth == 0)
    {
        u4SrcWidth = u4MaxWidth;
    }

    if (u4DstWidth == 0)
    {
        u4DstWidth = u4MaxWidth;
    }

    if (u4SrcHeight == 0)
    {
        u4SrcHeight = (fgPrgs) ? u4MaxHeight : (u4MaxHeight << 1);
    }

    if (u4DstHeight == 0)
    {
        u4DstHeight = (fgPrgs) ? u4MaxHeight : (u4MaxHeight << 1);
    }

    if (u4SrcWidth > OSD_SC_MAX_SRCWIDTH)
    {
        u4SrcWidth = OSD_SC_MAX_SRCWIDTH;
    }

    if (((IS_PANEL_L12R12) && (u4SrcHeight > OSD_SC_MAX_SRCHEIGHT * 2)) ||
            ((!IS_PANEL_L12R12) && (u4SrcHeight > OSD_SC_MAX_SRCHEIGHT)))
    {
        u4SrcHeight = OSD_SC_MAX_SRCHEIGHT;
    }

    // modify for MW's API require
    IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, u4Enable));

    // to cut non-necessary src input
    if (u4DstWidth > u4MaxWidth)
    {
        u4SrcWidth = (u4MaxWidth * u4SrcWidth) / u4DstWidth;
        u4DstWidth = u4MaxWidth;
        // boundry condition protection
        u4SrcWidth = MAX(u4SrcWidth, 1);
        u4DstWidth = MAX(u4DstWidth, 2);
    }

    if (u4SrcWidth == u4DstWidth)
    {
        IGNORE_RET(_OSD_SC_SetHuscEn(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetSrcHSize(u4Scaler, u4SrcWidth));
        IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4SrcWidth));
        IGNORE_RET(_OSD_SC_SetDstHSize(u4Scaler, u4SrcWidth));
        // clear
        IGNORE_RET(_OSD_SC_SetHuscOfst(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetHuscStep(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetHdscEn(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetHdscOfst(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetHdscStep(u4Scaler, 0));
    }
    else
    {
        if (u4SrcWidth < u4DstWidth)
        {
            // horizontal scaling up
            IGNORE_RET(_OSD_SC_SetHuscEn(u4Scaler, 1));
            IGNORE_RET(_OSD_SC_SetHdscEn(u4Scaler, 0));
            IGNORE_RET(_OSD_SC_SetHuscOfst(u4Scaler, 0));
            u4Tmp = ((u4SrcWidth - 1) << OSD_SC_STEP_BIT) / (u4DstWidth - 1);
            IGNORE_RET(_OSD_SC_SetHuscStep(u4Scaler, u4Tmp));
            IGNORE_RET(_OSD_SC_SetSrcHSize(u4Scaler, u4SrcWidth));
            IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4SrcWidth));
            IGNORE_RET(_OSD_SC_SetDstHSize(u4Scaler, u4DstWidth));
        }
        else
        {
            // horizontal scaling down
            IGNORE_RET(_OSD_SC_SetHuscEn(u4Scaler, 0));
            u4Tmp = ((u4DstWidth << OSD_SC_STEP_BIT) / u4SrcWidth)
                    + (((u4DstWidth << OSD_SC_STEP_BIT) % u4SrcWidth) ? 1 : 0);
            IGNORE_RET(_OSD_SC_SetHdscEn(u4Scaler, 1));
            IGNORE_RET(_OSD_SC_SetHdscOfst(u4Scaler, u4Tmp));
            IGNORE_RET(_OSD_SC_SetHdscStep(u4Scaler, u4Tmp));
            IGNORE_RET(_OSD_SC_SetSrcHSize(u4Scaler, u4SrcWidth));
            IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4DstWidth));
            IGNORE_RET(_OSD_SC_SetDstHSize(u4Scaler, u4DstWidth));
        }
    }

    if (u4SrcHeight == u4DstHeight)
    {
        IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetVuscEn(u4Scaler, 0));

        if (fgPrgs)
        {
            if (u4DstHeight > u4MaxHeight)
            {
                u4DstHeight = u4MaxHeight;
            }

            IGNORE_RET(_OSD_SC_SetSrcVSize(u4Scaler, u4DstHeight));
            IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
        }
        else
        {
            u4DstHeight >>= 1;

            if (u4DstHeight > u4MaxHeight)
            {
                u4DstHeight = u4MaxHeight;
            }

            IGNORE_RET(_OSD_SC_SetSrcVSize(u4Scaler, u4DstHeight));
            IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
        }

        // clear
        IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetVscStep(u4Scaler, 0));
    }
    else
    {
        if (!fgPrgs) // interlaced mode
        {
            u4DstHeight = u4DstHeight >> 1;
        }

        if (u4DstHeight > u4MaxHeight)
        {
            u4SrcHeight = (u4MaxHeight * u4SrcHeight) / u4DstHeight;
            u4DstHeight = u4MaxHeight;
            // boundry condition protection
            u4SrcHeight = MAX(u4SrcHeight, 1);
            u4DstHeight = MAX(u4DstHeight, 2);
        }

        // "=" only happen when src=2*dst in interlaced mode
        if (u4SrcHeight <= u4DstHeight)
        {
            // vertical scaling up
            IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 0));
            IGNORE_RET(_OSD_SC_SetVuscEn(u4Scaler, 1));

            if (fgPrgs)
            {
                u4Tmp = ((u4SrcHeight - 1) << OSD_SC_STEP_BIT) / (u4DstHeight
                                                                  - 1);
                IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, 0));
                IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, 0));
            }
            else
            {
                u4Tmp = ((u4SrcHeight - 1) << OSD_SC_STEP_BIT) / (u4DstHeight);

                if ((u4Tmp % (1 << OSD_SC_STEP_BIT)) == 0)
                {
                    u4Tmp--;
                }

                IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, u4Tmp >> 2));
                IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, ((3 * u4Tmp) >> 2) &
                                                 0x3ffc));
            }

            IGNORE_RET(_OSD_SC_SetVscStep(u4Scaler, u4Tmp));
            IGNORE_RET(_OSD_SC_SetSrcVSize(u4Scaler, u4SrcHeight));
            IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
        }
        else
        {
            // vertical scaling down
            IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 1));
            IGNORE_RET(_OSD_SC_SetVuscEn(u4Scaler, 0));

            if (fgPrgs)
            {
                u4Tmp = ((u4DstHeight << OSD_SC_STEP_BIT) / u4SrcHeight)
                        + (((u4DstHeight << OSD_SC_STEP_BIT) % u4SrcHeight) ? 1
                           : 0);
                IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, u4Tmp));
                IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, u4Tmp));
            }
            else
            {
                if (u4DstHeight < (u4SrcHeight >> 1))
                {
                    //step<=0x2000
                    u4Tmp = (((u4DstHeight + 1) << OSD_SC_STEP_BIT)
                             / u4SrcHeight) + ((((u4DstHeight + 1)
                                                 << OSD_SC_STEP_BIT) % u4SrcHeight) ? 1 : 0);

                    if (u4Tmp == (1 << (OSD_SC_STEP_BIT - 1)))
                    {
                        u4Tmp--;
                    }

                    IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, u4Tmp));
                    IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, u4Tmp +
                                                     (1 << (OSD_SC_STEP_BIT - 1))));
                }
                else
                {
                    //step>0x2000
                    u4Tmp = (((u4DstHeight + 1) << OSD_SC_STEP_BIT)
                             / u4SrcHeight) + ((((u4DstHeight + 1)
                                                 << OSD_SC_STEP_BIT) % u4SrcHeight) ? 1 : 0);

                    if ((u4Tmp % (1 << OSD_SC_STEP_BIT)) == 0)
                    {
                        u4Tmp--;
                    }

                    IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, u4Tmp -
                                                     (1 << (OSD_SC_STEP_BIT - 1))));
                    IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, u4Tmp));
                }
            }

            IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 1));
            IGNORE_RET(_OSD_SC_SetVscStep(u4Scaler, u4Tmp));
            IGNORE_RET(_OSD_SC_SetSrcVSize(u4Scaler, u4SrcHeight));
            IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
        }
    }

    OSD_RGN_MirrorFlipUpdate(u4RegionID, TRUE, TRUE);
    IGNORE_RET(_OSD_SC_SetAlphaCountEn(u4Scaler, TRUE));
    _OSD_SC_UpdateHwReg(u4Scaler);

    OSD_UnLockLogoDisplaying();
     #ifndef CC_MTK_LOADER
    if (OSD_IsDualOstgDisplay())
            {
                if (PANEL_Is4K2K120())
                { 
   UINT32 i4H, i4V;

    OSD_Base_GetOffset(&i4H, &i4V); 
    OSD_Base_SetHStart();
                }
    }
    #endif

    return (INT32) OSD_RET_OK;
}
#endif

INT32 OSD_SC_HDown(UINT32 u4Scaler, UINT32 u4SrcWidth, UINT32 u4Step)
{
    UINT32 u4DstWidth;

    if (u4Scaler == OSD_SCALER_1)
    {
        return OSD_RET_INV_SCALER;
    }

    OSD_VERIFY_SCALER(u4Scaler);
    IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, 1));
    IGNORE_RET(_OSD_SC_SetHdscEn(u4Scaler, 1));
    IGNORE_RET(_OSD_SC_SetHuscEn(u4Scaler, 0));
    IGNORE_RET(_OSD_SC_SetHdscOfst(u4Scaler, u4Step));
    IGNORE_RET(_OSD_SC_SetHdscStep(u4Scaler, u4Step));
    u4DstWidth = (u4SrcWidth * u4Step) >> OSD_SC_STEP_BIT;
    IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4DstWidth));
    IGNORE_RET(_OSD_SC_SetDstHSize(u4Scaler, u4DstWidth));
    IGNORE_RET(_OSD_SC_UpdateHwReg(u4Scaler));
    return (INT32)OSD_RET_OK;
}

INT32 OSD_SC_HUp(UINT32 u4Scaler, UINT32 u4SrcWidth, UINT32 u4Step)
{
    UINT32 u4DstWidth, u4MaxWidth;
    OSD_VERIFY_SCALER(u4Scaler);
    IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, 1));
    //IGNORE_RET(_OSD_SC_SetHdscEn(u4Scaler, 0));
    IGNORE_RET(_OSD_SC_SetHuscEn(u4Scaler, 1));
    //IGNORE_RET(_OSD_SC_SetHuscOfst(u4Scaler, 0));
    IGNORE_RET(_OSD_SC_SetHuscStep(u4Scaler, u4Step));
    u4DstWidth = (((u4SrcWidth - 1) * OSD_SC_STEP_BASE) / u4Step) + 1;
    u4MaxWidth = OSD_BASE_GetDisplayWidth();

    if (u4DstWidth > u4MaxWidth)
    {
        u4DstWidth = u4MaxWidth;
        u4SrcWidth = (((u4DstWidth - 1) * u4Step) >> OSD_SC_STEP_BIT) +
                     ((((u4DstWidth - 1) * u4Step) % OSD_SC_STEP_BASE) ? 1 : 0) + 1;
        IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4SrcWidth));
        IGNORE_RET(_OSD_SC_SetSrcHSize(u4Scaler, u4SrcWidth));
    }
    else
    {
        IGNORE_RET(_OSD_SC_SetVscHSize(u4Scaler, u4SrcWidth));
    }

    IGNORE_RET(_OSD_SC_SetDstHSize(u4Scaler, u4DstWidth));
    IGNORE_RET(_OSD_SC_UpdateHwReg(u4Scaler));
    return (INT32)OSD_RET_OK;
}


INT32 OSD_SC_VDown(UINT32 u4Scaler, UINT32 u4SrcHeight, UINT32 u4Step)
{
    UINT32 u4DstHeight = 0, fgPrgs;

    if (u4Scaler == OSD_SCALER_1)
    {
        return OSD_RET_INV_SCALER;
    }

    OSD_VERIFY_SCALER(u4Scaler);
    IGNORE_RET(_OSD_BASE_GetPrgs(&fgPrgs));
    IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, 1));
    IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 1));
    IGNORE_RET(_OSD_SC_SetVuscEn(u4Scaler, 0));

    if (fgPrgs)
    {
        IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, u4Step));
        IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, u4Step));
        IGNORE_RET(_OSD_SC_SetVscStep(u4Scaler, u4Step));
        u4DstHeight = (u4SrcHeight * u4Step) >> OSD_SC_STEP_BIT;
    }

    IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
    IGNORE_RET(_OSD_SC_UpdateHwReg(u4Scaler));
    return (INT32)OSD_RET_OK;
}

INT32 OSD_SC_VUp(UINT32 u4Scaler, UINT32 u4SrcHeight, UINT32 u4Step)
{
    UINT32 u4DstHeight = 0, u4MaxHeight, fgPrgs;
    OSD_VERIFY_SCALER(u4Scaler);
    IGNORE_RET(_OSD_BASE_GetPrgs(&fgPrgs));
    IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, 1));
    //IGNORE_RET(_OSD_SC_SetVdscEn(u4Scaler, 0));
    IGNORE_RET(_OSD_SC_SetVuscEn(u4Scaler, 1));

    if (fgPrgs)
    {
        IGNORE_RET(_OSD_SC_SetVscOfstTop(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetVscOfstBot(u4Scaler, 0));
        IGNORE_RET(_OSD_SC_SetVscStep(u4Scaler, u4Step));
        u4DstHeight = (((u4SrcHeight - 1) * OSD_SC_STEP_BASE) / u4Step) + 1;
        u4MaxHeight = OSD_BASE_GetDisplayHeight();

        if (u4DstHeight > u4MaxHeight)
        {
            u4DstHeight = u4MaxHeight;
            u4SrcHeight = (((u4DstHeight - 1) * u4Step) >> OSD_SC_STEP_BIT) +
                          ((((u4DstHeight - 1) * u4Step) % OSD_SC_STEP_BASE) ?
                           1 : 0) + 1;
            IGNORE_RET(_OSD_SC_SetSrcVSize(u4Scaler, u4SrcHeight));
        }
    }

    IGNORE_RET(_OSD_SC_SetDstVSize(u4Scaler, u4DstHeight));
    IGNORE_RET(_OSD_SC_UpdateHwReg(u4Scaler));
    return (INT32)OSD_RET_OK;
}

INT32 OSD_SC_Init(UINT32 u4Scaler)
{
    // adjust scaler to fit new resolution and also reset LPF
    // defaule enable scaler for better bandwidth utilization
    IGNORE_RET(OSD_SC_DoScale(u4Scaler, TRUE, 0, 0, 0, 0));
    _OSD_SC_SetAlphaCountEn(u4Scaler, TRUE);

    return (INT32)OSD_RET_OK;
}

VOID OSD_SC_InitAll(VOID)
{
    UINT32 u4Scaler;
    for (u4Scaler = 0; u4Scaler < OSD_SCALER_MAX_NUM; u4Scaler++)
    {
        OSD_SC_Init(u4Scaler);
    }
}

VOID OSD_SC_SwResetAll(VOID)
{
    UINT32 u4Scaler;
    for (u4Scaler = 0; u4Scaler < OSD_SCALER_MAX_NUM; u4Scaler++)
    {
        _OSD_SC_ResetCacheRegs(u4Scaler);
    }
}

//-----------------------------------------------------------------------------
/** get osd scaler infomation
 *  @param  u4Scaler scaler id(only OSD_SCALER_2)
 *  @param  pu4Enable enable pointer
 *  @param  pu4SrcW osd input width pointer
 *  @param  pu4SrcH osd input height pointer
 *  @param  pu4DstW osd output width pointer
 *  @param  pu4DstH osd output height pointer
 *  @param  pu4Is16Bpp don't care
 *  @retval OSD_RET_OK success
 */
//-----------------------------------------------------------------------------
#ifndef __USERDRV__
INT32 OSD_SC_GetScalerInfo(UINT32 u4Scaler, UINT32 *pu4Enable, UINT32 *pu4SrcW,
                           UINT32 *pu4SrcH, UINT32 *pu4DstW, UINT32 *pu4DstH, UINT32 *pu4Is16Bpp)
{
    OSD_VERIFY_SCALER(u4Scaler);

    *pu4Enable = arOsdScalerInfo[u4Scaler].u4Enable;
    *pu4SrcW = arOsdScalerInfo[u4Scaler].u4SrcWidth;
    *pu4SrcH = arOsdScalerInfo[u4Scaler].u4SrcHeight;
    *pu4DstW = arOsdScalerInfo[u4Scaler].u4DstWidth;
    *pu4DstH = arOsdScalerInfo[u4Scaler].u4DstHeight;

    //_OSD_SC_GetScEn(u4Scaler, pu4Enable);
    //_OSD_SC_GetSrcHSize(u4Scaler, pu4SrcW);
    //_OSD_SC_GetSrcVSize(u4Scaler, pu4SrcH);
    //_OSD_SC_GetDstHSize(u4Scaler, pu4DstW);
    //_OSD_SC_GetDstVSize(u4Scaler, pu4DstH);
    UNUSED(pu4Is16Bpp);
    return (INT32) OSD_RET_OK;
}
#endif
UINT32 OSD_SC_GetPlane(UINT32 u4_scaler)
{
    UINT32 u4Plane = OSD_INVALID_VALUE_U32;

    switch (u4_scaler)
    {
        case OSD_SCALER_1:
            u4Plane = OSD_PLANE_1;
            break;

        case OSD_SCALER_2:
            u4Plane = OSD_PLANE_2;
            break;

        case OSD_SCALER_3:
            u4Plane = OSD_PLANE_3;
            break;
#if defined(CC_MT5893) || defined(CC_MT5895)
        case OSD_RT_SCALER_1:
        case OSD_RT_SCALER_2:
        case OSD_RT_SCALER_3:
            u4Plane = u4_scaler + 2;
            break;
#endif
        default:
            break;
    }

    return u4Plane;
}

INT32 OSD_SC_SetLpfInfo(UINT32 u4Scaler, UINT32 u4Enable, INT16 i2C1,
                        INT16 i2C2, INT16 i2C3, INT16 i2C4, INT16 i2C5)
{
    /*
     UINT32 tmp;

     OSD_VERIFY_SCALER(u4Scaler);
     IGNORE_RET(_OSD_SC_SetScLpfEn(u4Scaler, u4Enable));

     OSD_SET_LPF_SIGN_NUM(tmp, 32, i2C1);
     IGNORE_RET(_OSD_SC_SetScLpfC1(u4Scaler, tmp));

     OSD_SET_LPF_SIGN_NUM(tmp, 64, i2C2);
     IGNORE_RET(_OSD_SC_SetScLpfC2(u4Scaler, tmp));

     if ((i2C3 > 127) || (i2C3 < 0))
     {
     return -(INT32)OSD_RET_INV_ARG;
     }
     tmp = (UINT16)i2C3;
     IGNORE_RET(_OSD_SC_SetScLpfC3(u4Scaler, tmp));

     UNUSED(i2C4);
     UNUSED(i2C5);


     if (u4Enable)
     {
     IGNORE_RET(_OSD_SC_SetScEn(u4Scaler, TRUE));
     }

     IGNORE_RET(_OSD_SC_UpdateHwReg(u4Scaler));
     */
    return (INT32) OSD_RET_OK;
}

//-----------------------------------------------------------------------------
/** enable low pass filter
 *  @param  u4Scaler scaler id(only OSD_SCALER_2)
 *  @param  fgEnable enable=TRUE/disable=FALSE
 *  @retval OSD_RET_OK success
 */
//-----------------------------------------------------------------------------
INT32 OSD_SC_SetLpf(UINT32 u4Scaler, UINT32 u4Enable)
{
    return OSD_SC_SetLpfInfo(u4Scaler, u4Enable, OSD_DEFAULT_LPF_C1,
                             OSD_DEFAULT_LPF_C2, OSD_DEFAULT_LPF_C3, OSD_DEFAULT_LPF_C4,
                             OSD_DEFAULT_LPF_C5);
}

INT32 OSD_SC_GetLpfInfo(UINT32 u4Scaler, UINT32 *pu4Enable, INT16 *pi2C1,
                        INT16 *pi2C2, INT16 *pi2C3, INT16 *pi2C4, INT16 *pi2C5)
{
    return (INT32) OSD_RET_OK;
}

INT32 OSD_SC_SetRegion(UINT32 u4Scaler, INT32 i4Region)
{
    UNUSED(_ai4ScalerRegion);
    _ai4ScalerRegion[u4Scaler] = i4Region;
    return (INT32) OSD_RET_OK;
}

UINT32 OSD_PLANE_TO_SCALER(UINT32 u4Plane)
{
    UINT32 u4Scaler = OSD_INVALID_VALUE_U32;

    switch (u4Plane)
    {
        case OSD_PLANE_1:
            u4Scaler = OSD_SCALER_1;
            break;

        case OSD_PLANE_2:
            u4Scaler = OSD_SCALER_2;
            break;

        case OSD_PLANE_3:
            u4Scaler = OSD_SCALER_3;
            break;
#if defined(CC_MT5893) || defined(CC_MT5895)
        case OSD_RT_PLANE_1:
            u4Scaler = OSD_RT_SCALER_1;
            break;

        case OSD_RT_PLANE_2:
            u4Scaler = OSD_RT_SCALER_2;
            break;

        case OSD_RT_PLANE_3:
            u4Scaler = OSD_RT_SCALER_3;
            break;
#endif

        default:
            OSD_LOG_E("Unknow OSD Plane: %d\n", u4Plane);
            break;
    }

    return u4Scaler;
}



