/**
 * @file hv_cal_OsdWindow.c
 * @brief Osd Cal window 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 OsdWindowPhyId s_enCurrentWinIndex = 0;

static UINT32 Hv_Cal_OsdWindow_GetAddrOffset(VOID)
{
    return s_enCurrentWinIndex * OSD_WIN_SIZE;
}

UINT32 Hv_Cal_OsdWindow_GetBaseAddr(OsdWindowPhyId enIndex)
{
    return OSD_NORMAL_WIN_BASE_ADDR + enIndex * OSD_WIN_SIZE;
}

VOID Hv_Cal_OsdWindow_SetCurrentWindow(OsdWindowPhyId enIndex)
{
    s_enCurrentWinIndex = enIndex;
}

OsdWindowPhyId Hv_Cal_OsdWindow_GetCurrentWindow(VOID)
{
    return s_enCurrentWinIndex;
}

VOID Hv_Cal_OsdWindow_SetEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = 0;

    uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_win_timing_enable, bEnable);
}

BOOL Hv_Cal_OsdWindow_GetEnable(VOID)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    return HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_win_timing_enable);
}

VOID Hv_Cal_OsdWindow_SetPos(USHORT16 usX, USHORT16 usY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_04, uiAddrOff, reg_00_win_stax, usX);
    /* coordinate to screen (0, 0) */
    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_04, uiAddrOff, reg_00_win_stay, usY + 1);
}

VOID Hv_Cal_OsdWindow_GetPos(USHORT16 *pusX, USHORT16 *pusY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    *pusX = HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_04, uiAddrOff, reg_00_win_stax);
    *pusY = HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_04, uiAddrOff, reg_00_win_stay);
    *pusY = (*pusY > 0) ? (*pusY - 1) : 0;
}

VOID Hv_Cal_OsdWindow_SetSize(USHORT16 usWidth, USHORT16 usHeight)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

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

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_08, uiAddrOff, reg_00_win_sizex, usWidth);
    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_08, uiAddrOff, reg_00_win_sizey, usHeight);
}

VOID Hv_Cal_OsdWindow_GetSize(USHORT16 *pusWidth, USHORT16 *pusHeight)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    *pusWidth = HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_08, uiAddrOff, reg_00_win_sizex);
    /* IP actually draws one line more than height set */
    *pusHeight = HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_08, uiAddrOff, reg_00_win_sizey) + 1;
}

VOID Hv_Cal_OsdWindow_SetBorderEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_14, uiAddrOff, reg_00_win_bd_ctrl, bEnable);
}

BOOL Hv_Cal_OsdWindow_GetBorderEnable(VOID)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    return HV_R32_FIELD_EX(OSD_KV_WIN_P6_00_14, uiAddrOff, reg_00_win_bd_ctrl);
}

VOID Hv_Cal_OsdWindow_SetBorderColor(UINT32 uiColor)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_14, uiAddrOff, reg_00_win_bd_r, OSD_R(uiColor));
    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_14, uiAddrOff, reg_00_win_bd_g, OSD_G(uiColor));
    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_14, uiAddrOff, reg_00_win_bd_b, OSD_B(uiColor));
}

VOID Hv_Cal_OsdWindow_SetFontEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_osd_en, bEnable);
}

BOOL Hv_Cal_OsdWindow_GetFontEnable(VOID)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    return HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_osd_en);
}

VOID Hv_Cal_OsdWindow_SetFontStart(USHORT16 usX, USHORT16 usY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_font_stax, usX);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_font_stay, usY);
}

VOID Hv_Cal_OsdWindow_GetFontStart(USHORT16 *pusX, USHORT16 *pusY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    *pusX = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_font_stax);
    *pusY = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_font_stay);
}

VOID Hv_Cal_OsdWindow_SetFontTimingDelayEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_delay_en, bEnable);
}

VOID Hv_Cal_OsdWindow_SetFontTimingXDelay(BOOL bXDelaySel, USHORT16 usXAllDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_2C, uiAddrOff, reg_00_x_delay_sel, bXDelaySel);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_2C, uiAddrOff, reg_00_x_all_delay, usXAllDelay);
}

VOID Hv_Cal_OsdWindow_SetFontTimingYDelay(USHORT16 usYAllDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_2C, uiAddrOff, reg_00_y_all_delay, usYAllDelay);
}

VOID Hv_Cal_OsdWindow_SetFontXDelay(BOOL bXDelaySel, USHORT16 usXDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_30, uiAddrOff, reg_00_font_x_dly_sel, bXDelaySel);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_30, uiAddrOff, reg_00_font_x_dly, usXDelay);
}

VOID Hv_Cal_OsdWindow_SetFontYDelay(BOOL bYDelaySel, USHORT16 usYDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_30, uiAddrOff, reg_00_font_y_dly_sel, bYDelaySel);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_30, uiAddrOff, reg_00_font_y_dly, usYDelay);
}

VOID Hv_Cal_OsdWindow_SetFontVsDelay(UCHAR8 ucDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_08, uiAddrOff, reg_00_win_ydly_font, ucDelay);
}

VOID Hv_Cal_OsdWindow_SetFontExtentionEnable(OsdResourceSize enSize, UCHAR8 ucBit, BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    UINT32 uiValue = 0;
    HV_R32_DECL_VAR();

    switch (enSize)
    {
        case OSD_RESOURCE_SIZE_12X12:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            if (bEnable)
            {
                uiValue |= 1 << ((ucBit / 2) * 4);
            }
            else
            {
                uiValue &= ~(1 << ((ucBit / 2) * 4));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_12X14:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            if (bEnable)
            {
                uiValue |= 2 << ((ucBit / 2) * 4);
            }
            else
            {
                uiValue &= ~(2 << ((ucBit / 2) * 4));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_12X16:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            if (bEnable)
            {
                uiValue |= 4 << ((ucBit / 2) * 4);
            }
            else
            {
                uiValue &= ~(4 << ((ucBit / 2) * 4));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_12X18:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            if (bEnable)
            {
                uiValue |= 8 << ((ucBit / 2) * 4);
            }
            else
            {
                uiValue &= ~(8 << ((ucBit / 2) * 4));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_20X20:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            if (bEnable)
            {
                uiValue |= 1 << ((ucBit / 2) * 3);
            }
            else
            {
                uiValue &= ~(1 << ((ucBit / 2) * 3));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_20X24:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            if (bEnable)
            {
                uiValue |= 2 << ((ucBit / 2) * 3);
            }
            else
            {
                uiValue &= ~(2 << ((ucBit / 2) * 3));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_20X28:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            if (bEnable)
            {
                uiValue |= 4 << ((ucBit / 2) * 3);
            }
            else
            {
                uiValue &= ~(4 << ((ucBit / 2) * 3));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_24X24:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00);
            if (bEnable)
            {
                uiValue |= 1 << ((ucBit / 2) * 2);
            }
            else
            {
                uiValue &= ~(1 << ((ucBit / 2) * 2));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00, uiValue);
            break;
        }
        case OSD_RESOURCE_SIZE_24X30:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00);
            if (bEnable)
            {
                uiValue |= 2 << ((ucBit / 2) * 2);
            }
            else
            {
                uiValue &= ~(2 << ((ucBit / 2) * 2));
            }
            HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00, uiValue);
            break;
        }
        default:
        {
            return;
        }
    }
}

BOOL Hv_Cal_OsdWindow_GetFontExtentionEnable(OsdResourceSize enSize, UCHAR8 ucBit)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    UINT32 uiValue = 0;
    HV_R32_DECL_VAR();

    switch (enSize)
    {
        case OSD_RESOURCE_SIZE_12X12:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            return (uiValue & (1 << ((ucBit / 2) * 4))) != 0;
        }
        case OSD_RESOURCE_SIZE_12X14:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            return (uiValue & (2 << ((ucBit / 2) * 4))) != 0;
        }
        case OSD_RESOURCE_SIZE_12X16:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            return (uiValue & (4 << ((ucBit / 2) * 4))) != 0;
        }
        case OSD_RESOURCE_SIZE_12X18:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00);
            return (uiValue & (8 << ((ucBit / 2) * 4))) != 0;
        }
        case OSD_RESOURCE_SIZE_20X20:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            return (uiValue & (1 << ((ucBit / 2) * 3))) != 0;
        }
        case OSD_RESOURCE_SIZE_20X24:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            return (uiValue & (2 << ((ucBit / 2) * 3))) != 0;
        }
        case OSD_RESOURCE_SIZE_20X28:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00);
            return (uiValue & (4 << ((ucBit / 2) * 3))) != 0;
        }
        case OSD_RESOURCE_SIZE_24X24:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00);
            return (uiValue & (1 << ((ucBit / 2) * 2))) != 0;
        }
        case OSD_RESOURCE_SIZE_24X30:
        {
            uiValue = HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00);
            return (uiValue & (2 << ((ucBit / 2) * 2))) != 0;
        }
        default:
        {
            return HV_FALSE;
        }
    }
}

VOID Hv_Cal_OsdWindow_ClearAllFontExtention(VOID)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_12_16_reg_00, 0);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_20_32_reg_00, 0);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_04, uiAddrOff, font_24_32_reg_00, 0);
}

VOID Hv_Cal_OsdWindow_SetFontHsStartEdge(OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    if (OSD_CLOCK_FALLING == enType)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_hs_edg_sel, 0);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_hs_edg_sel, 1);
    }
}

VOID Hv_Cal_OsdWindow_SetFontVsStartEdge(OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    if (OSD_CLOCK_FALLING == enType)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_vs_edg_sel, 0);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_0C, uiAddrOff, reg_00_vs_edg_sel, 1);
    }
}

VOID Hv_Cal_OsdWindow_SetFontSwHsEdge(OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    if (OSD_CLOCK_FALLING == enType)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_sw_hs_sel, 0);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_sw_hs_sel, 1);
    }
}

VOID Hv_Cal_OsdWindow_SetFontSwVsEdge(OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    if (OSD_CLOCK_FALLING == enType)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_sw_vs_sel, 0);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_sw_vs_sel, 1);
    }
}

VOID Hv_Cal_OsdWindow_SetFontSwVrefSel(BOOL bUseOsdVref)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_18, uiAddrOff, reg_00_sw_vref_sel, bUseOsdVref);
}

VOID Hv_Cal_OsdWindow_SetFontBmpSameLineEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_B8, uiAddrOff, reg_00_font_bmp_same_line, bEnable);
}

BOOL Hv_Cal_OsdWindow_GetFontBmpSameLineEnable(VOID)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    HV_R32_DECL_VAR();

    return HV_R32_FIELD_EX(OSD_KV_WIN_P0_00_B8, uiAddrOff, reg_00_font_bmp_same_line);
}

VOID Hv_Cal_OsdWindow_SetFontNewPathEnable(BOOL bEnable)
{
    if (bEnable)
    {
        HV_W32_FIELD(OSD_KV_TOP_CTRL_2C, index_buffer_delay, 1);
        HV_W32_FIELD(OSD_KV_TOP_CTRL_30, resource_buffer_delay, 1);
        HV_W32_FIELD(OSD_KV_WIN_P0_00_B8, reg_00_font_rd_sel, 0);
        HV_W32_FIELD(OSD_KV_WIN_P0_01_B8, reg_01_font_rd_sel, 0);
        HV_W32_FIELD(OSD_KV_WIN_P0_02_B8, reg_02_font_rd_sel, 0);
        HV_W32_FIELD(OSD_KV_WIN_P0_03_B8, reg_03_font_rd_sel, 0);
    }
    else
    {
        HV_W32_FIELD(OSD_KV_TOP_CTRL_2C, index_buffer_delay, 0);
        HV_W32_FIELD(OSD_KV_TOP_CTRL_30, resource_buffer_delay, 0);
        HV_W32_FIELD(OSD_KV_WIN_P0_00_B8, reg_00_font_rd_sel, 1);
        HV_W32_FIELD(OSD_KV_WIN_P0_01_B8, reg_01_font_rd_sel, 1);
        HV_W32_FIELD(OSD_KV_WIN_P0_02_B8, reg_02_font_rd_sel, 1);
        HV_W32_FIELD(OSD_KV_WIN_P0_03_B8, reg_03_font_rd_sel, 1);
    }
}

VOID Hv_Cal_OsdWindow_SetUserDefinedFont(OsdResourceType enType, UCHAR8 ucWidth, UCHAR8 ucHeight)
{
    UCHAR8 fontType = 0;
    USHORT16 usPixels = (USHORT16)ucWidth * ucHeight;
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_ASSERT_TRUE_VOID((ucWidth % 4 == 0) && (usPixels % 8) == 0);

    switch (enType)
    {
        case OSD_RESOURCE_TYPE_1BIT:
        {
            fontType = 1;
            break;
        }
        case OSD_RESOURCE_TYPE_2BIT:
        {
            fontType = 2;
            break;
        }
        case OSD_RESOURCE_TYPE_4BIT:
        {
            fontType = 4;
            break;
        }
        case OSD_RESOURCE_TYPE_6BIT:
        {
            fontType = 6;
            break;
        }
        case OSD_RESOURCE_TYPE_8BIT:
        {
            fontType = 8;
            break;
        }
        default:
        {
            return;
        }
    }

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_h_addr_reg_00, (ucWidth * fontType) / 4);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_00, uiAddrOff, font_v_addr_reg_00, (usPixels * fontType) / 8);

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_font_h_size, (ucWidth - 1));
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_font_v_size, (ucHeight - 1));
}

VOID Hv_Cal_OsdWindow_SetResource(UCHAR8 ucIndex, USHORT16 usResourceOffset, OsdResourceSize enSize)
{
    BOOL bIsLow = (ucIndex % 2 == 0);
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    uiAddrOff += (ucIndex / 2) * 4;
    if (bIsLow)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_A8, uiAddrOff,
                reg_00_font_type_0_baseaddr, usResourceOffset >> 4);
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_A8, uiAddrOff,
                reg_00_font_type_0_select, enSize);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_A8, uiAddrOff,
                reg_00_font_type_1_baseaddr, usResourceOffset >> 4);
        HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_A8, uiAddrOff,
                reg_00_font_type_1_select, enSize);
    }
}

static VOID Hv_Cal_OsdWindow_SetRamDelay(UCHAR8 ucDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_ram_delay_num, ucDelay);
}

VOID Hv_Cal_OsdWindow_SetRowIndexAddr(USHORT16 usOffset)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    OSD_DRV_LOG_DEBUG("set rowIndex offset: 0x%x", usOffset);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_08, uiAddrOff, reg_00_vrm_ofs, usOffset >> 4);
}

VOID Hv_Cal_OsdWindow_SetRowCount(USHORT16 usRowCount)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    OSD_DRV_LOG_DEBUG("set rowCount: %u", usRowCount);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_08, uiAddrOff, reg_00_vrm_lg, (usRowCount + 3) >> 2);
}

static VOID Hv_Cal_OsdWindow_SetWinHsStartEdge(OsdWinClockType enClock, OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    UCHAR8 ucValue = 0;

    switch (enClock)
    {
        case OSD_WIN_HS_CLOCK:
        {
            if (OSD_CLOCK_FALLING == enType)
            {
                ucValue = 0x1;
            }
            else
            {
                ucValue = 0x0;
            }
            break;
        }
        case OSD_WIN_DE_CLOCK:
        {
            if (OSD_CLOCK_FALLING == enType)
            {
                ucValue = 0x3;
            }
            else
            {
                ucValue = 0x2;
            }
            break;
        }
        default:
        {
            return;
        }
    }

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_hs_select, ucValue);
}

static VOID Hv_Cal_OsdWindow_SetWinVsStartEdge(OsdClockType enType)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    if (OSD_CLOCK_FALLING == enType)
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_vs_select, 1);
    }
    else
    {
        HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_vs_select, 0);
    }
}

static VOID Hv_Cal_OsdWindow_SetWinHsDelay(UCHAR8 ucDelay)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_00, uiAddrOff, reg_00_win_hs_dly, ucDelay);
}

VOID Hv_Cal_OsdWindow_SetRectGroupEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_10, uiAddrOff, reg_00_disable_sw, bEnable);
}

VOID Hv_Cal_OsdWindow_SetRectGroupAlpha(UCHAR8 ucAlpha)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_10, uiAddrOff, reg_00_rect_alpha, ucAlpha);
}

VOID Hv_Cal_OsdWindow_SetRectGroupBGEnable(BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_10, uiAddrOff, reg_00_bg_output_enable_line, bEnable);
}

VOID Hv_Cal_OsdWindow_SetRectGroupBGColor(USHORT16 usColor)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P6_00_10, uiAddrOff, reg_00_RGB565_for_background, usColor);
}

VOID Hv_Cal_OsdWindow_SetFontBlinkDuty(OsdBlinkDuty enDuty)
{
    HV_ASSERT_TRUE_VOID(enDuty < OSD_BLINK_DUTY_MAX);

    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_14, uiAddrOff, reg_00_blnk_duty, enDuty);
}

VOID Hv_Cal_OsdWindow_SetFontBlinkRate(UCHAR8 ucRate)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_14, uiAddrOff, reg_00_blnk_rate, ucRate);
}

VOID Hv_Cal_OsdWindow_SetFontTransMode(OsdTransMode enMode)
{
    HV_ASSERT_TRUE_VOID(enMode < OSD_TRANS_MODE_MAX);

    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_10, uiAddrOff, reg_00_trans_mode, enMode);
}

VOID Hv_Cal_OsdWindow_SetFontTransSpeed(UCHAR8 ucSpeed)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_24, uiAddrOff, reg_00_cpu_trans_speed, ucSpeed);
}

VOID Hv_Cal_OsdWindow_SetFontTransFrame(UCHAR8 ucFrame)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_20, uiAddrOff, reg_00_cpu_trans_frame, ucFrame);
}

VOID Hv_Cal_OsdWindow_SetFontTransDirection(OsdTransDirection enDirection)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    UCHAR8 ucValue = 0;

    switch (enDirection)
    {
        case OSD_TRANS_DI_V:
        {
            ucValue = 0;    /* also 1 */
            break;
        }
        case OSD_TRANS_DI_H:
        {
            ucValue = 2;
            break;
        }
        case OSD_TRANS_DI_V_H:
        {
            ucValue = 3;
            break;
        }
        default:
        {
            return;
        }
    }

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_24, uiAddrOff, reg_00_cpu_trans_di, ucValue);
}

VOID Hv_Cal_OsdWindow_SetFontTrans2Direction(OsdTrans2Direction enDirection)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();
    UCHAR8 ucValue = 0;

    switch (enDirection)
    {
        case OSD_TRANS2_DI_V_OUT:
        {
            ucValue = 0;    /* also 1 */
            break;
        }
        case OSD_TRANS2_DI_H_OUT:
        {
            ucValue = 2;
            break;
        }
        case OSD_TRANS2_DI_V_H_OUT:
        {
            ucValue = 3;
            break;
        }
        case OSD_TRANS2_DI_V_IN:
        {
            ucValue = 4;    /* also 5 */
            break;
        }
        case OSD_TRANS2_DI_H_IN:
        {
            ucValue = 6;
            break;
        }
        case OSD_TRANS2_DI_V_H_IN:
        {
            ucValue = 7;
            break;
        }
        default:
        {
            return;
        }
    }

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_24, uiAddrOff, reg_00_cpu_trans_di, ucValue);
}

VOID Hv_Cal_OsdWindow_SetFontTransStartPos(USHORT16 usX, USHORT16 usY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_1C, uiAddrOff, reg_00_cpu_trans_xst, usX);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_1C, uiAddrOff, reg_00_cpup_trans_yst, usY);
}

VOID Hv_Cal_OsdWindow_SetFontTransCen(USHORT16 usX, USHORT16 usY)
{
    UINT32 uiAddrOff = Hv_Cal_OsdWindow_GetAddrOffset();

    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_24, uiAddrOff, reg_00_cpu_trans_xcen, usX);
    HV_W32_FIELD_EX(OSD_KV_WIN_P0_00_24, uiAddrOff, reg_00_cpu_trans_ycen, usY);
}

VOID Hv_Cal_OsdWindow_Init(VOID)
{
    OsdWindowPhyId enWinIndex = PHY_WIN_0;

    /* cal window init */
    for (enWinIndex = PHY_WIN_0; enWinIndex < PHY_WIN_ID_MAX; ++enWinIndex)
    {
        Hv_Cal_OsdWindow_SetCurrentWindow(enWinIndex);
        Hv_Cal_OsdWindow_SetWinHsStartEdge(OSD_WIN_DE_CLOCK, OSD_CLOCK_RISING);
        Hv_Cal_OsdWindow_SetWinVsStartEdge(OSD_CLOCK_RISING);
        Hv_Cal_OsdWindow_SetWinHsDelay(0x3f);
        if (OSD_WINDOW_IS_NORMAL(enWinIndex))
        {
            Hv_Cal_OsdWindow_SetFontYDelay(HV_TRUE, 3);
            Hv_Cal_OsdWindow_SetFontXDelay(HV_FALSE, 0);
            Hv_Cal_OsdWindow_SetFontVsDelay(0);
            Hv_Cal_OsdWindow_SetFontTimingDelayEnable(HV_TRUE);
            Hv_Cal_OsdWindow_SetFontTimingXDelay(HV_FALSE, 0);
            Hv_Cal_OsdWindow_SetFontTimingYDelay(1);
            Hv_Cal_OsdWindow_SetFontSwHsEdge(OSD_CLOCK_RISING);
            Hv_Cal_OsdWindow_SetFontSwVsEdge(OSD_CLOCK_RISING);
            Hv_Cal_OsdWindow_SetFontHsStartEdge(OSD_CLOCK_RISING);
            Hv_Cal_OsdWindow_SetFontVsStartEdge(OSD_CLOCK_RISING);
            Hv_Cal_OsdWindow_SetFontSwVrefSel(HV_TRUE);
            Hv_Cal_OsdWindow_SetFontNewPathEnable(1);
            Hv_Cal_OsdWindow_SetFontEnable(HV_FALSE);
            Hv_Cal_OsdWindow_SetFontBmpSameLineEnable(1);
        }
        Hv_Cal_OsdBlend_SetForegroundAlpha(OSD_BLENDING_STAGE_RECT_GROUP, 255);
        Hv_Cal_OsdBlend_SetRectGroupEnable(HV_TRUE);
        Hv_Cal_OsdWindow_SetEnable(HV_FALSE);
    }
}
