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

VOID Hv_Cal_OsdDDR_WriteSetEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_enable, bEnable);
}

OsdPixelFormat Hv_Cal_OsdDDR_WriteGetPixelFormat(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_KOSD_TOP_3C, regs_wdma_format);
}

VOID Hv_Cal_OsdDDR_WriteSetPixelFormat(OsdPixelFormat enFormat)
{
    UCHAR8 ucBits = 0;

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_3C, regs_wdma_format, enFormat);

    ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);
    HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_08, reg_osd_wr_pack_len, ucBits);
}

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

    HV_W32(DISP_TOP_DPU_WVDM_03_18, uiAddr);
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_start_addr_sw_enable, 1);
}

VOID Hv_Cal_OsdDDR_WriteSetSize(USHORT16 usWidth, USHORT16 usHeight, UCHAR8 ucBurstLen)
{
    UINT32 uiRowBits = 0;
    OsdPixelFormat enFormat = Hv_Cal_OsdDDR_WriteGetPixelFormat();
    UCHAR8 ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);
    UCHAR8 ucAlignedBytes = 16;

    HV_ASSERT_TRUE_VOID(usWidth != 0 && usHeight != 0);
    HV_ASSERT_TRUE_VOID(ucBurstLen > 0);

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

    uiRowBits = (UINT32)usWidth * ucBits;

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

    Hv_Cal_OsdOuterWDMA_SetEnable(OSD_DATAPATH_DDRWRITE, 1);
    Hv_Cal_OsdOuterWDMA_SetBufferDepth(OSD_DATAPATH_DDRWRITE, DMA_MAX_BUFFER_DEPTH);
    Hv_Cal_OsdOuterWDMA_SetAccessMode(OSD_DATAPATH_DDRWRITE, OSD_DMA_MODE_BLOCK);
    Hv_Cal_OsdOuterWDMA_SetOutstandingReq(OSD_DATAPATH_DDRWRITE, 1);

    Hv_Cal_OsdOuterWDMA_SetDataBlock(OSD_DATAPATH_DDRWRITE, uiRowBits / 8, ucBurstLen);

    Hv_Cal_OsdOuterWDMA_SetColStep(OSD_DATAPATH_DDRWRITE, roundup(uiRowBits / 8, ucAlignedBytes));
    Hv_Cal_OsdOuterWDMA_SetColDirection(OSD_DATAPATH_DDRWRITE, OSD_DMA_DIRECTION_FORWARD);
    Hv_Cal_OsdOuterWDMA_SetLineStep(OSD_DATAPATH_DDRWRITE, 0);
    Hv_Cal_OsdOuterWDMA_SetLineDirection(OSD_DATAPATH_DDRWRITE, OSD_DMA_DIRECTION_FORWARD);

    Hv_Cal_OsdOuterWDMA_SetColNumber(OSD_DATAPATH_DDRWRITE, usHeight);
    Hv_Cal_OsdOuterWDMA_SetLineNumber(OSD_DATAPATH_DDRWRITE, 1);

    Hv_Cal_OsdOuterWDMA_SetPackFormat(OSD_DATAPATH_DDRWRITE, enFormat);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_db_en, 1);
}

VOID Hv_Cal_OsdDDR_WriteSetColStep(USHORT16 usStep)
{
    if (0 == usStep)
    {
        return;
    }

    HV_ASSERT_TRUE_VOID((usStep & 0x0f) == 0);

    Hv_Cal_OsdOuterWDMA_SetColStep(OSD_DATAPATH_DDRWRITE, usStep);
}

VOID Hv_Cal_OsdDDR_WriteSetColorKey(UINT32 uiColorKey)
{
    OsdPixelFormat enFormat = Hv_Cal_OsdDDR_WriteGetPixelFormat();
    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_70, regs_wdma_color_key, uiTemp);
}

OsdPixelFormat Hv_Cal_OsdDDR_ReadGetPixelFormat(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_AC, regs_rdma_pixel_format);
}

VOID Hv_Cal_OsdDDR_ReadSetPixelFormat(OsdPixelFormat enFormat, UCHAR8 ucAlpha, UINT32 uiColor)
{
    UINT32 regVal = 0;

    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_AC, regs_rdma_pixel_format, enFormat);

    switch (enFormat)
    {
        case OSD_PIXEL_FORMAT_RGB565:
        case OSD_PIXEL_FORMAT_RGB888:
        {
            HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_B0, regs_rdma_alpha, ucAlpha);
            break;
        }
        case OSD_PIXEL_FORMAT_Alpha8:
        case OSD_PIXEL_FORMAT_Alpha4:
        {
            regVal = HV_R32(DISP_TOP_SUB_OSD_TOP_B0);
            disp_top_sub_osd_top_b0(regVal)->regs_rdma_r = OSD_R(uiColor);
            disp_top_sub_osd_top_b0(regVal)->regs_rdma_g = OSD_G(uiColor);
            disp_top_sub_osd_top_b0(regVal)->regs_rdma_b = OSD_B(uiColor);
            HV_W32(DISP_TOP_SUB_OSD_TOP_B0, regVal);
            break;
        }
        default:
        {
            break;
        }
    }
}

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

    HV_W32(DISP_TOP_DPU_RVDM_04_48, uiAddr);
    HV_W32_FIELD(DISP_TOP_DPU_RVDM_04_44, reg_04_dm_start_addr_sw_enable, 1);
}

VOID Hv_Cal_OsdDDR_ReadSetEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_B8, regs_rdma_en, bEnable);
}

BOOL Hv_Cal_OsdDDR_ReadGetEnable(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_B8, regs_rdma_en);
}

VOID Hv_Cal_OsdDDR_ReadSetSize(USHORT16 usWidth, USHORT16 usHeight, UCHAR8 ucBurstLen)
{
    UINT32 uiRowBits = 0;
    OsdPixelFormat enFormat = Hv_Cal_OsdDDR_ReadGetPixelFormat();
    UCHAR8 ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);
    UCHAR8 ucAlignedBytes = 16;

    HV_ASSERT_TRUE_VOID(usWidth != 0 && usHeight != 0);
    HV_ASSERT_TRUE_VOID(ucBurstLen > 0);

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

    uiRowBits = (UINT32)usWidth * ucBits;

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

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

    Hv_Cal_OsdOuterRDMA_SetDataBlock(OSD_DATAPATH_DDRREAD, uiRowBits / 8, ucBurstLen);

    Hv_Cal_OsdOuterRDMA_SetColStep(OSD_DATAPATH_DDRREAD, roundup(uiRowBits / 8, ucAlignedBytes));
    Hv_Cal_OsdOuterRDMA_SetColDirection(OSD_DATAPATH_DDRREAD, OSD_DMA_DIRECTION_FORWARD);
    Hv_Cal_OsdOuterRDMA_SetLineStep(OSD_DATAPATH_DDRREAD, 0);
    Hv_Cal_OsdOuterRDMA_SetLineDirection(OSD_DATAPATH_DDRREAD, OSD_DMA_DIRECTION_FORWARD);

    Hv_Cal_OsdOuterRDMA_SetColNumber(OSD_DATAPATH_DDRREAD, usHeight);
    Hv_Cal_OsdOuterRDMA_SetLineNumber(OSD_DATAPATH_DDRREAD, 1);

    Hv_Cal_OsdOuterRDMA_SetUnpackFormat(OSD_DATAPATH_DDRREAD, enFormat);
    Hv_Cal_OsdOuterRDMA_SetUnpackSize(OSD_DATAPATH_DDRREAD, usWidth, usHeight);
}

VOID Hv_Cal_OsdDDR_ReadSetColStep(USHORT16 usStepBytes)
{
    if (0 == usStepBytes)
    {
        return;
    }

    HV_ASSERT_TRUE_VOID((usStepBytes & 0x0f) == 0);

    Hv_Cal_OsdOuterRDMA_SetColStep(OSD_DATAPATH_DDRREAD, usStepBytes);
}

VOID Hv_Cal_OsdDDR_ReadSetColorKeyEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_B4, regs_rdma_color_key_enable, bEnable);
}

VOID Hv_Cal_OsdDDR_ReadSetColorKey(UINT32 uiColorKey)
{
    OsdPixelFormat enFormat = Hv_Cal_OsdDDR_ReadGetPixelFormat();
    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_SUB_OSD_TOP_B4, regs_rdma_color_key, uiTemp);

}

VOID Hv_Cal_OsdDDR_ReadSetDataPadding(BOOL bPadOne)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_AC, regs_rdma_full_mode, bPadOne);
}

VOID Hv_Cal_OsdDDR_Init(VOID)
{
    Hv_Cal_OsdDDR_ReadSetDataPadding(1);

    Hv_Cal_OsdDDR_WriteSetEnable(0);
#if (HV_PROJECT_CONFIG_OSD_DDRPATH == HV_CONFIG_ON)
    Hv_Cal_OsdDDR_ReadSetEnable(1);
    Hv_Cal_OsdDDR_ReadSetPixelFormat(HV_OSD_CONFIG_DDR_FORMAT, 0, 0);
    Hv_Cal_OsdDDR_WriteSetPixelFormat(HV_OSD_CONFIG_DDR_FORMAT);
#else
    Hv_Cal_OsdDDR_ReadSetEnable(0);
#endif
#if (HV_OSD_CONFIG_COLORKEY == HV_CONFIG_ON)
    Hv_Cal_OsdDDR_ReadSetColorKeyEnable(HV_TRUE);
    Hv_Cal_OsdDDR_ReadSetColorKey(HV_OSD_CONFIG_COLORKEY_VALUE);

    Hv_Cal_OsdDDR_WriteSetColorKey(HV_OSD_CONFIG_COLORKEY_VALUE);
#else
    Hv_Cal_OsdDDR_ReadSetColorKeyEnable(HV_FALSE);
#endif
}
