/**
 * @file hv_cal_OsdGraphic.c
 * @brief Osd Cal Graphic 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"

BOOL Hv_Cal_OsdGraphic_GetEnable(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_KOSD_TOP_14, reg_osd_bmp_en);
}

VOID Hv_Cal_OsdGraphic_SetEnable(BOOL bEnable)
{
    Hv_Cal_OsdOuterRDMA_SetEnable(OSD_DATAPATH_GRAPHIC, bEnable);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_14, reg_osd_bmp_en, bEnable);
}

OsdPixelFormat Hv_Cal_OsdGraphic_GetFormat(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_KOSD_TOP_30, regs_bmp_pixel_format);
}

VOID Hv_Cal_OsdGraphic_SetPatternEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_14, reg_osd_bmp_patt_en, bEnable);
}

VOID Hv_Cal_OsdGraphic_GetRange(OsdArea *pstArea)
{
    HV_R32_DECL_VAR();

    HV_ASSERT_TRUE_VOID(pstArea != NULL);

    pstArea->usX = HV_R32_FIELD(DISP_TOP_KOSD_TOP_14, reg_osd_bmp_hstart);
    pstArea->usY = HV_R32_FIELD(DISP_TOP_KOSD_TOP_18, reg_osd_bmp_vstart);
    pstArea->usWidth = HV_R32_FIELD(DISP_TOP_KOSD_TOP_18, reg_osd_bmp_hend) - pstArea->usX;
    pstArea->usHeight = HV_R32_FIELD(DISP_TOP_KOSD_TOP_1C, reg_osd_bmp_vend) - pstArea->usY;
}

VOID Hv_Cal_OsdGraphic_SetRange(OsdArea *pstArea)
{
    USHORT16 usHEnd = pstArea->usX + pstArea->usWidth;
    USHORT16 usVEnd = pstArea->usY + pstArea->usHeight;

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_14, reg_osd_bmp_hstart, pstArea->usX);
    HV_W32(DISP_TOP_KOSD_TOP_18, pstArea->usY << 16 | usHEnd);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_1C, reg_osd_bmp_vend, usVEnd);
}

/**
 * Graphic setting order: setFormat, setRange -> setRDMA
 *
 */
VOID Hv_Cal_OsdGraphic_SetRDMA(USHORT16 usColStep, UCHAR8 ucBurstLen)
{
    OsdArea stArea;
    UINT32 uiRowBits = 0;
    OsdPixelFormat enFormat = Hv_Cal_OsdGraphic_GetFormat();
    UCHAR8 ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);
    UCHAR8 ucAlignedBytes = 16;

    if (OSD_PIXEL_FORMAT_RGB888 == enFormat)
    {
        ucAlignedBytes = 48;
    }

    Hv_Cal_OsdGraphic_GetRange(&stArea);

    HV_ASSERT_TRUE_VOID(stArea.usWidth != 0 && stArea.usHeight != 0);

    uiRowBits = stArea.usWidth * ucBits;

    /* pack/unpack requires more than 64 bytes */
    if (uiRowBits < (4 * AXI_BIT_WIDTH))
    {
        stArea.usWidth = stArea.usWidth * stArea.usHeight;
        stArea.usHeight = 1;
        uiRowBits = stArea.usWidth * ucBits;
    }

    Hv_Cal_OsdOuterRDMA_SetEnable(OSD_DATAPATH_GRAPHIC, 1);
    Hv_Cal_OsdOuterRDMA_SetBufferDepth(OSD_DATAPATH_GRAPHIC, DMA_MAX_BUFFER_DEPTH);
    Hv_Cal_OsdOuterRDMA_SetAccessMode(OSD_DATAPATH_GRAPHIC, OSD_DMA_MODE_BLOCK);
    Hv_Cal_OsdOuterRDMA_SetOutstandingReq(OSD_DATAPATH_GRAPHIC, 1);

    Hv_Cal_OsdOuterRDMA_SetDataBlock(OSD_DATAPATH_GRAPHIC, uiRowBits / 8, ucBurstLen);

    Hv_Cal_OsdOuterRDMA_SetColStep(OSD_DATAPATH_GRAPHIC,
            usColStep ? usColStep : roundup(uiRowBits / 8, ucAlignedBytes));
    Hv_Cal_OsdOuterRDMA_SetColDirection(OSD_DATAPATH_GRAPHIC, OSD_DMA_DIRECTION_FORWARD);
    Hv_Cal_OsdOuterRDMA_SetLineStep(OSD_DATAPATH_GRAPHIC, 0);
    Hv_Cal_OsdOuterRDMA_SetLineDirection(OSD_DATAPATH_GRAPHIC, OSD_DMA_DIRECTION_FORWARD);

    Hv_Cal_OsdOuterRDMA_SetColNumber(OSD_DATAPATH_GRAPHIC, stArea.usHeight);
    Hv_Cal_OsdOuterRDMA_SetLineNumber(OSD_DATAPATH_GRAPHIC, 1);

    Hv_Cal_OsdOuterRDMA_SetUnpackFormat(OSD_DATAPATH_GRAPHIC, enFormat);
    Hv_Cal_OsdOuterRDMA_SetUnpackSize(OSD_DATAPATH_GRAPHIC, stArea.usWidth, stArea.usHeight);
}

VOID Hv_Cal_OsdGraphic_SetDDRAddr(UINT32 uiAddr)
{
    uiAddr &= 0x7fffffff;

    HV_W32(DISP_TOP_DPU_RVDM_02_48, uiAddr);
    HV_W32_FIELD(DISP_TOP_DPU_RVDM_02_44, reg_02_dm_start_addr_sw_enable, 1);
}

/* Must set format before set position */
VOID Hv_Cal_OsdGraphic_SetFormat(OsdPixelFormat enFormat, UCHAR8 ucAlpha, UINT32 uiColor)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_30, regs_bmp_pixel_format, enFormat);
    UINT32 regVal;

    switch (enFormat)
    {
        case OSD_PIXEL_FORMAT_RGB565:
        {
            HV_W32_FIELD(DISP_TOP_KOSD_TOP_34, regs_bmp_alpha, ucAlpha);
            break;
        }
        case OSD_PIXEL_FORMAT_Alpha8:
        {
            regVal = HV_R32(DISP_TOP_KOSD_TOP_34);
            disp_top_kosd_top_34(regVal)->regs_bmp_r = OSD_R(uiColor);
            disp_top_kosd_top_34(regVal)->regs_bmp_g = OSD_G(uiColor);
            disp_top_kosd_top_34(regVal)->regs_bmp_b = OSD_B(uiColor);
            HV_W32(DISP_TOP_KOSD_TOP_34, regVal);
            break;
        }
        case OSD_PIXEL_FORMAT_Alpha4:
        {
            regVal = HV_R32(DISP_TOP_KOSD_TOP_34);
            disp_top_kosd_top_34(regVal)->regs_bmp_r = OSD_R(uiColor);
            disp_top_kosd_top_34(regVal)->regs_bmp_g = OSD_G(uiColor);
            disp_top_kosd_top_34(regVal)->regs_bmp_b = OSD_B(uiColor);
            HV_W32(DISP_TOP_KOSD_TOP_34, regVal);
            break;
        }
        case OSD_PIXEL_FORMAT_RGB888:
        {
            HV_W32_FIELD(DISP_TOP_KOSD_TOP_34, regs_bmp_alpha, ucAlpha);
            break;
        }
        default:
        {
            break;
        }
    }
}

VOID Hv_Cal_OsdGraphic_SetColorKeyEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_38, regs_color_key_enable, bEnable);
}

VOID Hv_Cal_OsdGraphic_SetColorKey(UINT32 uiColorKey)
{
    OsdPixelFormat enFormat = Hv_Cal_OsdGraphic_GetFormat();
    UINT32 uiTemp = 0;

    switch (enFormat)
    {
        case OSD_PIXEL_FORMAT_RGB565:
        {
            uiTemp = Hv_Cal_OsdFrame_PixelFormatConvert(
                    OSD_PIXEL_FORMAT_RGB565, OSD_PIXEL_FORMAT_RGB888, uiColorKey);
            uiTemp = OSD_R(uiTemp) << 16 | OSD_G(uiTemp) << 8 | OSD_B(uiTemp);
            break;
        }
        case OSD_PIXEL_FORMAT_RGBA8888:
        {
            uiTemp = OSD_R(uiColorKey) << 16 | OSD_G(uiColorKey) << 8 | OSD_B(uiColorKey);
            break;
        }
        case OSD_PIXEL_FORMAT_RGB888:
        {
            uiTemp = OSD_R(uiColorKey) << 16 | OSD_G(uiColorKey) << 8 | OSD_B(uiColorKey);
            break;
        }
        case OSD_PIXEL_FORMAT_RGBA4444:
        {
            uiTemp = Hv_Cal_OsdFrame_PixelFormatConvert(
                    OSD_PIXEL_FORMAT_RGBA4444, OSD_PIXEL_FORMAT_RGB888, uiColorKey);
            uiTemp = OSD_R(uiTemp) << 16 | OSD_G(uiTemp) << 8 | OSD_B(uiTemp);
            break;
        }
        default:
        {
            break;
        }

        HV_W32_FIELD(DISP_TOP_KOSD_TOP_38, regs_color_key, uiTemp);
    }

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_38, regs_color_key, uiTemp);
}

VOID Hv_Cal_OsdGraphic_SetDataPadding(BOOL bPadOne)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_30, reg_osd_bmp_full_mode, bPadOne);
}

VOID Hv_Cal_OsdGraphic_Init(VOID)
{
    Hv_Cal_OsdGraphic_SetDataPadding(1);

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_00, osd_bmp_bld0_en, 1);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_00, osd_bmp_bld1_en, 0);

#if (HV_OSD_CONFIG_COLORKEY == HV_CONFIG_ON)
    Hv_Cal_OsdGraphic_SetColorKeyEnable(HV_TRUE);
    Hv_Cal_OsdGraphic_SetColorKey(HV_OSD_CONFIG_COLORKEY_VALUE);
#else
    Hv_Cal_OsdGraphic_SetColorKeyEnable(HV_FALSE);
#endif

    Hv_Cal_OsdGraphic_SetEnable(0);
}
