/**
 * @file hv_cal_OsdRect.c
 * @brief Osd Cal Rect interface file.
 * @details This file provides the following functions: \n
 *          (1) Osd CAL layer initialization functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-31
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author         <th>Date        <th>Change Description
 * <tr><td>OSD Group      <td>2022-08-31   <td>create
 * </table>
*/

#include "hv_drv_Osd.h"
#include "hv_cal_Osd.h"

static OsdRectPhyId g_enCurrentRectIndex = PHY_WIN0_RECT_0;

static OsdWindowPhyId Hv_Cal_OsdRect_GetWindowIndex(VOID)
{
    if (g_enCurrentRectIndex < PHY_RECT0_RECT_0)
    {
        return g_enCurrentRectIndex >> 2;
    }
    else if (g_enCurrentRectIndex < PHY_RECT1_RECT_0)
    {
        return PHY_WIN_RECT_0;
    }
    else
    {
        return PHY_WIN_RECT_1;
    }
}

static UINT32 Hv_Cal_OsdRect_GetBaseAddr(VOID)
{
    OsdWindowPhyId enWinIndex = Hv_Cal_OsdRect_GetWindowIndex();
    UINT32 uiBaseAddr = Hv_Cal_OsdWindow_GetBaseAddr(enWinIndex);

    if (OSD_WINDOW_IS_NORMAL(enWinIndex))
    {
        return uiBaseAddr + _NORMAL_WIN_RECT_OFFSET + (g_enCurrentRectIndex - (enWinIndex << 2)) * OSD_RECT_SIZE;
    }
    else
    {
        return uiBaseAddr + _RECT_WIN_RECT_OFFSET + ((g_enCurrentRectIndex - PHY_RECT0_RECT_0) % 8) * OSD_RECT_SIZE;
    }
}

static INT32 Hv_Cal_OsdRect_GetAddrOffset(VOID)
{
    OsdWindowPhyId enWinIndex = Hv_Cal_OsdRect_GetWindowIndex();
    INT32 iAddrOff = enWinIndex * OSD_WIN_SIZE;

    if (OSD_WINDOW_IS_NORMAL(enWinIndex))
    {
        iAddrOff += (g_enCurrentRectIndex - (enWinIndex << 2)) * OSD_RECT_SIZE;
    }
    else
    {
        iAddrOff += ((g_enCurrentRectIndex - PHY_RECT0_RECT_0) % 8) * OSD_RECT_SIZE;
        iAddrOff += _RECT_WIN_RECT_OFFSET - _NORMAL_WIN_RECT_OFFSET;
    }

    return iAddrOff;
}

VOID Hv_Cal_OsdRect_SetCurrentRect(OsdRectPhyId enIndex)
{
    HV_ASSERT_TRUE_VOID(enIndex < PHY_RECT_ID_MAX);

    g_enCurrentRectIndex = enIndex;
}

VOID Hv_Cal_OsdRect_SetEnable(BOOL bEnable)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_enable_rect0, bEnable);
}

BOOL Hv_Cal_OsdRect_GetEnable(VOID)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();
    HV_R32_DECL_VAR();

    return HV_R32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_enable_rect0);
}

VOID Hv_Cal_OsdRect_SetPos(USHORT16 usX, USHORT16 usY)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_04, iAddrOff, reg_00_start_x_rect0, usX + 1);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_04, iAddrOff, reg_00_start_y_rect0, usY + 1);
}

VOID Hv_Cal_OsdRect_GetPos(USHORT16 *pusX, USHORT16 *pusY)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();
    HV_R32_DECL_VAR();

    *pusX = HV_R32_FIELD_EX(OSD_KV_WIN_P4_00_04, iAddrOff, reg_00_start_x_rect0);
    *pusX = (*pusX > 0) ? (*pusX - 1) : 0;
    *pusY = HV_R32_FIELD_EX(OSD_KV_WIN_P4_00_04, iAddrOff, reg_00_start_y_rect0);
    *pusY = (*pusY > 0) ? (*pusY - 1) : 0;
}

VOID Hv_Cal_OsdRect_SetSize(USHORT16 usWidth, USHORT16 usHeight)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();
    HV_R32_DECL_VAR();

    /* IP actually draws one line more than height set */
    usWidth = (usWidth > 0) ? (usWidth - 1) : 0;
    usHeight = (usHeight > 0) ? (usHeight - 1) : 0;

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_08, iAddrOff, reg_00_size_x_rect0, usWidth);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_08, iAddrOff, reg_00_size_y_rect0, usHeight);
}

VOID Hv_Cal_OsdRect_GetSize(USHORT16 *pusWidth, USHORT16 *pusHeight)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();
    HV_R32_DECL_VAR();

    *pusWidth = HV_R32_FIELD_EX(OSD_KV_WIN_P4_00_08, iAddrOff, reg_00_size_x_rect0) + 1;
    *pusHeight = HV_R32_FIELD_EX(OSD_KV_WIN_P4_00_08, iAddrOff, reg_00_size_y_rect0) + 1;
}

VOID Hv_Cal_OsdRect_SetBorderEnable(BOOL bEnable)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_border_enable_rect0, bEnable);
}

VOID Hv_Cal_OsdRect_SetBorderType(OsdRectBorderType enType)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();
    INT32 iTypeValue = 0;

    if (OSD_BORDER_2D == enType)
    {
        iTypeValue = 0;
    }
    else if (OSD_BORDER_3D == enType)
    {
        iTypeValue = 0x8;
    }
    else
    {
        return;
    }

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_border_type_rect0, iTypeValue);
}

VOID Hv_Cal_OsdRect_SetBorderSize(UCHAR8 ucSizeX, UCHAR8 ucSizeY)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    /* IP restriction */
    ucSizeX = (ucSizeX > 0) ? (ucSizeX - 1) : 0;
    ucSizeX = (ucSizeX > OSD_BORDER_SIZE_MAX) ? OSD_BORDER_SIZE_MAX : ucSizeX;
    ucSizeY = (ucSizeY > 0) ? (ucSizeY - 1) : 0;
    ucSizeY = (ucSizeY > OSD_BORDER_SIZE_MAX) ? OSD_BORDER_SIZE_MAX : ucSizeY;
    
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_border_size_x_rect0, ucSizeX);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_border_size_y_rect0, ucSizeY);
}

VOID Hv_Cal_OsdRect_SetBorderColor(USHORT16 usTopColor, USHORT16 usBottomColor, USHORT16 usLeftColor, USHORT16 usRightColor)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_0C, iAddrOff, reg_00_border_color0_rect0, usTopColor);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_0C, iAddrOff, reg_00_border_color1_rect0, usBottomColor);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_10, iAddrOff, reg_00_border_color2_rect0, usLeftColor);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_10, iAddrOff, reg_00_border_color3_rect0, usRightColor);
}

VOID Hv_Cal_OsdRect_SetShadowEnable(BOOL bEnable)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_shadow_enable_rect0, bEnable);
}

VOID Hv_Cal_OsdRect_SetShadowType(OsdRectShadowType enType)
{
    HV_ASSERT_TRUE_VOID(enType < OSD_SHADOW_MAX);

    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_shadow_type_rect0, enType);
}

VOID Hv_Cal_OsdRect_SetShadowSize(UCHAR8 ucSizeX, UCHAR8 ucSizeY)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    /* IP restriction */
    ucSizeX = (ucSizeX > 0) ? (ucSizeX - 1) : 0;
    ucSizeX = (ucSizeX > OSD_SHADOW_SIZE_MAX) ? OSD_SHADOW_SIZE_MAX : ucSizeX;
    ucSizeY = (ucSizeY > 0) ? (ucSizeY - 1) : 0;
    ucSizeY = (ucSizeY > OSD_SHADOW_SIZE_MAX) ? OSD_SHADOW_SIZE_MAX : ucSizeY;
    
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_shadow_size_x_rect0, ucSizeX);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_shadow_size_y_rect0, ucSizeY);
}

VOID Hv_Cal_OsdRect_SetShadowColor(USHORT16 usColor)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_14, iAddrOff, reg_00_shadow_color_rect0, usColor);
}

VOID Hv_Cal_OsdRect_SetBackgroundEnable(BOOL bEnable)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_fill_enable_rect0, bEnable);
}

VOID Hv_Cal_OsdRect_SetBackgroundColor(USHORT16 usStartColor, USHORT16 usEndColor)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_1C, iAddrOff, reg_00_bg_start_color_rect0, usStartColor);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_1C, iAddrOff, reg_00_bg_end_color_rect0, usEndColor);
}

VOID Hv_Cal_OsdRect_SetBackgroundGradientEnable(BOOL bEnableGradient)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_00, iAddrOff, reg_00_gradient_enable_rect0, bEnableGradient);
}

VOID Hv_Cal_OsdRect_SetBackgroundGradientType(OsdGradientType enType)
{
    HV_ASSERT_TRUE_VOID(enType < OSD_GRADIENT_MAX);

    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_14, iAddrOff, reg_00_gradient_type_rect0, enType);
}

VOID Hv_Cal_OsdRect_SetBackgroundGradientStep(USHORT16 usStepR, USHORT16 usStepG, USHORT16 usStepB)
{
    INT32 iAddrOff = Hv_Cal_OsdRect_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_18, iAddrOff, reg_00_gradient_step_factor_r_rect0, usStepR);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_18, iAddrOff, reg_00_gradient_step_factor_g_rect0, usStepG);
    HV_W32_FIELD_EX(OSD_KV_WIN_P4_00_18, iAddrOff, reg_00_gradient_step_factor_b_rect0, usStepB);
}
