/**
 * @file hv_mw_PQ.c
 * @brief  dpu PQ middleware source file
 * @details This file provides the following functions: \n
 *          (1) dpu operation function \n
 *          (2) init handle \n
 *          (3) Feed functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-25
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                         <th>Date         <th>Change Description
 * <tr><td>Hiview SoC Software Team       <td>2022-08-25   <td>init
 * </table>
*/

#include <string.h>
#include "hv_comm_MemoryConfig.h"
#include "hv_comm_Assert.h"
#include "hv_comm_DataBase.h"

#include "hv_mw_PQ.h"
#include "hv_mw_Channel_Manager.h"
#include "hv_mw_PanelManager.h"
#include "hv_mw_SystemManager.h"
#include "hv_app_Function.h"

#include "hv_drv_DpuMainScaler.h"
#include "hv_drv_DpuMainMute.h"
#include "hv_drv_DpuCommon.h"
#include "hv_drv_PLL.h"
#include "hv_drv_DpuCommon.h"
#include "hv_drv_Mprt.h"
#include "hv_drv_PQ.h"
#include "hv_drv_Od.h"
#include "hv_drv_Gamma.h"
#include "hv_drv_Dither.h"
#include "hv_drv_FramerateDet.h"
#include "hv_drv_Demura.h"

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#include "hv_drv_DpuSubMute.h"
#include "hv_drv_DpuSubScaler.h"
#include "hv_cal_DpuSubScaler.h"
#endif

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_AMBIENT_LIGHT)
#include "hv_drv_Led.h"
#endif


#include "hv_cal_DpuMainScaler.h"
#include "PanelConfig.h"
#include "hv_chip_Debug.h"

/*#if (HV_PROJECT_CONFIG_PQ_INITBYBIN == HV_CONFIG_ON)
static UCHAR8 s_ucInitByBinMacro = HV_CONFIG_ON;
#else
static UCHAR8 s_ucInitByBinMacro = HV_CONFIG_OFF;
#endif

#if (HV_PROJECT_CONFIG_FULL_LOCALDIMMING == HV_CONFIG_ON)
static UCHAR8 s_ucFullLdcMacro = HV_CONFIG_ON;
#else
static UCHAR8 s_ucFullLdcMacro = HV_CONFIG_OFF;
#endif*/

static Status SendNotifyMessageToSystemTask(SettingParamId enParamId, UINT32 uiValue)
{
    SystemEvent stSystemEvent = {0};
    HV_VOS_QUEUE_S *xSystembQueue = Hv_Mw_System_GetSystemQueue();

    HV_ASSERT_VALID_PTR(xSystembQueue);
    stSystemEvent.enEventType = SYSTEM_REV_EVENT_TYPE_OSD_SETTING;
    stSystemEvent.usEventId = enParamId;
    stSystemEvent.uiValue = uiValue;
    HV_ASSERT_TRUE(Hv_Vos_QueueSend(xSystembQueue, (VOID *)&stSystemEvent));

    return HV_SUCCESS;
}

static VOID PQ_SetMacroConfig(VOID)
{
    Hv_Drv_PQSetMacroConfig(HV_PROJECT_CONFIG_FULL_LOCALDIMMING, HV_PROJECT_CONFIG_LDC_2D_PIXELGAIN);
    return;
}

VOID Hv_Mw_PQ_PQBypass(BOOL bBypass)
{
    Hv_Drv_PQPathBypass(bBypass);
    HV_PQ_DATABASE_SET(DiagData, ucDBPqBypassEn, !bBypass);

    return;
}

VOID Hv_Mw_PQ_DpuPQ_CommonRegInit(const UINT32 *puiBaseRegAddr, UINT32 uiLen)
{
    PQ_SetMacroConfig();
    Hv_Drv_DpuPQ_CommonRegInit(puiBaseRegAddr, uiLen);
    return;
}

UCHAR8 Hv_Mw_PQ_GetDynamicBLEn()
{
    return Hv_Drv_PQ_GetDynamicBLEn();
}

VOID Hv_Mw_PQ_DynamicBLEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_DynamicBLEn(ucEn);
    return;
}

Status Hv_Mw_PQ_CMInit(const UINT32 *puiCmAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiCmAddr, HV_FAILURE);
    Hv_Drv_PQ_CMInit(puiCmAddr, uiLen);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_CMLutInit(const UINT32 *puiCmLutAddr, UINT32 *puiCmLutAddr2)
{
    HV_ASSERT_VALID_PTR_RET(puiCmLutAddr, HV_FAILURE);
    Hv_Drv_PQ_CMLutInit(puiCmLutAddr, puiCmLutAddr2);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_CMChangeLut(UINT32 uiLutAddr)
{
    if(uiLutAddr != 0)
    {
        Hv_Drv_PQ_CMChangeLut(uiLutAddr);
    }
    return;
}

VOID Hv_Mw_PQ_CMEnable(BOOL bEn)
{
   return Hv_Drv_PQ_CMEnable(bEn); 
}

VOID Hv_Mw_PQ_CM64SetAll(VOID)
{
    UCHAR8 ucIndex = 0;

    for(ucIndex = 0; ucIndex < 64; ucIndex++)
    {
        Hv_Mw_PQ_CM64AxisSetHue(ucIndex);
        Hv_Mw_PQ_CM64AxisSetSat(ucIndex);
        Hv_Mw_PQ_CM64AxisSetLum(ucIndex);
    }
    
    return;
}

VOID Hv_Mw_PQ_CM64AxisSetHue(UCHAR8 ucIndex)
{
    HV_LOG_INFO(PQ,"CM64 set hue index %d val %d", ucIndex, Hv_Mw_PQ_Cm64AxisGetHue(ucIndex));
    Hv_Drv_PQ_Cm64Axis(CM_SET_HUE, ucIndex, Hv_Mw_PQ_Cm64AxisGetHue(ucIndex));
    return;
}
VOID Hv_Mw_PQ_CM64AxisSetLum(UCHAR8 ucIndex)
{
    HV_LOG_INFO(PQ,"CM64 set lum index %d val %d", ucIndex, Hv_Mw_PQ_Cm64AxisGetLum(ucIndex));
    Hv_Drv_PQ_Cm64Axis(CM_SET_LUM, ucIndex, Hv_Mw_PQ_Cm64AxisGetLum(ucIndex));
    return;
}
VOID Hv_Mw_PQ_CM64AxisSetSat(UCHAR8 ucIndex)
{
    HV_LOG_INFO(PQ,"CM64 set sat index %d val %d", ucIndex, Hv_Mw_PQ_Cm64AxisGetSat(ucIndex));
    Hv_Drv_PQ_Cm64Axis(CM_SET_SAT, ucIndex, Hv_Mw_PQ_Cm64AxisGetSat(ucIndex));
    return;
}

UCHAR8 Hv_Mw_PQ_Cm64AxisGetSat(UCHAR8 ucIndex)
{
    UINT32 uiCM64Addr = 0;
    uiCM64Addr = (UINT32)(Hv_Common_Db_GetDiagDataDBRegionPtr()) + OFFSET_OF(DiagDataDBRegion, ucDBHueAll);
    return HV_R8(uiCM64Addr + 64 + ucIndex);
}

UCHAR8 Hv_Mw_PQ_Cm64AxisGetLum(UCHAR8 ucIndex)
{
    UINT32 uiCM64Addr = 0;
    uiCM64Addr = (UINT32)(Hv_Common_Db_GetDiagDataDBRegionPtr()) + OFFSET_OF(DiagDataDBRegion, ucDBHueAll);
    return HV_R8(uiCM64Addr + 64 * 2 + ucIndex);
}

UCHAR8 Hv_Mw_PQ_Cm64AxisGetHue(UCHAR8 ucIndex)
{
    UINT32 uiCM64Addr = 0;
    uiCM64Addr = (UINT32)(Hv_Common_Db_GetDiagDataDBRegionPtr()) + OFFSET_OF(DiagDataDBRegion, ucDBHueAll);
    return HV_R8(uiCM64Addr + ucIndex);;
}

VOID Hv_Mw_PQ_CMSetHue(CmColorType enCmMod, UCHAR8 ucCmHue)
{
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueR, ucCmHue);
            break;
        }
        case PQ_CM_G:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueG, ucCmHue);
            break;
        }
        case PQ_CM_B:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueB, ucCmHue);
            break;
        }
        case PQ_CM_C:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueC, ucCmHue);
            break;
        }
        case PQ_CM_M:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueM, ucCmHue);
            break;
        }
        case PQ_CM_Y:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBHueY, ucCmHue);
            break;
        }
        default:
        {
            break;
        }

    }
    if (enCmMod < PQ_CM_MAX)
    {
        Hv_Drv_PQ_CMSetHue(enCmMod, ucCmHue);
    }

    return;
}

VOID Hv_Mw_PQ_CMSetSat(CmColorType enCmMod, UCHAR8 ucSat)
{
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatR, ucSat);
            break;
        }
        case PQ_CM_G:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatG, ucSat);
            break;
        }
        case PQ_CM_B:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatB, ucSat);
            break;
        }
        case PQ_CM_C:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatC, ucSat);
            break;
        }
        case PQ_CM_M:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatM, ucSat);
            break;
        }
        case PQ_CM_Y:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBSatY, ucSat);
            break;
        }
        default:
        {
            break;
        }
    }

    if (enCmMod < PQ_CM_MAX)
    {
        Hv_Drv_PQ_CMSetSat(enCmMod, ucSat);
    }

    return;
}

VOID Hv_Mw_PQ_CMSetLum(CmColorType enCmMod, UCHAR8 ucLum)
{
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumR, ucLum);
            break;
        }
        case PQ_CM_G:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumG, ucLum);
            break;
        }
        case PQ_CM_B:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumB, ucLum);
            break;
        }
        case PQ_CM_C:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumC, ucLum);
            break;
        }
        case PQ_CM_M:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumM, ucLum);
            break;
        }
        case PQ_CM_Y:
        {
            HV_PQ_DATABASE_SET(DiagData, ucDBLumY, ucLum);
            break;
        }
        default:
        {
            break;
        }

    }

    if (enCmMod < PQ_CM_MAX)
    {
        Hv_Drv_PQ_CMSetLum(enCmMod, ucLum);
    }

    return;
}

Status Hv_Mw_PQ_GammaInit(const UINT32 *puiGammabin, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiGammabin, HV_FAILURE);
    Hv_Drv_PQ_GammaInit(puiGammabin, uiLen);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_GammaLutInit(const UINT32 *puiGammalut)
{
    HV_ASSERT_VALID_PTR_RET(puiGammalut, HV_FAILURE);
    Hv_Drv_PQ_GammaLutInit(puiGammalut);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_OsdGammaLutInit(const UINT32 *puiOsdGmiAddr, const UINT32 *puiOsdGmdAddr)
{
    HV_ASSERT_VALID_PTR_RET(puiOsdGmiAddr, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiOsdGmdAddr, HV_FAILURE);
    Hv_Drv_PQ_OsdGammaLutInit(puiOsdGmiAddr, puiOsdGmdAddr);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetGamma(UCHAR8 ucGammaIndex)
{
    Hv_Drv_PQ_SetGammaIndex(ucGammaIndex);
    Hv_Drv_PQ_SetOsdGammaIndex(ucGammaIndex);

    return;
}

//VOID Hv_Mw_PQ_GammaEnable(UCHAR8 ucGammaEn)
//{
//    Hv_Drv_PQ_GammaEnable(ucGammaEn);
//
//    return;
//}

Status Hv_Mw_PQ_SetGammaLut(UCHAR8 *pucGamma, USHORT16 usTableSize)
{
    HV_ASSERT_VALID_PTR_RET(pucGamma, HV_FAILURE);
    Hv_Drv_PQ_SetGammaLut(pucGamma, usTableSize);

    return HV_SUCCESS;
}

Status Hv_Mw_PQ_SharpnessInit(const UINT32 *puiSharpnessbin, UINT32 uiLen, const UINT32 *puiSharpnessParam)
{
    HV_ASSERT_VALID_PTR_RET(puiSharpnessbin, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiSharpnessParam, HV_FAILURE);
    Hv_Drv_PQ_SharpnessInit(puiSharpnessbin, uiLen, puiSharpnessParam);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetSharpness(UCHAR8 ucSharpness)
{
    Hv_Drv_PQ_SetSharpness(ucSharpness);
    return;
}

VOID Hv_Mw_PQ_SharpnessEnable(BOOL bEn)
{
    Hv_Drv_PQ_SharpnessEnable(bEn); 
    return;
}

Status Hv_Mw_PQ_GcInit(const UINT32 *puiGcAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiGcAddr, HV_FAILURE);
    Hv_Drv_PQ_GcInit(puiGcAddr, uiLen);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_GcLutInit(const UINT32 *puiGcLutAddr, UINT32 *puiGcLutAddr1)
{
    HV_ASSERT_VALID_PTR_RET(puiGcLutAddr, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiGcLutAddr1, HV_FAILURE);
    Hv_Drv_PQ_GcLutInit(puiGcLutAddr, puiGcLutAddr1);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_GcModeSwitch(UCHAR8 ucGcMode, UCHAR8 ucCurBlkSta)
{
    Hv_Drv_PQ_GcModeSwitch(ucGcMode, ucCurBlkSta); 
    return;
}

VOID Hv_Mw_PQ_GCEnable(BOOL bEn)
{
   Hv_Drv_PQ_GCEnable(bEn); 
    return;
}

VOID Hv_Mw_PQ_GCSetDarkStaDir(UCHAR8 ucDir)
{
    Hv_Drv_PQ_GCSetDarkStaDir(ucDir);
    return;
}

Status Hv_Mw_PQ_HdrInit(const UINT32 *puiHdrAddr1, UCHAR8 ucHdrIdx)
{
    HV_ASSERT_VALID_PTR_RET(puiHdrAddr1, HV_FAILURE);
    Hv_Drv_PQ_HdrInit(puiHdrAddr1, ucHdrIdx);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_LdcInit(const UINT32 *puiLdcAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiLdcAddr, HV_FAILURE);
    Hv_Drv_PQ_LdcInit(puiLdcAddr, uiLen);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_LdcLutInit(const UINT32 *puiLdcLutAddr, UINT32 *puiBlAddr)
{
    HV_ASSERT_VALID_PTR_RET(puiLdcLutAddr, HV_FAILURE);
    Hv_Drv_PQ_LdcLutInit(puiLdcLutAddr, puiBlAddr);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_LdcPwmBlend(UINT32 uiPwm)
{
    HV_LOG_DEBUG(PQ,"LDC blend %u", uiPwm);
    Hv_Drv_PQ_LdcPwmBlend(uiPwm);

    return;
}

Status Hv_Mw_PQ_LdcSetModeLutAddr(const USHORT16 *pusLdcModeLutBaseAddr)
{
    HV_ASSERT_VALID_PTR_RET(pusLdcModeLutBaseAddr, HV_FAILURE);
    Hv_Drv_PQ_LdcSetModeLutAddr(pusLdcModeLutBaseAddr);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_LdcSetMode(UCHAR8 ucLdcModeIndex, USHORT16 usMaxWeightVal)
{
    HV_LOG_DEBUG(PQ,"LDC mode %u", ucLdcModeIndex);
    Hv_Drv_PQ_LdcSetMode(ucLdcModeIndex, usMaxWeightVal);
    
    return;
}

UINT32 Hv_Mw_PQ_LDCGetGlobalAvgBright(VOID)
{
    return Hv_Drv_PQ_LDCGetGlobalAvgBright();
}

UINT32 Hv_Mw_PQ_LDCGetGlobalMaxBright(VOID)
{
    return Hv_Drv_PQ_LDCGetGlobalMaxBright();
}

UCHAR8 Hv_Mw_PQ_GetPicPWM(VOID)
{
    return Hv_Drv_PQ_LdcCalcPWM();
}

VOID Hv_Mw_PQ_SetLdBypass(BOOL bLdBypass)
{
    Hv_Drv_PQ_SetLdBypass(bLdBypass);
    return;
}

VOID Hv_Mw_PQ_SetMaxBl(UCHAR8 ucMaxBl)
{
    Hv_Drv_PQ_SetMaxBl(ucMaxBl);
    return;
}

UINT32 Hv_Mw_PQ_GetLdimBlBufAddr(UCHAR8 ucBlBufId)
{
    return Hv_Drv_PQ_GetLdimBlBufAddr(ucBlBufId);
}

UINT32 Hv_Mw_PQ_GetKspiRdmaAddr(VOID)
{
    UINT32 uiKspiRdmaAddr = 0;
    uiKspiRdmaAddr = Hv_Drv_PQ_GetKspiRdmaAddr();

    return uiKspiRdmaAddr;
}

VOID Hv_Mw_PQ_SetKspiDemoMode(UCHAR8 ucDemoMode)
{
    Hv_Drv_PQ_SetKspiDemoMode(ucDemoMode);
    return;
}

VOID Hv_Mw_PQ_SetKspiDemoData(USHORT16 usDemoData)
{
    Hv_Drv_PQ_SetKspiDemoData(usDemoData);
    return;
}

VOID Hv_Mw_PQ_SetKspiDataLen(USHORT16 usDataLen)
{
    Hv_Drv_PQ_SetKspiDataLen(usDataLen);
    return;
}

Status Hv_Mw_PQ_SetKspiHeader(UCHAR8 ucCh, UCHAR8 ucHeaderNum, USHORT16 *pusHeadrData)
{
    HV_ASSERT_VALID_PTR_RET(pusHeadrData, HV_FAILURE);
    Hv_Drv_PQ_SetKspiHeader(ucCh, ucHeaderNum, pusHeadrData);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_SetKspiTail(UCHAR8 ucCh, UCHAR8 ucTailNum, USHORT16 *pusTailData)
{
    HV_ASSERT_VALID_PTR_RET(pusTailData, HV_FAILURE);
    Hv_Drv_PQ_SetKspiTail(ucCh, ucTailNum, pusTailData);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_KspiHardCrcEn(UCHAR8 ucHardCrcEn)
{
    Hv_Drv_PQ_KspiHardCrcEn(ucHardCrcEn);
    return;
}

VOID Hv_Mw_PQ_KspiSwModeEn(UCHAR8 ucSwModeEn)
{
    Hv_Drv_PQ_KspiSwModeEn(ucSwModeEn);
    return;
}

VOID Hv_Mw_PQ_SetHDREnableFlag(UCHAR8 ucCh, UCHAR8 ucHDREn)
{
    Hv_Drv_PQ_HDREnableFlag(ucCh, ucHDREn);
    return;
}

UCHAR8 Hv_Mw_PQ_GetHDREnable(UCHAR8 ucCh)
{
    return Hv_Drv_PQ_GetHDREnable(ucCh);
}


VOID Hv_Mw_PQ_HDREnable(UCHAR8 ucCh, UCHAR8 ucHDREn)
{
    Hv_Drv_PQ_HDREnable(ucCh, ucHDREn);
    return;
}

VOID Hv_Mw_PQ_HdrSetMappingInit(UCHAR8 ucMapType, UINT32 uiMapLutAddr)
{
    if(uiMapLutAddr != 0)
    {
        Hv_Drv_PQ_HdrToneMappingInit(ucMapType, uiMapLutAddr);
    }
    return;
}

Status Hv_Mw_PQ_SetHdrMode(UCHAR8 ucCh, UCHAR8 ucHdrModel, const HDRParam* pstHdrParam)
{
    HV_ASSERT_VALID_PTR_RET(pstHdrParam, HV_FAILURE);
    if((ucHdrModel == SDR_TYPE)||(ucHdrModel == HDR10_TYPE)||(ucHdrModel == HLG_TYPE))//valid hdr input
    {
        /* Main/Sub Logic */
        Hv_Drv_PQ_SetHdrMode(ucCh, ucHdrModel, (HDRParam*)pstHdrParam);
        return HV_SUCCESS;
    }
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_GetBlkAvg(USHORT16 ucPstX, USHORT16 ucPstY, UCHAR8 *pucRed, UCHAR8 *pucGreen, UCHAR8 *pucBlue)
{
    PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();

    if(ucPstX > stPanelParam.usPanelHactive)
    {
        ucPstX = stPanelParam.usPanelHactive; 
    }
    if(ucPstY > stPanelParam.usPanelVactive)
    {
        ucPstY = stPanelParam.usPanelVactive; 
    }

    return Hv_Drv_PQ_GetBlkAvg(ucPstX, ucPstY, pucRed, pucGreen, pucBlue);
}

Status Hv_Mw_PQ_WcgInit(const UINT32 *puiWcgAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiWcgAddr, HV_FAILURE);
    Hv_Drv_PQ_WcgInit(puiWcgAddr, uiLen);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_WcgEnable(UCHAR8 ucWcgEn)
{
    Hv_Drv_PQ_WcgEnable(ucWcgEn);
    return;
}

Status Hv_Mw_PQ_WcgLutInit(const UINT32 *puiGmiAddr, const UINT32 *puiRgbAddr, const UINT32 *puiGmdAddr)
{
    HV_ASSERT_VALID_PTR_RET(puiGmiAddr, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiRgbAddr, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiGmdAddr, HV_FAILURE);
    Hv_Drv_PQ_WcgLutInit(puiGmiAddr, puiRgbAddr, puiGmdAddr);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_LoadWCGLUT(const UINT32 *puiRgbAddr)
{
    HV_ASSERT_VALID_PTR_RET(puiRgbAddr, HV_FAILURE);
    Hv_Drv_LoadWCGLUT(puiRgbAddr);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetWCGLutEnable(VOID)
{
    Hv_Drv_SetWCGLutEnable();
    return;
}

Status Hv_Mw_PQ_CscInit(const UINT32 *puiCscAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiCscAddr, HV_FAILURE);
    Hv_Drv_PQ_CscInit(puiCscAddr, uiLen);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_CscConfigAddr(const UINT32 *puiMainCscHdb, const UINT32 *puiSubCscHdb)
{
    HV_ASSERT_VALID_PTR_RET(puiMainCscHdb, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(puiSubCscHdb,   HV_FAILURE);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    Hv_Drv_PQ_CscConfigAddr(puiMainCscHdb, puiSubCscHdb);
#else
    Hv_Drv_PQ_CscConfigAddr(puiMainCscHdb, NULL);
#endif
    return HV_SUCCESS;
} 

VOID Hv_Mw_PQ_SetGamutEnable(VOID)
{
    Hv_Drv_SetGamutEnable();
    return;
}

Status Hv_Mw_PQ_SetGamutParam(const GamutSet *psGamut)
{
    HV_ASSERT_VALID_PTR_RET(psGamut, HV_FAILURE);
    Hv_Drv_SetGamutParam(psGamut);
    return HV_SUCCESS;
}

Status Hv_Mw_PQ_SetGamutOffset(const GamutOffset *pstOffset)
{
    HV_ASSERT_VALID_PTR_RET(pstOffset, HV_FAILURE);
    Hv_Drv_PQ_SetGamutOffset(pstOffset);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetGamutNative()
{
    Hv_Drv_PQ_SetGamutNative();
    return;
}

Status Hv_Mw_PQ_SetGamutFac(GamutSet *stGamut)
{
    HV_ASSERT_VALID_PTR_RET(stGamut, HV_FAILURE);
    Hv_Drv_PQ_SetGamutFac(stGamut);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetContrast(UCHAR8 ucCh, UINT32 uiContrast)
{
    Hv_Drv_PQ_SetContrast(ucCh, uiContrast);

    return;
}

VOID Hv_Mw_PQ_SetHue(UCHAR8 ucCh, UCHAR8 ucHue)
{
    Hv_Drv_PQ_SetHue(ucCh, ucHue);

    return;
}

VOID Hv_Mw_PQ_SetRGBGainFac(UCHAR8 ucCh, USHORT16 usRed, USHORT16 usGreen, USHORT16 usBlue)
{
    Hv_Drv_PQ_SetRGBGain(ucCh, usRed, usGreen, usBlue);

    return;
}

VOID Hv_Mw_PQ_SetRGBGain(UCHAR8 ucCh, USHORT16 usRed, USHORT16 usGreen, USHORT16 usBlue)
{
    Hv_Drv_PQ_SetRGBGain(ucCh, usRed, usGreen, usBlue);

    return;
}

VOID Hv_Mw_PQ_SetRGBOffset(UCHAR8 ucCh, USHORT16 usRed, USHORT16 usGreen, USHORT16 usBlue)
{
    Hv_Drv_PQ_SetRGBOffset(ucCh, usRed, usGreen, usBlue);

    return; 
}

UCHAR8 Hv_Mw_PQ_GetContrastDB(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, uiDBContrast);
}

UCHAR8 Hv_Mw_PQ_GetSaturation(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, ucDBSaturation);
}

UCHAR8 Hv_Mw_PQ_GetHue(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, ucDBHue);
}

UCHAR8 Hv_Mw_PQ_GetRGain(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, usDBRGain);
}

UCHAR8 Hv_Mw_PQ_GetGGain(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, usDBGGain);
}

UCHAR8 Hv_Mw_PQ_GetBGain(VOID)
{
    return HV_PQ_DATABASE_GET(DiagData, usDBBGain);
}

UCHAR8 Hv_Mw_PQ_CMGetHue(CmColorType enCmMod)
{
    UCHAR8 ucCmHue = 0;
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            /* Red */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueR);
            break;
        }
        case PQ_CM_G:
        {
            /* Green */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueG);
            break;
        }
        case PQ_CM_B:
        {
            /* Blue */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueB);
            break;
        }
        case PQ_CM_C:
        {
            /* Cyan */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueC);
            break;
        }
        case PQ_CM_M:
        {
            /* Magenta */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueM);
            break;
        }
        case PQ_CM_Y:
        {
            /* Yellow */
            ucCmHue = HV_PQ_DATABASE_GET(DiagData, ucDBHueY);
            break;
        }
        default:
        {
            break;
        }

    }

    return ucCmHue;
}

UCHAR8 Hv_Mw_PQ_CMGetSat(CmColorType enCmMod)
{
    UCHAR8 ucCmSat = 0;
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            /* Red */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatR);
            break;
        }
        case PQ_CM_G:
        {
            /* Green */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatG);
            break;
        }
        case PQ_CM_B:
        {
            /* Blue */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatB);
            break;
        }
        case PQ_CM_C:
        {
            /* Cyan */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatC);
            break;
        }
        case PQ_CM_M:
        {
            /* Magenta */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatM);
            break;
        }
        case PQ_CM_Y:
        {
            /* Yellow */
            ucCmSat = HV_PQ_DATABASE_GET(DiagData, ucDBSatY);
            break;
        }
        default:
        {
            break;
        }

    }

    return ucCmSat;
}

UCHAR8 Hv_Mw_PQ_CMGetLum(CmColorType enCmMod)
{
    UCHAR8 ucCmLum = 0;
    /* only use in PQtool, switch-case is ok */
    switch(enCmMod)
    {
        case PQ_CM_R:
        {
            /* Red */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumR);
            break;
        }
        case PQ_CM_G:
        {
            /* Green */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumG);
            break;
        }
        case PQ_CM_B:
        {
            /* Blue */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumB);
            break;
        }
        case PQ_CM_C:
        {
            /* Cyan */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumC);
            break;
        }
        case PQ_CM_M:
        {
            /* Magenta */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumM);
            break;
        }
        case PQ_CM_Y:
        {
            /* Yellow */
            ucCmLum = HV_PQ_DATABASE_GET(DiagData, ucDBLumY);
            break;
        }
        default:
        {
            break;
        }

    }

    return ucCmLum;
}


//AKA Brightness
VOID Hv_Mw_PQ_SetBlackLevel(UCHAR8 ucCh, USHORT16 usBlackLevel)
{
    Hv_Drv_PQ_SetBlackLevel(ucCh, usBlackLevel);

    return;
}

VOID Hv_Mw_PQ_SetSaturation(UCHAR8 ucCh, UCHAR8 ucSaturation)
{
    Hv_Drv_PQ_SetSaturation(ucCh, ucSaturation);

    return;
}

VOID Hv_Mw_PQ_SetBrightRange(UCHAR8 ucCh, PQBrightRange enRange)
{
    Hv_Drv_PQ_SetBrightRange(ucCh, enRange);

    return;
}

VOID Hv_Mw_PQ_SetColorSpace(UCHAR8 ucCh, PQColorSpace enColorSpace)
{
    const ChannelManager* pstChannelManager = Hv_Mw_Channel_GetManager();
    if(ucCh > 1)
    {
        return;
    }
    if(enColorSpace == PQ_COLOR_SPACE_AUTO)
    {
        if(ColorFormatType_RGB == pstChannelManager->astChannelData[ucCh].stVideoConfigParams.stColor.eClrFormat)
        {
            enColorSpace = PQ_COLOR_SPACE_RGB;
        }
        else
        {
            enColorSpace = PQ_COLOR_SPACE_YUV;
        }
    
    }
    /* Sub Main Logic */
    Hv_Drv_PQ_SetColorSpace(ucCh, enColorSpace);

    return;
}

Status Hv_Mw_PQ_DitherInit(const UINT32 *puiDitherAddr, UINT32 uiLen)
{
    HV_ASSERT_VALID_PTR_RET(puiDitherAddr, HV_FAILURE);
    Hv_Drv_PQ_DitherInit(puiDitherAddr, uiLen);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetBrightness(USHORT16 usBrightness)
{
    UINT32 uiLow = 0; 
    UINT32 uiHigh = 0; 

#if (defined CONFIG_USER_BOE_EDP_GV238QUB_N12 || defined CONFIG_USER_BOE_VBO_DV430QUM_N10_UHD60)
    usBrightness = PQ_BRIGHTNESS_DRV_FOR_OSD_SET_END - usBrightness;  //亮度控制需要反转电平时可打开
#endif

    uiHigh = usBrightness;
    uiLow = HV_PROJECT_CONFIG_MPRT_HIGHT_FREQ_PWM_TOTAL - uiHigh;

    HV_LOG_DEBUG(PQ, "Brightness2 %u", usBrightness);
    Hv_Drv_MPRT_SetOutHighFreqPwmDuty(HV_PROJECT_CONFIG_MPRT_HIGHT_PORT, uiLow, uiHigh);//low-high

    return;
}

Status Hv_Mw_PQ_ScalerUpLutInit(const UINT32 *puiScalerAddr)
{
    HV_ASSERT_VALID_PTR_RET(puiScalerAddr, HV_FAILURE);
    Hv_Drv_PQ_ScalerUpLutInit(puiScalerAddr);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_SetHdrSwitch(UINT32 uiValue)
{
    HV_LOG_DEBUG(PQ, "set Hdr = %u",uiValue);
    HV_ASSERT_SUCCESS_VOID(SendNotifyMessageToSystemTask(SETTING_PARAM_ID_HDR_SWITCH, uiValue));

    return;
}

VOID Hv_Mw_PQ_DmaSetlatch(VOID)
{
    Hv_Drv_DpuPQ_DmaSetlatch();
    return;
}

VOID Hv_Mw_PQ_DmaWorkaround(VOID)
{
    Hv_Drv_DpuPQ_DmaWorkaround();
    return;
}


VOID Hv_Mw_PQ_SetPwmDuty(USHORT16 usHigh)
{
    USHORT16 usLow = 0;
    usLow = HV_PROJECT_CONFIG_MPRT_HIGHT_FREQ_PWM_TOTAL - usHigh;
    Hv_Drv_MPRT_SetOutHighFreqPwmDuty(HV_PROJECT_CONFIG_MPRT_HIGHT_PORT, usLow, usHigh);//low-high
    return;
}

#ifdef CONFIG_USER_DISPCTRL_DEMURA_ON
static Status DemuraCfgInit(const DispCtrlCfg *pstCfg)
{
    HV_ASSERT_VALID_PTR_RET(pstCfg, HV_FAILURE);
    DemuraInitParams stDemuraParam = {0};
    stDemuraParam.usHact = Hv_Mw_Panel_GetPanelHactive();
    stDemuraParam.usVact = Hv_Mw_Panel_GetPanelVactive();
    stDemuraParam.ucColorMode = DEMURA_COLOR_MODE;
    stDemuraParam.ucBlkXBit = DEMURA_BLK_X_BIT;
    stDemuraParam.ucBlkYBit = DEMURA_BLK_Y_BIT;
    stDemuraParam.ucLayerNum = DEMURA_LAYER_NUM;
    stDemuraParam.usBlackLimit = DEMURA_BLACK_LIMIT;
    stDemuraParam.usWhiteLimit = DEMURA_WHITE_LIMIT;
    stDemuraParam.uiDDRAddr = VIRT_TO_PHY(HV_MEMORY_CONFIG_DMURA_DDR_START);
    stDemuraParam.ausBound[0] = DEMURA_LAYER0_LEVEL;
    stDemuraParam.ausBound[1] = DEMURA_LAYER1_LEVEL;
    stDemuraParam.ausBound[2] = DEMURA_LAYER2_LEVEL;
    stDemuraParam.ausBound[3] = DEMURA_LAYER3_LEVEL;
    stDemuraParam.ausBound[4] = DEMURA_LAYER4_LEVEL;
    stDemuraParam.ausBound[5] = DEMURA_LAYER5_LEVEL;
    stDemuraParam.ausBound[6] = DEMURA_LAYER6_LEVEL;
    stDemuraParam.ausBound[7] = DEMURA_LAYER7_LEVEL;
    stDemuraParam.ausBound[8] = DEMURA_LAYER8_LEVEL;

    stDemuraParam.ausStrengthGain[0] = DEMURA_STRENGTH_GAIN_LOW;
    stDemuraParam.ausStrengthGain[1] = DEMURA_STRENGTH_GAIN;
    stDemuraParam.ausStrengthGain[2] = DEMURA_STRENGTH_GAIN_HIGH;

    if ((UINT32*)pstCfg->puiDemuraLut != NULL)
    {
        stDemuraParam.puiDemuraLut = pstCfg->puiDemuraLut;
        stDemuraParam.uiLutLen = pstCfg->uiDemuraLutLen;
        Hv_Drv_Demura_Init(&stDemuraParam);
        Hv_Drv_Demura_Enable(HV_TRUE);
    }
    return;
}
#endif

Status Hv_Mw_PQ_DispCtrlInit(const DispCtrlCfg *pstCfg)
{
    Hv_Drv_FramerateDet_Init(pstCfg->puiFrameDetThd);

#ifdef CONFIG_USER_DISPCTRL_GAMMA_ON
    HvDrvGammaInitParams stGammaIni;
    GammaDataDBRegion *puiGmaAddr = Hv_Common_Db_GetGammaDataDBRegionPtr();

    UINT32 uiNum = HV_COMMON_DATABASE_GET(GammaData, ucGmaNum);
    HV_LOG_DEBUG(PQ,"Gaaaaaa num %x", uiNum);
    UCHAR8 ucCompress = HV_COMMON_DATABASE_GET(GammaData,ucGammaCompress);
    
    if(ucCompress == HV_TRUE)
    {
        UINT32 *puiGammaOrig = NULL;
        puiGammaOrig = (UINT32*)Hv_Vos_Malloc(1025*3);
        HV_ASSERT_VALID_PTR_RET(puiGammaOrig, HV_FAILURE);
        Hv_Drv_GammaDeCompress((UCHAR8*)&puiGmaAddr->auiGamma[0], puiGammaOrig); 
        stGammaIni.puiGammaLutAddr = puiGammaOrig;
    }
    else
    {
        stGammaIni.puiGammaLutAddr = &puiGmaAddr->auiGamma[0];
    }

    stGammaIni.enGammaMod = GAMMA_RGB;
    stGammaIni.enGammaVrrMod  = GAMMA_SYNC;
    stGammaIni.bGammaVrrEn = HV_TRUE;
    stGammaIni.puiGammaVrrLutAddr = pstCfg->puiGammaVrrLut;

    Hv_Drv_Gamma_Init(&stGammaIni);
#endif


#ifdef CONFIG_USER_DISPCTRL_OD_ON
    HvDrvODInitParams    stODIni;
    stODIni.ucCprRatio = OD_CPR_5_83;
    stODIni.ucODMatrixSize = OD_LUT_SIZE_17x17;
    stODIni.ucODLutMode = OD_SEL_LUT0_LUT1;
    stODIni.ucODRGBMode = OD_ACCESS_SYNC;
    stODIni.puiODLut0Addr = pstCfg->puiODLut0;
    stODIni.puiODLut1Addr = pstCfg->puiODLut1;
    stODIni.uiCprDmaAddr = HV_MEMORY_CONFIG_OD_DMA_DDR_START;
    stODIni.usHact = Hv_Mw_Panel_GetPanelHactive();
    stODIni.usVact = Hv_Mw_Panel_GetPanelVactive();
    
    Hv_Drv_OD_Init(&stODIni);
#endif


#ifdef CONFIG_USER_DISPCTRL_DITHER_12_10_ON
    DitherInitParams stDitherParam;
    Hv_Drv_Dither_Init(&stDitherParam);
    
    Hv_Drv_Dither_SetMode(DITHER_MODE_12_10);
    Hv_Drv_Dither_Enable(HV_TRUE);
#endif
#ifdef CONFIG_USER_DISPCTRL_DITHER_12_8_ON
    DitherInitParams stDitherParam;
    Hv_Drv_Dither_Init(&stDitherParam);
    
    Hv_Drv_Dither_SetMode(DITHER_MODE_12_8);
    Hv_Drv_Dither_Enable(HV_TRUE);
#endif

#ifdef CONFIG_USER_DISPCTRL_DEMURA_ON
    DemuraCfgInit(pstCfg);
#endif
    return HV_SUCCESS;
}

#ifdef CONFIG_USER_DISPCTRL_OD_ON

/**
 * @brief OSD控制OD开关的标志，因为OSD Rotation与OD公用DDR，所以在打开OSD时需要关闭OD。
 *        HV_TRUE: OSD控制OD关闭；HV_FALSE: OSD退出时恢复OD
 */
static BOOL s_bOsdControledOdFlag = HV_FALSE;

UCHAR8 Hv_Mw_PQ_GetODLevel(VOID)
{
    return HV_COMMON_DATABASE_GET(UserData, ucResponseTime);
}

VOID Hv_Mw_PQ_SetOsdControledOdFlag(BOOL bControl)
{
    s_bOsdControledOdFlag = bControl;
}

BOOL Hv_Mw_PQ_GetOsdControledOdFlag(VOID)
{
    return s_bOsdControledOdFlag;
}

VOID Hv_Mw_PQ_OsdControlOdOff(BOOL bControl)
{
    //当OSD要控制OD关闭时，传入HV_TRUE，无条件执行关闭OD动作;
    //如果OSD控制了OD关闭，在退出OSD显示时必须要传入HV_FALSE，来释放OSD控制权，此时要根据菜单中的当前选项来恢复OD
    Hv_Mw_PQ_SetOsdControledOdFlag(bControl);

    if(HV_TRUE == bControl)
    {
        Hv_Drv_OD_Enable(HV_FALSE);
        Hv_Drv_ODCPR_Enable(HV_FALSE);
    }
    else
    {
        //默认level 0为od关，非0时这里需要打开OD，此时只能从DB中获取当前的级别来决定是否开OD
        if(0 != Hv_Mw_PQ_GetODLevel())
        {
            Hv_Drv_ODCPR_Enable(HV_TRUE);
            Hv_Drv_OD_SetOdOpenDelayFlag();
        }
    }

    return;
}

VOID Hv_Mw_PQ_SetODLevel(UCHAR8 ucODLevel)
{
    Hv_Drv_OD_ClearOdOpenDelayFlag();

    //关闭OD，刷OD LUT
    Hv_Drv_OD_SetLevel(ucODLevel);

    if(HV_FALSE == Hv_Mw_PQ_GetOsdControledOdFlag())
    {
        //当OSD没有控制OD关闭，且当前OD选项为非关时，打开OD功能，此时是OSD正在控制OD选项，可以直接用传参
        if(0 != ucODLevel)
        {
            Hv_Drv_ODCPR_Enable(HV_TRUE);
            Hv_Drv_OD_SetOdOpenDelayFlag();
        }
    }
    else
    {
        //OSD控制了OD必须关闭，这里不能打开OD
    }
    
    return;
}

Status Hv_Mw_PQ_SetODTable(UCHAR8 *pucOdTable, USHORT16 usTableSize, UCHAR8 ucWhichLut)
{
    HV_ASSERT_VALID_PTR_RET(pucOdTable, HV_FAILURE);
    return Hv_Drv_OD_SetTable(pucOdTable, usTableSize, ucWhichLut);
}
#endif

VOID Hv_Mw_PQ_SetOsdGammaLevel(UCHAR8 ucGammaLevel)
{
    Hv_Drv_PQ_SetOsdGammaIndex(ucGammaLevel);
    HV_LOG_DEBUG(PQ, "Set OSD gamma level to %d", ucGammaLevel);

    return;
}

VOID Hv_Mw_PQ_SetGammaLevel(UCHAR8 ucGammaLevel)
{
#ifdef CONFIG_USER_DISPCTRL_GAMMA_ON
    Hv_Drv_Gamma_SetLevel(ucGammaLevel);
#endif
    Hv_Drv_PQ_SetOsdGammaIndex(ucGammaLevel);
    HV_LOG_DEBUG(PQ, "Set gamma level to %d", ucGammaLevel);
    
    return;
}

VOID Hv_Mw_PQ_SetDemuraLevel(UCHAR8 ucDemuraLevel)
{
    BOOL bEnable = (ucDemuraLevel == 0 ? HV_FALSE : HV_TRUE);
    Hv_Drv_Demura_Enable(bEnable);
}

UCHAR8 Hv_Mw_PQ_GetDemuraCrcFlag(void)
{
    return (Hv_Drv_Demura_GetCRCFlag() == 0 ? 2 : 0);
}

UCHAR8 Hv_Mw_PQ_GetPattern()
{
    return Hv_Drv_DpuPQ_GetPattern();
}

VOID Hv_Mw_PQ_SetInpColor(USHORT16 usRed, USHORT16 usGreen, USHORT16 usBlue)
{
    Hv_Drv_PQ_SetInpPatColor(usRed, usGreen, usBlue);
    return;
}

VOID Hv_Mw_PQ_SetInpPattEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_SetInpPattEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_SetInpPatt(UCHAR8 ucPattSwitch, UCHAR8 ucPatternMode)
{

    if(ucPattSwitch == HV_TRUE)
    {
        Hv_Drv_PQ_SetInpPattEn(1);
        switch (ucPatternMode)
        {
            case 0:
            {
                /* 红 */
                Hv_Mw_PQ_SetInpColor(0x3ff, 0, 0);
                break;
            }
            case 1:
            {
                /* 绿 */
                Hv_Mw_PQ_SetInpColor(0x0, 0x3ff, 0);
                break;
            }
            case 2:
            {
                /* 蓝 */
                Hv_Mw_PQ_SetInpColor(0x0, 0, 0x3ff);
                break;
            }
            case 3:
            {
                /* 白 */
                Hv_Mw_PQ_SetInpColor(0x3ff, 0x3ff, 0x3ff);
                break;
            }
            case 4:
            {
                /* 黄 */
                Hv_Mw_PQ_SetInpColor(0x3ff, 0x3ff, 0);
                break;
            }
            case 5:
            {
                /* 青 */
                Hv_Mw_PQ_SetInpColor(0, 0x3ff, 0x3ff);
                break;
            }
            case 6:
            {
                /* 紫 */
                Hv_Mw_PQ_SetInpColor(0x3ff, 0, 0x3ff);
                break;
            }
            case 7:
            {
                /* 黑 */
                Hv_Mw_PQ_SetInpColor(0, 0, 0);
                break;
            }
            default:
            {
                break;
            }
        }
    }
    else
    {
        Hv_Drv_PQ_SetInpPattEn(0);
        Hv_Mw_PQ_SetInpColor(0, 0, 0);
    }

    return;
}

#if (HV_PROJECT_CONFIG_AMBILIGHT == HV_CONFIG_ON)
/* HNUM and VHUM must be odd number; HNUM max = 31, VNUM max = 19*/
#define PQ_AMBILIGHT_HNUM    7
#define PQ_AMBILIGHT_VNUM    7
#define PQ_AMBILIGHT_BURSTLEN    8

/* 每行数据量必须为128bit整数倍 */
#define PQ_AMBILIGHT_TABLE_HNUM     (PQ_AMBILIGHT_HNUM + 3) / 4 * 4
#define PQ_AMBILIGHT_TABLE_NUM      PQ_AMBILIGHT_TABLE_HNUM * PQ_AMBILIGHT_VNUM
static UINT32 __attribute__((aligned(16))) s_uiAmbilightTable[PQ_AMBILIGHT_TABLE_NUM] = {0};
static CrosshairArea s_stAmbilightArea = {0};


static VOID Hv_Mw_Video_CrosshairGenerateTable(const CrosshairArea *pstArea, USHORT16 *pusWidthTbl, USHORT16 *pusHeightTbl)
{
    UCHAR8 ucIdx;
    PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();
    USHORT16 usScreenWidth = stPanelParam.usPanelHactive;
    USHORT16 usScreenHeight = stPanelParam.usPanelVactive;

    UCHAR8 ucFixedCol = pstArea->usX / (usScreenWidth / PQ_AMBILIGHT_HNUM);
    USHORT16 usBlockWidth = (usScreenWidth - pstArea->usWidth) / (PQ_AMBILIGHT_HNUM - 1);
    USHORT16 usRemainWidth = usScreenWidth - usBlockWidth * (PQ_AMBILIGHT_HNUM - 1) - pstArea->usWidth;

    for (ucIdx = 0; ucIdx < PQ_AMBILIGHT_HNUM; ucIdx++)
    {
        if (ucIdx == ucFixedCol)
        {
            pusWidthTbl[ucIdx] = pstArea->usWidth;
        }
        else
        {
            pusWidthTbl[ucIdx] = usBlockWidth;
            if (usRemainWidth > 0)
            {
                pusWidthTbl[ucIdx]++;
                usRemainWidth--;
            }
        }
    }

    UCHAR8 ucFixedRow = pstArea->usY / (usScreenHeight / PQ_AMBILIGHT_VNUM);
    USHORT16 usBlockHeight = (usScreenHeight - pstArea->usHeight) / (PQ_AMBILIGHT_VNUM - 1);
    USHORT16 usRemainHeight = usScreenHeight - usBlockHeight * (PQ_AMBILIGHT_VNUM - 1) - pstArea->usHeight;

    for (ucIdx = 0; ucIdx < PQ_AMBILIGHT_VNUM; ucIdx++)
    {
        if (ucIdx == ucFixedRow)
        {
            pusHeightTbl[ucIdx] = pstArea->usHeight;
        }
        else
        {
            pusHeightTbl[ucIdx] = usBlockHeight;
            if (usRemainHeight > 0)
            {
                pusHeightTbl[ucIdx]++;
                usRemainHeight--;
            }
        }
    }

    HV_LOG_DEBUG(PQ, "s_uiAmbilightTable  usScreenWidth:%d, usScreenHeight:%d, usBlockWidth:%d, usBlockHeight:%d", 
                    usScreenWidth, usScreenHeight, usBlockWidth, usBlockHeight);

}

VOID Hv_Mw_PQ_CrosshairInit(VOID)
{
    Hv_Drv_PQ_AmBilight_Init();
    return;
}

VOID Hv_Mw_PQ_CrosshairEnable(BOOL bEnable)
{
    Hv_Drv_PQ_AmBilight_Enable(bEnable);
    Hv_Drv_PQ_AmBilight_DMAEnable(bEnable);
    return;
}

Status Hv_Mw_PQ_CrosshairSetArea(CrosshairArea *pstArea)
{
    USHORT16 *pusWidthTbl = (USHORT16 *)HV_MALLOC(PQ_AMBILIGHT_HNUM * sizeof(USHORT16));
    USHORT16 *pusHeightTbl = (USHORT16 *)HV_MALLOC(PQ_AMBILIGHT_VNUM * sizeof(USHORT16));
    
    HV_ASSERT_VALID_PTR_RET(pstArea,     HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(pusWidthTbl, HV_FAILURE);
    HV_ASSERT_VALID_PTR_RET(pusHeightTbl,HV_FAILURE);
    
    HV_MEMSET(pusWidthTbl, 0, PQ_AMBILIGHT_HNUM * sizeof(USHORT16));
    HV_MEMSET(pusHeightTbl, 0, PQ_AMBILIGHT_VNUM * sizeof(USHORT16));

    s_stAmbilightArea.usX = pstArea->usX;
    s_stAmbilightArea.usY = pstArea->usY;
    s_stAmbilightArea.usWidth = pstArea->usWidth;
    s_stAmbilightArea.usHeight = pstArea->usHeight;
    HV_LOG_DEBUG(PQ, "CrosshairSetArea: (%d, %d), %d * %d",
                 pstArea->usX,
                 pstArea->usY,
                 pstArea->usWidth,
                 pstArea->usHeight);

    Hv_Mw_Video_CrosshairGenerateTable(pstArea, &pusWidthTbl[0], &pusHeightTbl[0]);
    UCHAR8 ucIdx = 0;
    for (ucIdx = 0; ucIdx < PQ_AMBILIGHT_HNUM; ucIdx++)
    {
        HV_LOG_DEBUG(PQ, "idx:%d, width:%d", ucIdx, pusWidthTbl[ucIdx]);
        HV_LOG_DEBUG(PQ, "idx:%d, height:%d", ucIdx, pusHeightTbl[ucIdx]);
    }
    Hv_Drv_PQ_AmBilight_SetCells(PQ_AMBILIGHT_HNUM, PQ_AMBILIGHT_VNUM, pusWidthTbl, pusHeightTbl);

    Hv_Drv_PQ_AmBilight_DMAWriteSetting(PQ_AMBILIGHT_HNUM, PQ_AMBILIGHT_VNUM, PQ_AMBILIGHT_BURSTLEN);
    HV_LOG_DEBUG(PQ, "s_uiAmbilightTable  addr:0x%x", &s_uiAmbilightTable);
    Hv_Drv_PQ_AmBilight_DMAWriterAddr(s_uiAmbilightTable);

    if (pusWidthTbl)
    {
        HV_FREE(pusWidthTbl);
    }
    if (pusHeightTbl)
    {
        HV_FREE(pusHeightTbl);
    }
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_CrosshairGetRGBY(CrosshairRGBY *pstValue)
{
    PanelParam stPanelParam = Hv_Mw_Panel_GetCurrentPanelParam();
    UCHAR8 ucFixedCol = s_stAmbilightArea.usX / (stPanelParam.usPanelHactive / PQ_AMBILIGHT_HNUM);
    UCHAR8 ucFixedRow = s_stAmbilightArea.usY / (stPanelParam.usPanelVactive / PQ_AMBILIGHT_VNUM);
    USHORT16 usValueIdx = PQ_AMBILIGHT_TABLE_HNUM * ucFixedRow + ucFixedCol;
    UINT32 uiRGBY = s_uiAmbilightTable[usValueIdx];

    HV_LOG_DEBUG(PQ, "GetRGBY  ucFixedCol:%d, ucFixedRow:%d, usValueIdx:%d, uiRGBY:0x%x,", ucFixedCol, ucFixedRow, usValueIdx, uiRGBY);

    pstValue->ucR = (UCHAR8)((uiRGBY >> 24) & 0xFF);
    pstValue->ucG = (UCHAR8)((uiRGBY >> 16) & 0xFF);
    pstValue->ucB = (UCHAR8)((uiRGBY >> 8) & 0xFF);
    pstValue->ucY = (UCHAR8)((uiRGBY >> 0) & 0xFF);
    return;
}

#endif


#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_AMBIENT_LIGHT)

VOID Hv_Mw_PQ_UpdateFollowingPQ(VOID* pvArgument, USHORT16 usTimerId)
{
    return;
}

VOID Hv_Mw_PQ_StartFollowingPQ(VOID)
{
    return;
}

VOID Hv_Mw_PQ_StopFollowingPQ(VOID)
{
    return;
}

VOID Hv_Mw_PQ_UpdateSingleColor(UCHAR8 ucColorType)
{
    return;
}


VOID Hv_Mw_PQ_UpdateAutoColor(VOID* pvArgument, USHORT16 usTimerId)
{
    return;
}

VOID Hv_Mw_PQ_StartAutoColor(VOID)
{
    return;
}

VOID Hv_Mw_PQ_StopAutoColor(VOID)
{
    return;
}

VOID Hv_Mw_PQ_UpdateMarqueeColor(VOID* pvArgument, USHORT16 usTimerId)
{
    return;
}

VOID Hv_Mw_PQ_StartMarqueeColor(VOID)
{
    return;
}

VOID Hv_Mw_PQ_StopMarqueeColor(VOID)
{
    return;
}

VOID Hv_Mw_PQ_BulbInit(VOID)
{
    return;
}

VOID Hv_Mw_PQ_BulbDeInit(VOID)
{
    return;
}


VOID Hv_Mw_PQ_StartAmbilightTimer(UINT32 uiTimeoutMs)
{
    return;
}

VOID Hv_Mw_PQ_StopAmbilightTimer(VOID)
{
    return;
}

VOID Hv_Mw_PQ_StartAutoTimer(UINT32 uiTimeoutMs)
{
    return;
}

VOID Hv_Mw_PQ_StopAutoTimer(VOID)
{
    return;
}

VOID Hv_Mw_PQ_StartMarqueeTimer(UINT32 uiTimeoutMs)
{
    return;
}

VOID Hv_Mw_PQ_StopMarqueeTimer(VOID)
{
    return;
}

#endif

Status Hv_Mw_PQ_KspiSwSendData(UCHAR8 ucCh, UINT32* puiData, UINT32 uiLength, UCHAR8 ucLastChFlag)
{
    HV_ASSERT_VALID_PTR_RET(puiData, HV_FAILURE);
    Hv_Drv_PQ_KspiSwSendData(ucCh, puiData, uiLength, ucLastChFlag);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_KspiSwSendDataInit(VOID)
{
    Hv_Drv_PQ_KspiSwSendDataInit();
}

VOID Hv_Mw_PQ_KspiSwSendDataStart(VOID)
{
    Hv_Drv_PQ_KspiSwSendDataStart();
}

VOID Hv_Mw_PQ_LdcSetCurveY(UCHAR8 ucY0, UCHAR8 ucY1)
{
    Hv_Drv_PQ_LDC_SetCurveY(ucY0, ucY1);
    return;
}

VOID Hv_Mw_PQ_LDC_LdcEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_LdcEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_LDC_SpaceFilterEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_SpaceFilterEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_LDC_TimeFilterEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_TimeFilterEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_LDC_BlgammaEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_BlgammaEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_LDC_PixelgainEn(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_PixelgainEn(ucEn);
    return;
}

VOID Hv_Mw_PQ_LDC_Blgamma1En(UCHAR8 ucEn)
{
    Hv_Drv_PQ_LDC_Blgamma1En(ucEn);
    return;
}

Status Hv_Mw_PQ_PatDetInit(USHORT16 ** puiArray, UCHAR8 ucPatNum, UCHAR8 ucPatW, UCHAR8 ucPatH)
{
    HV_ASSERT_VALID_PTR_RET(puiArray, HV_FAILURE);
    Hv_Drv_PQ_PatDetInit(puiArray, ucPatNum, ucPatW, ucPatH);
    return HV_SUCCESS;
}

VOID Hv_Mw_PQ_GammaEnable(BOOL bEn)
{
    Hv_Drv_PQ_GammaBypass(bEn);
    return;
}

VOID Hv_Mw_PQ_ColorEnable(BOOL bEn)
{
    Hv_Drv_PQ_ColorBypass(bEn);
    return;
}

USHORT16 Hv_Mw_PQ_GetBlackLevel(UCHAR8 ucCh)
{
    return Hv_Drv_PQ_GetBlackLevel(ucCh);
}

USHORT16 Hv_Mw_PQ_GetContrast(UCHAR8 ucCh)
{
    return Hv_Drv_PQ_GetContrast(ucCh);
}

VOID Hv_Hv_Mw_Video_SetBrightFrameBrightness(USHORT16 usBrightness)
{
    Hv_Mw_PQ_SetBlackLevel(CHANNEL_SUB, usBrightness);
    return;
}

USHORT16 Hv_Mw_Video_GetBrightFrameBrightness(VOID)
{
    return Hv_Mw_PQ_GetBlackLevel(CHANNEL_SUB);
}

VOID Hv_Mw_Video_SetBrightFrameContrast(USHORT16 usContrast)
{
    Hv_Mw_PQ_SetContrast(CHANNEL_SUB, usContrast);
    return;
}

USHORT16 Hv_Mw_Video_GetBrightFrameContrast(VOID)
{
    return Hv_Mw_PQ_GetContrast(CHANNEL_SUB);
}

VOID Hv_Mw_PQ_LDCPrintPattern()
{
    Hv_Drv_PQ_LDCPrintPattern();
}

VOID Hv_Mw_PQ_SetSharpnessReverse(UCHAR8 ucSharpness)
{
    Hv_Drv_PQ_SetSharpnessReverse(ucSharpness);
    return;
}

VOID Hv_Mw_PQ_SetHdrGmiLut(UCHAR8 ucHdrIdx, UINT32 uiHdrGmiLutAddr)
{
    Hv_Drv_PQ_SetHdrGmiLut(ucHdrIdx, uiHdrGmiLutAddr);
    return;
}

VOID Hv_Mw_PQ_LDCPrintSumDiff()
{
    Hv_Drv_PQ_LDCPrintSumDiff();
    return;
}

VOID Hv_Mw_PQ_LDCSetPatThr(UINT32 uiThr)
{
    Hv_Drv_PQ_LDCSetPatThr(uiThr);
    return;
}
VOID Hv_Mw_PQ_GCLutExpand(USHORT16 *pusInput, UCHAR8 ucCnt)
{
    Hv_Drv_PQ_GCLutExpand(pusInput, ucCnt);
}


VOID Hv_Mw_PQ_MhiInit()
{
    Hv_Drv_PQ_MhiInit();
}
VOID Hv_Mw_MhiSetPos(USHORT16 usStartX, USHORT16 usStartY, USHORT16 usWidth, USHORT16 usHeight)
{
    Hv_Drv_MhiSetPos(usStartX, usStartY, usWidth, usHeight);
}

UINT32* Hv_Mw_PQ_GetMhi16()
{
    return Hv_Drv_PQ_GetMhi16();
}


VOID Hv_Mw_PQ_PWM(VOID)
{ 
    Hv_Drv_PQ_PWM();
}

VOID Hv_Mw_PQ_SetBrightRangeY(UCHAR8 ucCh, UCHAR8 ucRange)
{
    Hv_Drv_PQ_SetBrightRangeY(ucCh, ucRange);
}