/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

#include "drv_MapleApi.h"
#include "nptv_debug.h"
#include "pdwnc_if.h"
#include "msdc_if.h"
#include "hw_ycproc.h"
#include "hw_ospe.h"
#include "drv_display.h"
#include "panel.h"
#include "panel_cust.h"

#ifdef CC_SUPPORT_DOLBY_VISION
#include "../../dolby/drv_dolby_drvif.h"
#endif
// === DEFINE =============================================================================
#define CLIP(val, min, max) ((val>=max) ? max : ((val<=min) ? min : val))
#define LOAD_PANEL_FROM_FLASH_BY_NAME 1

/*********************** Definition & Macro *******************************/
typedef enum { 
    E_CUST_PQ_BUF_COMTRAST      = 1<<0,
    E_CUST_PQ_BUF_COLOR         = 1<<1,
    E_CUST_PQ_BUF_HUE           = 1<<2, 
    E_CUST_PQ_BUF_LUMA_CURVE    = 1<<3,    
    E_CUST_PQ_BUF_SRS           = 1<<4,   
    E_CUST_PQ_BUF_SHARPNESS     = 1<<5,    
    E_CUST_PQ_BUF_SCE           = 1<<6,
    E_CUST_PQ_BUF_RGB_GAIN_OFST = 1<<7,
    E_CUST_PQ_BUF_YLEV		    = 1<<8,
    E_CUST_PQ_BUF_MATRIX		= 1<<9,
    E_CUST_PQ_BUF_PARTIALY      = 1<<10,
    E_CUST_PQ_BUF_PARTIALS      = 1<<11,
	E_CUST_PQ_BUF_4BAND_FREQ_RANGE	= 1<<12,
	E_CUST_PQ_BUF_4BAND_FREQ_FILTER = 1<<13,
	E_CUST_PQ_BUF_IBSE_YLEV		    = 1<<14,
	E_CUST_PQ_BUF_PARTIALS_P		= 1<<15,
    E_CUST_PQ_BUF_FLUSH         = 1<<31,
} E_CUST_PQ_BUF_TYPE;


/************************** Extenl function *******************************/

/************************** Global Variable *******************************/
SONY_PQ_FUNC_T* sony_pq_func = NULL;
SONY_BE_FUNC_T* sony_be_func = NULL;
SONY_BE_GEN_FUNC_T* sony_be_gen_func = NULL;
SONY_PQ_GEN_FUNC_T* sony_pq_gen_func = NULL;
SONY_BE_EXT_FUNC_T* sony_be_ext_func = NULL;
UINT8 gU1EnSetTnr;
UINT8 gU1PreEnSetTnr = 0xFF;

UINT8  gu1EcsCommandReply[256];
UINT32  gu4EcsCommandReplySize;
UINT32	gBEErrorDetect = 0x00;
E_BE_DEVICE		gBEDevice;
UINT32		gBEDeviceInfoSize;
VOID*		gBEInfoPara;

UINT8   gBEVersionNum = 8;
UINT8*  gBEVersion = NULL;
static BOOL fgBEVersionIsSet = FALSE;

static UINT16 u2LumaArrayBuf[LUMA_CURVE_NUM_65]; 
static UINT16 u2SkinArrayBuf[LUMA_CURVE_NUM_65]; 
static UINT16 u2ContrastBuf, u2ColorBuf, u2HueBuf, u2BrightnessBuf;
static UINT16 u2MatrixContrastBuf, u2MatrixColorBuf, u2MatrixHueBuf, u2MatrixBrightnessBuf;
static UINT32 PhyAddrBuf_A, PhyAddrBuf_B;
static UINT32 u4BufFlag = 0;
static CUST_SHARP_OFST_T stSharpOfst;
static UINT8 u1SceYSlope[SCE_LUMA_HUE_SLICE];
static UINT8 u1SceSGain1[SCE_HUE_SLICE];
static UINT8 u1SceSGain2[SCE_HUE_SLICE];
static UINT8 u1SceSGain3[SCE_HUE_SLICE];
static UINT8 u1SceSGainP1[SCE_HUE_SLICE];
static UINT8 u1SceSGainP2[SCE_HUE_SLICE];
CUST_LD_HW_TABLE_T tLDHwTable;

static CUST_RGB_GAIN_OFST_T stRGBGainOfst;
extern BOOL fgCriticalSection;
static UINT8 u1YLevArrayBuf[17];
static UINT8 u1YLevIBSEArrayBuf[17]; 

CUST_4BAND_FILTER_RANGE CUST_4BAND_HIST_FILTER_RANGE;
CUST_4BAND_H_FILTER CUST_4BAND_HIST_FILTER;
CUST_CAP_DATA_T CUST_CAP_DATA;
CUST_SCE_CAP_DATA_T CUST_SCE_CAP_DATA;
#define COL_CONV_MAX_NUM (400)
CUST_COL_CONV_TABLE_PARAM_T CUST_COL_CONV_TABLE_PARAM[COL_CONV_MAX_NUM];
UINT16 u1ConvTblParamIDX=0;
extern BOOL CustomPanelLoadTableFromFlash(UINT32 u4Type, void *pData);
CUST_XVYCC_GAMMA_TABLE_SEL_T gbXVYCC_TBL_SEL;
UINT32 gbXVYCC1GmProgrmTbl[4096];
UINT32 gbXVYCC1AGmProgrmTbl[4096];
UINT32 gbXVYCC2GmProgrmTbl[4096];
UINT32 gbXVYCC2AGmProgrmTbl[4096];
CUST_COLOR_SENSOR_SETTING_T gbColorSensorSetting;

/*************************** static functions *****************************/
static void vDrvSetSRS(UINT32 u4Addr_A, UINT32 u4Addr_B)
{       
    LOG(2, "DRVCUST_SetSRSLut Table A Addr 0x%08x Table B Addr 0x%08x \n", u4Addr_A, u4Addr_B);

    if (IO32ReadFldAlign(SRS_3, STA_TBL_UPDATE))
    {        
        LOG(0, "DRVCUST_SetSRSLut Busy !!!! \n");
        return;
    }

    if (u4Addr_A && u4Addr_B)
    {
    	
        vIO32WriteFldAlign(SRS_0, (u4Addr_A & 0x0FFFFFF0)>>4, C_SRS_DRAM_ADR_A);
        vIO32WriteFldAlign(SRS_2, (u4Addr_B & 0x0FFFFFF0)>>4, C_SRS_DRAM_ADR_B);
		vIO32WriteFldAlign(SRS_1, (u4Addr_A & 0x70000000)>>28, C_SRS_ADDR_MSB);

        vIO32WriteFldAlign(SRS_0, 1, C_TBL_UPDATE_TRIG);
        vIO32WriteFldAlign(SRS_0, 0, C_TBL_UPDATE_TRIG);
    }
    else
    {
        LOG(0, "DRVCUST_SetSRSLut Parametes error !!!! \n");
    }    
}

/*************************** functions ************************************/
void DRVCUST_SetExclusiveReg(UINT8 u1Enable)
{

	vDrvADLSetYHistogramMode(u1Enable ? 2 : 0);
	vDrvADLSetLumaCurveMode(u1Enable ? 0 : 1);
    vDrvADLManualLumaCurveOnOff(u1Enable ? 1 : 0);
	vDrvADLOnOff(u1Enable ? 0 : 1);
    vDrvSCECalculateOnOff(u1Enable ? 0 : 1);

    if (u1Enable == SV_FALSE)
    {
        // reset to default 
        DRVCUST_SetContrast(0x80);
        DRVCUST_SetColor(0x80);
        DRVCUST_SetHue(0x80);
    }

    // SRS todo

    LOG(2, "DRVCUST_SetExclusiveReg %d \n", u1Enable); 
}

void DRVCUST_SetLumaCurve(const UINT16* waLArray, const UINT16* waSkinLArray)
{
    x_memcpy(u2LumaArrayBuf, waLArray, LUMA_CURVE_NUM_65*sizeof(UINT16));
	x_memcpy(u2SkinArrayBuf, waSkinLArray, LUMA_CURVE_SKIN_NUM_65*sizeof(UINT16));
    u4BufFlag |= E_CUST_PQ_BUF_LUMA_CURVE;
    //LOG(2, "DRVCUST_SetLumaCurve \n");
}

void DRVCUST_SetContrast(UINT16 u2Value)
{
	#ifndef CC_MTK_AUTO_TEST
    u2ContrastBuf = u2Value;      
    u4BufFlag |= E_CUST_PQ_BUF_COMTRAST;
    //LOG(2, "DRVCUST_SetContrast %d \n", u2Value);
    #else
	vIO32WriteFldAlign(G_PIC_ADJ_MAIN_1,u2Value, CONTRAST);
	#endif
}

void DRVCUST_SetColor(UINT16 u2Value)
{
	#ifndef CC_MTK_AUTO_TEST
    u2ColorBuf= u2Value;  
    
    u4BufFlag |= E_CUST_PQ_BUF_COLOR;
    //LOG(2, "DRVCUST_SetColor %d \n", u2Value);
    #else
	vIO32WriteFldAlign(G_PIC_ADJ_MAIN_2,u2Value, SAT);
	#endif
}

void DRVCUST_SetHue(UINT16 u2Value)
{    
	#ifndef CC_MTK_AUTO_TEST
    u2HueBuf = u2Value;  
   
    u4BufFlag |= E_CUST_PQ_BUF_HUE;
    //LOG(2, "DRVCUST_SetHue %d \n", u2Value);
    #else
	vIO32WriteFldAlign(G_PIC_ADJ_MAIN_2,u2Value<<2, HUE);
	#endif
}

void DRVCUST_SetPqWBGainOffset(CUST_RGB_GAIN_OFST_T* pstRgbGainOfst)
{        
    if (pstRgbGainOfst != NULL)
    {
        x_memcpy(&stRGBGainOfst, pstRgbGainOfst, sizeof(CUST_RGB_GAIN_OFST_T));
    }
    else
    {
        LOG(0, "DRVCUST_SetPqWBGainOffset Failed !!!!\n");
        return;
    }

    u4BufFlag |= E_CUST_PQ_BUF_RGB_GAIN_OFST;
    //LOG(2, "DRVCUST_SetPqWBGainOffset\n");
}

void DRVCUST_GetPqWBGainOffset(CUST_RGB_GAIN_OFST_T* pstRgbGainOfst)
{
    if (pstRgbGainOfst != NULL)
    {
        pstRgbGainOfst->u2RGain = IO32ReadFldAlign(GAINOSET_00, R_GAIN_MAIN);
        pstRgbGainOfst->u2GGain = IO32ReadFldAlign(GAINOSET_00, G_GAIN_MAIN);
        pstRgbGainOfst->u2BGain = IO32ReadFldAlign(GAINOSET_00, B_GAIN_MAIN);
        pstRgbGainOfst->u2ROffset = IO32ReadFldAlign(GAINOSET_02, R_OFST1_MAIN);
        pstRgbGainOfst->u2GOffset = IO32ReadFldAlign(GAINOSET_02, G_OFST1_MAIN);
        pstRgbGainOfst->u2BOffset = IO32ReadFldAlign(GAINOSET_02, B_OFST1_MAIN);
    }
}

void DRVCUST_SetSharpnessOffset(CUST_SHARP_OFST_T* pSharpOfst)
{   
    if (pSharpOfst != NULL)
    {
        x_memcpy(&stSharpOfst, pSharpOfst, sizeof(CUST_SHARP_OFST_T));
    }
    else
    {
        LOG(0, "DRVCUST_SetSharpnessOffset Failed !!!!\n");
        return;
    }
    
    u4BufFlag |= E_CUST_PQ_BUF_SHARPNESS; 

	#if 0
    LOG(2, "DRVCUST_SetSharpnessOffset\n");
    
    LOG(2, "GainH           %d %d %d \n", 
        stSharpOfst.u1GainH[0], stSharpOfst.u1GainH[1], stSharpOfst.u1GainH[2]);
    LOG(2, "GainV           %d %d %d \n", 
        stSharpOfst.u1GainV[0], stSharpOfst.u1GainV[1], stSharpOfst.u1GainV[2]);
    LOG(2, "GainD           %d %d %d \n", 
        stSharpOfst.u1GainD[0], stSharpOfst.u1GainD[1], stSharpOfst.u1GainD[2]);    
    LOG(2, "CoringZeroH     %d %d %d \n", 
        stSharpOfst.u1CorzH[0], stSharpOfst.u1CorzH[1], stSharpOfst.u1CorzH[2]);        
    LOG(2, "CoringZeroV     %d %d %d \n", 
        stSharpOfst.u1CorzV[0], stSharpOfst.u1CorzV[1], stSharpOfst.u1CorzV[2]);
    LOG(2, "CoringZeroD     %d %d %d \n", 
        stSharpOfst.u1CorzD[0], stSharpOfst.u1CorzD[1], stSharpOfst.u1CorzD[2]);
	LOG(2, "HSHPGainLow          %d %d \n", 
        stSharpOfst.u1HSHPGainLow[0], stSharpOfst.u1HSHPGainLow[1]);
    LOG(2, "HSHPGainMid          %d %d \n", 
        stSharpOfst.u1HSHPGainMid[0], stSharpOfst.u1HSHPGainMid[1]);
    LOG(2, "HSHPGainHigh         %d %d \n", 
        stSharpOfst.u1HSHPGainHigh[0], stSharpOfst.u1HSHPGainHigh[1]);    
    LOG(2, "HSHPCoringZero     %d %d %d \n", 
        stSharpOfst.u1HSHPCor[0], stSharpOfst.u1HSHPCor[1], stSharpOfst.u1HSHPCor[2]);        
    LOG(2, "EdgeGain     %d %d %d \n", 
        stSharpOfst.u1EdgeGain[0], stSharpOfst.u1EdgeGain[1], stSharpOfst.u1EdgeGain[2]);
    LOG(2, "DetailGain     %d %d %d \n", 
        stSharpOfst.u1DetailGain[0], stSharpOfst.u1DetailGain[1], stSharpOfst.u1DetailGain[2]);
	LOG(2, "LTIGain     %d %d %d \n", 
        stSharpOfst.u1LTIGain[0], stSharpOfst.u1LTIGain[1], stSharpOfst.u1LTIGain[2]);
    LOG(2, "LTICoringZero     %d %d %d \n", 
        stSharpOfst.u1LTICorz[0], stSharpOfst.u1LTICorz[1], stSharpOfst.u1LTICorz[2]);
	
    LOG(0, "u1Edf1Th     %d %d %d \n", 
        stSharpOfst.u1Edf1Th[0], stSharpOfst.u1Edf1Th[1], stSharpOfst.u1Edf1Th[2]);
	
    LOG(0, "u1Edf2Th     %d %d %d %d \n", 
        stSharpOfst.u1Edf2Th[0], stSharpOfst.u1Edf2Th[1], stSharpOfst.u1Edf2Th[2], stSharpOfst.u1Edf2Th[3]);

    LOG(0, "u1Edf2FGain     %d %d %d \n", 
        stSharpOfst.u1Edf2FGain[0], stSharpOfst.u1Edf2FGain[1], stSharpOfst.u1Edf2FGain[2]);

    LOG(0, "u1Edf2DGain     %d %d %d  \n", 
        stSharpOfst.u1Edf2DGain[0], stSharpOfst.u1Edf2DGain[1], stSharpOfst.u1Edf2DGain[2]);

	
    LOG(0, "u1Edf2DGain     %d %d %d %d %d %d \n", 
        stSharpOfst.u1Edf2EGain[0], stSharpOfst.u1Edf2EGain[1], stSharpOfst.u1Edf2EGain[2],  stSharpOfst.u1Edf2EGain[3], stSharpOfst.u1Edf2EGain[4], stSharpOfst.u1Edf2EGain[5]);
	#endif
	
}


void DRVCUST_SetSRSLut(UINT8* pTableA, UINT8* pTableB)
{  
    LOG(2, "DRVCUST_SetSRSLut Table A Addr 0x%08x Table B Addr 0x%08x \n", pTableA, pTableB);

    if (pTableA && pTableB)
    {
        PhyAddrBuf_A = PHYSICAL((UINT32)pTableA);
        PhyAddrBuf_B = PHYSICAL((UINT32)pTableB);        
        u4BufFlag |= E_CUST_PQ_BUF_SRS;
    }
    else
    {
        LOG(0, "DRVCUST_SetSRSLut Parametes error !!!! \n");
    }    
}

UINT8 DRVCUST_CheckSetSRSLut(void)
{
    if (u4BufFlag&E_CUST_PQ_BUF_SRS)
	{
	    return SV_TRUE;
	}
	else
	{
	    return SV_FALSE;
	}
}

UINT8 DRVCUST_FlushPqSetting(void)
{  
	if(fgCriticalSection)
	{    
		return SV_FALSE;
	}
	
    u4BufFlag |= E_CUST_PQ_BUF_FLUSH;

    //LOG(2, "DRVCUST_FlushPqSetting !!!! \n");

	return SV_TRUE;
}

UINT8 DRVCUST_CheckFlushPqSettingFlag(void)
{
    if (u4BufFlag&E_CUST_PQ_BUF_FLUSH)
	{
	    return SV_TRUE;
	}
	else
	{
	    return SV_FALSE;
	}
}

void DRVCUST_EnNoiseLevel(UINT8 u1Enable)
{
    vIO32WriteFldAlign(NR_NM_16, u1Enable, CUST_FORCE_NOISE_LVL_EN);
    //LOG(2, "DRVCUST_EnNoiseLevel %d \n", u1Enable);
}

UINT8 DRVCUST_GetNoiseLevelEn(void)
{
    return IO32ReadFldAlign(NR_NM_16, CUST_FORCE_NOISE_LVL_EN);
}

void DRVCUST_SetNoiseLevel(UINT8 u1NoiseLevel)
{
    vIO32WriteFldAlign(NR_NM_16, u1NoiseLevel, CUST_FORCE_NOISE_LVL);
    //LOG(2, "DRVCUST_SetNoiseLevel %d \n", u1NoiseLevel);
}

UINT8 DRVCUST_GetNoiseLevel(void)
{
    return IO32ReadFldAlign(NR_NM_16, CUST_FORCE_NOISE_LVL);
}

void DRVCUST_EnNoiseLevel2(UINT8 u1Enable)	
{
    vIO32WriteFldAlign(NR_NM_16, u1Enable, CUST_FORCE_NOISE_LVL2_EN);
    //LOG(2, "DRVCUST_EnNoiseLevel %d \n", u1Enable);
}

UINT8 DRVCUST_GetNoiseLevel2En(void)
{
    return IO32ReadFldAlign(NR_NM_16, CUST_FORCE_NOISE_LVL2_EN);
}

void DRVCUST_SetNoiseLevel2(UINT8 u1NoiseLevel)
{
    vIO32WriteFldAlign(NR_NM_16, u1NoiseLevel, CUST_FORCE_NOISE_LVL2);
    //LOG(2, "DRVCUST_SetNoiseLevel %d \n", u1NoiseLevel);
}

UINT8 DRVCUST_GetNoiseLevel2(void)
{
    return IO32ReadFldAlign(NR_NM_16, CUST_FORCE_NOISE_LVL2);
}

void DRVCUST_SetPostSharpYLev(UINT8* pYLev)
{
	if(pYLev==NULL)
	{
		LOG(0, "Err! Ptr Sharp ness pYLev null !!!!\n");
		return;
	}
    x_memcpy(u1YLevArrayBuf, pYLev, 17);
    u4BufFlag |= E_CUST_PQ_BUF_YLEV;
    //LOG(2, "DRVCUST_SetPostSharpYLev \n");
}
void DRVCUST_SetIbseYLev(UINT8* pYLev)
{
	if(pYLev==NULL)
	{
		LOG(0, "Err! Ptr IBSE pYLev null !!!!\n");
		return;
	}
    x_memcpy(u1YLevIBSEArrayBuf, pYLev, 17);
    u4BufFlag |= E_CUST_PQ_BUF_IBSE_YLEV;
    //LOG(2, "DRVCUST_SetPostSharpYLev \n");
}

void DRVCUST_GetPostSharpYLev(UINT8* pYLev)
{
    DRVCUST_GetYLevTable(pYLev);
}

void DRVCUST_GetIbseYLev(UINT8* pYLev)
{
    DRVCUST_GetIbseYLevTable(pYLev);
}


void DRVCUST_UpdateTimingGroup(UINT8* pCustSrcTimingTbl, UINT8* pCustSrcGroup)
{    
    UINT32 u4SrcTimingSize = sizeof(bCustomSrcTimingTbl);
    UINT32 u4SrcGroupSize = sizeof(bCustomSourceGroup);

    if (pCustSrcTimingTbl && pCustSrcGroup)
    {           
        if ((pCustSrcTimingTbl[u4SrcTimingSize-1] == SOURCE_TYPE_TIMING_MAX)
            && (pCustSrcGroup[u4SrcGroupSize-1] == SOURCE_TYPE_TIMING_MAX)
            && (pCustSrcGroup[u4SrcGroupSize-2] == SOURCE_TYPE_TIMING_MAX))
        {
    	    x_memcpy(bCustomSrcTimingTbl, pCustSrcTimingTbl, u4SrcTimingSize);
    	    x_memcpy(bCustomSourceGroup, pCustSrcGroup, u4SrcGroupSize);
            bApiParseCustomQtyItem();
        }
        else
        {
            LOG(0, "DRVCUST_UpdateTimingGroup : Array mismatch !!! \n");
        }
    }
    else
    {
        LOG(0, "DRVCUST_UpdateTimingGroup : Null pointer !!! \n");
    }

    //LOG(2, "DRVCUST_UpdateTimingGroup \n");
}

void DRVCUST_PqSendDataToBe(UINT8* pData, UINT32 u4Size)
{
    if (sony_be_func && sony_be_func->be_receive_from_pq)
    {
        sony_be_func->be_receive_from_pq(pData, u4Size);
    }
}

void DRVCUST_RegisterPqFunc(SONY_PQ_FUNC_T *pq_func)
{
    if (pq_func)
    {
        sony_pq_func = pq_func;
        LOG(2, "Sony PQ function registered \n");	
    }
    else
    {
        LOG(2, "Sony PQ function NULL \n");
    }
}

void DRVCUST_DeregisterPqFunc(void)
{
    sony_pq_func = NULL;    
    LOG(2, "Sony PQ function unregistered \n");
}

void DRVCUST_RegisterBeFunc(SONY_BE_FUNC_T *be_func)
{
    if (be_func)
    {
        sony_be_func = be_func;
        LOG(2, "Sony BE function registered \n");
		//DRVCUST_BE_Connect(0,0,0,0);
		//DRVCUST_BE_Connect(1,2,2,2);
		DRVCUST_BE_Connect(E_CUST_BE_TX_PATH_VIDEO,E_CUST_BE_SCL_TYPE_PQ,E_CUST_BE_PLANE_ORDER_0,SV_VP_MAIN);
		DRVCUST_BE_Connect(E_CUST_BE_TX_PATH_GFX,E_CUST_BE_SCL_TYPE_GFX,E_CUST_BE_PLANE_ORDER_2,SV_VP_NA);
	//	DRVCUST_BE_Connect(E_CUST_BE_TX_PATH_VIDEO,E_CUST_BE_SCL_TYPE_VIDEO,E_CUST_BE_PLANE_ORDER_1,SV_VP_PIP);//just for test
    }
    else
    {
        LOG(2, "Sony BE function NULL \n");
    }
}

void DRVCUST_DeregisterBeFunc(void)
{
	
    sony_be_func = NULL;    
    LOG(2, "Sony BE function unregistered \n");
}

void DRVCUST_RegisterBeGeneralFunc (SONY_BE_GEN_FUNC_T* be_gen_func)
{
    if (be_gen_func)
    {
        sony_be_gen_func = be_gen_func;
        LOG(2, "Sony BE General function registered \n");
    }
    else
    {
        LOG(2, "Sony BE General function NULL \n");
    }
}

void DRVCUST_DeregisterBeGeneralFunc(void)
{
    sony_be_gen_func = NULL;    
    LOG(2, "Sony BE General function unregistered \n");
}

void DRVCUST_RegisterPQGeneralFunc(SONY_PQ_GEN_FUNC_T* pq_gen_func)
{
	if(pq_gen_func)
	{
		sony_pq_gen_func = pq_gen_func;
        LOG(2, "Sony PQ General function registered \n");
	}
	else
	{	
		LOG(2, "Sony PQ General function NULL \n");
	}
}

void DRVCUST_DeRegisterPQGeneralFunc(void)
{
    sony_pq_gen_func = NULL;    
    LOG(2, "Sony PQ General function unregistered \n");
}
void DRVCUST_ResetSystem(E_CUST_RESET eReset)
{   
    switch (eReset)
    {
        case E_CUST_RESET_SHUTDOWN:                        
            PDWNC_EnterPowerDown(WAK_IRRX | WAK_RTC, (UINT32)PDWNC_POWER_DOWN_UNKNOWN);            
            break;
        default:
        case E_CUST_RESET_REBOOT:
            PDWNC_Reboot();
            break;
    }
    
    LOG(2, "DRVCUST_ResetSystem %d \n", eReset);
}

void DRVCUST_SetEcsCommandReply(UINT8* pData, UINT32 u4Size)
{
	
	if (u4Size <= 256) 
	{
		gu4EcsCommandReplySize = u4Size;
		x_memcpy(gu1EcsCommandReply, pData, u4Size);
	}
	
    //LOG(2, "DRVCUST_SetEcsCommandReply \n");
}

UINT32 DRVCUST_BePartitionWrite(E_CUST_BE_PART ePartId, UINT32 u4Offset, VOID *pvBuf, UINT32 u4BufSize)
{
	UINT64 u8Offset;
    UINT64 u8offsetTmp;
	UINT64 u4RelPartId=0 ;
    INT32  i4Ret, u4PartitionSize, u4FooterInfo;
    UINT8 u4Tmp0, u4Tmp1, u4Tmp2, u4Tmp3, u4BankIndexNum, u4DualFlagIsSupported;
    UINT8 _u4FooterInfo[8];
    UINT8 *pu4FooterInfo = _u4FooterInfo;

    LOG(2, "DRVCUST_BePartitionWrite\n");
	if(ePartId >= E_CUST_PART_MAX)
	{
		Printf("%s error : partid is invalid\n", __FUNCTION__);
		return 1 ;
}
	if (DRVCUST_InitQuery64(eBELPartitionId, &u4RelPartId) != 0 )
	{
		Printf("%s error query BE ID\n", __FUNCTION__);
		return 1;
	}

    u4RelPartId += ePartId ;
	u8Offset = ((UINT64)(u4RelPartId << 32)) | u4Offset ;

    /* Dual Bank Partition */
    if (ePartId == E_CUST_PART_FDAT || ePartId == E_CUST_PART_UDAT) {
        /* Read Bank Ctrl Info */
        u4PartitionSize     = DRVCUST_InitGet64((QUERY_TYPE_T)(eNANDFlashPartSize0 + u4RelPartId));
        u8offsetTmp = ((UINT64)((UINT64)u4RelPartId << 32)) | (u4PartitionSize - 32);
        MSDCPART_Read(u8offsetTmp, pu4FooterInfo, 8);
        u4Tmp0 = *pu4FooterInfo;
        u4Tmp1 = *(pu4FooterInfo+1);
        u4Tmp2 = *(pu4FooterInfo+2);
        u4Tmp3 = *(pu4FooterInfo+3);
        u4FooterInfo = ((UINT32)(u4Tmp0<<24)+(UINT32)(u4Tmp1<<16)+(UINT32)(u4Tmp2<<8)+(UINT32)u4Tmp3);

        u4DualFlagIsSupported = *(pu4FooterInfo+4);
        u4BankIndexNum        = *(pu4FooterInfo+5);

        if (u4FooterInfo == 0x4354524C && u4DualFlagIsSupported) {
            if (u4BankIndexNum == 0) {
                u8Offset += ((u4PartitionSize / 2) - 16);
                Printf("%s  u4BankIndexNum = 0: u8Offset => 0x%08x %ld\n", __FUNCTION__, u8Offset, u8Offset);
                i4Ret = MSDCPART_Write((UINT64)u8Offset, (UPTR)pvBuf, u4BufSize);

                if (i4Ret == 0) {
                    u4BankIndexNum = 1;
                    u8offsetTmp = ((UINT64)((UINT64)u4RelPartId << 32)) | (u4PartitionSize - 27);
                    MSDCPART_Write((UINT64)u8offsetTmp, (UPTR)&u4BankIndexNum, 1);
                }
            } else {
                Printf("%s u4BankIndexNum = 1: u8Offset => 0x%08x %ld\n", __FUNCTION__, u8Offset, u8Offset);
                i4Ret = MSDCPART_Write((UINT64)u8Offset, (UPTR)pvBuf, u4BufSize);

                 if (i4Ret == 0) {
                    u4BankIndexNum = 0;
                    u8offsetTmp = ((UINT64)((UINT64)u4RelPartId << 32)) | (u4PartitionSize - 27);
                    MSDCPART_Write((UINT64)u8offsetTmp, (UPTR)&u4BankIndexNum, 1);
                }
            }
        } else {
            i4Ret = MSDCPART_Write((UINT64)u8Offset, (UPTR)pvBuf, u4BufSize);
        }
    } else {
        /* Single Bank Partition */
        i4Ret = MSDCPART_Write((UINT64)u8Offset, (UPTR)pvBuf, u4BufSize);
    }
    return i4Ret;
}

UINT32 DRVCUST_SopqPartitionWrite(E_CUST_SPQ_PART ePartId, UINT32 u4Offset, VOID *pvBuf, UINT32 u4BufSize)
{
	UINT64 u8Offset;
	UINT64 u4RelPartId=0 ;
	INT32  i4Ret;
	
	LOG(2, "DRVCUST_SopqPartitionWrite\n");
	if(ePartId >= E_CUST_PART_SPMAX)
	{
		Printf("%s error : partid is invalid\n", __FUNCTION__);
		return 1 ;
	}
	
	if(ePartId == E_CUST_PART_SPQD)
	{
		if (DRVCUST_InitQuery64(eSPQDPartition, &u4RelPartId) != 0 )
		{
			Printf("%s error E_CUST_PART_SPQD ID\n", __FUNCTION__);
			return 1;
		}	
	}
	else
	{
		if (DRVCUST_InitQuery64(eSPQCPartition, &u4RelPartId) != 0 )
		{
			Printf("%s error eSPQCPartition ID\n", __FUNCTION__);
			return 1;
		}	
	}

	// u4RelPartId += ePartId ;
	u8Offset = ((UINT64)(u4RelPartId << 32)) | u4Offset ;

	i4Ret = MSDCPART_Write((UINT64)u8Offset, (UPTR)pvBuf, u4BufSize);
	return i4Ret;
}


void DRVCUST_SetBeDeviceInformation(E_BE_DEVICE device, VOID* pParam, UINT32 size)
{
	gBEDevice = device;
	gBEInfoPara = pParam;
	gBEDeviceInfoSize = size;
	UINT8 arPanelIDString_New_Recipe[ATV_PANEL_ID_STRING_LEN+1]={0};
	
	//get panel ID string forn New_Recipe_condition_data
	EEPROM_Read(0x10020, (UPTR)arPanelIDString_New_Recipe, 16);
	arPanelIDString_New_Recipe[ATV_PANEL_ID_STRING_LEN]='\0';
	Printf("4K New_Recipe_condition_data_PANEL_ID_STRING=%s \n",arPanelIDString_New_Recipe);

	//panel ID string forn 4KBE
	Printf("4K Panel ID String From 4KBE=%s \n",pParam);
	
	if (x_strncmp((const char *)pParam, (const char *)arPanelIDString_New_Recipe, ATV_PANEL_ID_STRING_LEN) == 0)	
	{
		Printf("4K Panel ID String From 4KBE = [New]Recipe Condition Data \n");
	}
	else
	{
		Printf("Panel ID String From 4KBE != [New]Recipe Condition Data \n");
		//Write  panel ID string forn 4KBE to [New]Recipe Condition Data
		if(device == PANEL_INFO)
		{
			if(CustomPanelLoadTableFromFlash(LOAD_PANEL_FROM_FLASH_BY_NAME, pParam))
			{
				EEPROM_Write(0x10020, pParam, size);
			}
		}
		//LED blinking +turn 4K panel off
		GPIO_CustomLedCtrlFunc(eLedErrPanelID);
        #ifdef CC_SUPPORT_STR
		ostg_set_fgPanelPowerState(FALSE);//4K set pnael power off
		#endif
	}
	
	//LOG(2, "DRVCUST_SetBeDeviceInformation\n");
}


void DRVCUST_SetBeDeviceErrorDetect(E_BE_ERROR_DETECT Efactor)
{
	gBEErrorDetect |= Efactor;
	//LOG(2, "DRVCUST_SetBeDeviceInformation: 0x%04x\n", Efactor);
}

void DRV_CUST_SetBEDeviceVersion(UINT8 u1Number, UINT8* pVersion)
{
    gBEVersionNum = u1Number;

	if(gBEVersion != NULL)
	{
		x_mem_free(gBEVersion);
		gBEVersion = NULL;
	}
		
    if ((gBEVersion = (UINT8*)x_mem_alloc(gBEVersionNum*20)) == NULL)
    {
        LOG(0, "DRVCUST_SetBeDeviceInformation: gBEVersion memory allocation fail!\n");
    }
    else
    {
        x_memcpy(gBEVersion, pVersion, gBEVersionNum*20);
    }
    
    if (!fgBEVersionIsSet)
    {
        fgBEVersionIsSet = TRUE;
    }
    //LOG (2, "DRVCUST_SetBeDeviceInformation\n");
}

UINT8 QueryBEDeviceVersionNum(void)
{
    return gBEVersionNum;
}

INT32 QueryBEDeviceVersion(UINT8* pOut)
{
    if (pOut == NULL)
   {
        LOG(0, "DRVCUST_GetBEDeviceVersion: output pointer is null\n");
        return -1;
   }
   else
   {
        if (fgBEVersionIsSet)
        {
            x_memcpy(pOut, gBEVersion, gBEVersionNum*20);
            return 0;
        }
        else
        {            
            LOG(0, "DRVCUST_GetBEDeviceVersion: BE version has not been set\n");
            return -1;
        }
   }
}

void DRVCUST_SetPqColMatrixParam(UINT8 u1Upof_ext, UINT8 u1Ucof_ext,UINT8 u1Ubof_ext )
{
	u2MatrixContrastBuf = u1Upof_ext;      
	u2MatrixColorBuf = u1Ucof_ext;      
	u2MatrixBrightnessBuf = u1Ubof_ext;      
    u4BufFlag |= E_CUST_PQ_BUF_MATRIX;
	//LOG(2, "DRVCUST_SetPqColMatrixParam\n");
}

void DRVCUST_GetPqColMatrixParam(UINT8 *u1Cont_ext, UINT8 *u1Color_ext,UINT8 *u1Bri_ext )
{
    *u1Cont_ext = IO32ReadFldAlign(GLOBAL_ADJ_04, EXT_ADJ_CONT);
    *u1Color_ext = IO32ReadFldAlign(GLOBAL_ADJ_04, EXT_ADJ_SAT);
    *u1Bri_ext = IO32ReadFldAlign(GLOBAL_ADJ_04, EXT_ADJ_BRI);
}

void DRVCUST_SetPqNewPartialS(UINT8* u1PointL, UINT8* u1PointM, UINT8* u1PointH)
{     
    if (u1PointL != NULL)
    {
        x_memcpy(u1SceSGain1, u1PointL, SCE_HUE_SLICE);
    }
    else
    {
        LOG(0, "DRVCUST_SetPqNewPartialSFailed u1PointL!!!!\n");
        return;
    }

	if (u1PointM != NULL)
    {
        x_memcpy(u1SceSGain2, u1PointM, SCE_HUE_SLICE);
    }
    else
    {
        LOG(0, "DRVCUST_SetPqNewPartialSFailed u1PointM!!!!\n");
        return;
    }

	if (u1PointH != NULL)
    {
        x_memcpy(u1SceSGain3, u1PointH, SCE_HUE_SLICE);
    }
    else
    {
        LOG(0, "DRVCUST_SetPqNewPartialSFailed u1PointH!!!!\n");
        return;
    }
	
	u4BufFlag |= E_CUST_PQ_BUF_PARTIALS;
    u4BufFlag |= E_CUST_PQ_BUF_SCE;
    //LOG(2, "DRVCUST_SetPqNewPartialS \n");
}

void DRVCUST_SetPqPartialY(UINT8* u1Point)
{     
    if (u1Point != NULL)
    {
        x_memcpy(u1SceYSlope, u1Point, SCE_LUMA_HUE_SLICE);
    }
    else
    {
        LOG(0, "DRVCUST_SetPqPartialY Failed !!!!\n");
        return;
    }
    
    u4BufFlag |= E_CUST_PQ_BUF_SCE;
	u4BufFlag |= E_CUST_PQ_BUF_PARTIALY;
    //LOG(2, "DRVCUST_SetPqPartialY \n");
}

void DRVCUST_SetScalerCoefLumaH(UINT32* u4Array)
{     
	vDrvSCPQSetSramCoeff(COEFTYP_HOR_Y, u4Array);
}

void DRVCUST_SetScalerCoefChromaH(UINT32* u4Array)
{     
	vDrvSCPQSetSramCoeff(COEFTYP_HOR_C, u4Array);
}

void DRVCUST_SetScalerCoefLumaV(UINT32* u4Array)
{     
	vDrvSCPQSetSramCoeff(COEFTYP_VER_Y, u4Array);
}

void DRVCUST_SetScalerCoefChromaV(UINT32* u4Array)
{     
	vDrvSCPQSetSramCoeff(COEFTYP_VER_C, u4Array);
}

void DRVCUST_SetLdHwParam(CUST_LD_HW_PARAM_T* pLDHWParam)
{     
	vDrvLcDimSetHWParam((LCDIM_HW_PARAM_T*)pLDHWParam);
}

void DRVCUST_SetLdSwParam(CUST_LD_SW_PARAM_T* pLDSWParam)
{     
	vDrvLcDimSetSWParam((LCDIM_SW_PARAM_T*)pLDSWParam);
}

void DRVCUST_SetLdHwTable(CUST_LD_HW_TABLE_T* pLDHWTable)
{
    x_memcpy(&tLDHwTable, pLDHWTable, sizeof(CUST_LD_HW_TABLE_T));
    vApiRegisterVideoEvent(PE_EVENT_LD, VDP_1, SV_ON);
	//vDrvLcdimWriteDimTable(pLDHWTable->u2LDDimTable);
    //vDrvLcdimWriteGainTable(pLDHWTable->u2LDGainTable);
    //vDrvLcdimWriteGainLimitTable(pLDHWTable->u2LDGainLimitTable); 
}

void DRVCUST_SetLdSwTable(CUST_LD_SW_TABLE_T* pLDSWTable)
{     
	vDrvLcDimSetSWTable(pLDSWTable->u2LDGainLimitTable_LOW_BND, pLDSWTable->u2LDGainLimitTable_UP_BND);
	//LOG(2, "DRVCUST_SetLdSwTable \n");
}

void DRVCUST_SetPqSwVersion(UINT8* pData)
{     

}

extern UINT8 bIsMetaData;
extern UINT8 u1MetaDataVerify;

void DRVCUST_SetPqMetaData(CUST_PQ_META_DATA_T* pPqMetaData)
{
    if(bIsMetaData || u1MetaDataVerify)
    {
        FBM_POOL_T *prPool = FBM_GetPoolInfo(FBM_POOL_TYPE_SCPOS_PIP);
        if(prPool == NULL)
        {
            LOG(0, "PqMetaData memory request fail\n");
            return ;
        }

        if(VDP_LogChkMsk(VDP_1,VDP_LOG_DBG_MSK_META))
        {
            Printf("[%s][%d] 0x%08x 0x%08x \n",__FUNCTION__,__LINE__, prPool->u4Addr , (UINT8*)VIRTUAL(prPool->u4Addr));
        }

        SCPIP_WRITE_FLD(SCPIP_DRAM_P_1F, 0, DRAM_P_1F_DRAM2_IMPORT_EN);
        TranMetadataToDram((UINT8*)VIRTUAL(prPool->u4Addr), &(pPqMetaData->u1DataBody[0]), pPqMetaData->u2DataSize);
    
    }
}
#define BLOCK_HEIGHT    (8)
#define BLOCK_WIDTH     (256)
#define BLOCK_SIZE      (2048) // (8*256)
#define LINE_LENGHT     (1920)
#define SIZE_LENGHT     (2)

void TranMetadataToDram(UINT8 *pDest, UINT8 *pSrc, UINT16 u4Size)
{
    UINT32 u4CopySize=0, u4DestIdx=0, u4SrcIdx=0, u4Processed=0;
    BOOL   fgSwitchBlockLine=FALSE, fgFirstBlockLineSwitched=FALSE;
    UINT8 *pTmpDest=pDest, *pTmpSrc=pSrc,u1CurLine=1;

    UINT32 u4TestIdx = 0;

    // Assign the MetaData size
    *pTmpDest = (UINT8)u4Size;
    *(pTmpDest+1) = (UINT8)(u4Size>>8);

    if(VDP_LogChkMsk(VDP_1,VDP_LOG_DBG_MSK_META))
    {
        dump_stack();

        Printf("[%s][%d] size(%d) dst(%08x) dstL(%x) dstH(%x) \n",__FUNCTION__,__LINE__,
            u4Size, pTmpDest ,pTmpDest[0], pTmpDest[1]);

        for(u4TestIdx = 0; u4TestIdx < u4Size; u4TestIdx++)
        {
            Printf("[%s][%d] input src(%x) tmpSrc(%x) \n",__FUNCTION__,__LINE__,pSrc[u4TestIdx],pTmpSrc[u4TestIdx]);
        }
    }

    pTmpDest += SIZE_LENGHT;

    // Speical process the first block rest data
    u4CopySize = (u4Size > BLOCK_WIDTH-SIZE_LENGHT) ? (BLOCK_WIDTH-SIZE_LENGHT) : u4Size;
    x_memcpy((void *)pTmpDest, (void *)pTmpSrc, u4CopySize);

    // Init for while Loop
    pTmpDest    = pDest;
    u4Processed = u4CopySize;
    u4SrcIdx    = u4CopySize;

    if(VDP_LogChkMsk(VDP_1,VDP_LOG_DBG_MSK_META))
    {
        Printf("[%s][%d] input u4Processed(%d) u4Size(%d) \n",__FUNCTION__,__LINE__,u4Processed , u4Size);
    }

    // Process the rest MetaData
    while (u4Processed < u4Size)
    {
        u4CopySize = ((LINE_LENGHT-u4SrcIdx)>BLOCK_WIDTH) ? (BLOCK_WIDTH) : ((fgSwitchBlockLine=TRUE),(LINE_LENGHT-u4SrcIdx));
        // Sepcail process for the first Block Line
        if ((fgFirstBlockLineSwitched==FALSE) && fgSwitchBlockLine)
        {
            fgFirstBlockLineSwitched = TRUE;
            u4CopySize = LINE_LENGHT%BLOCK_WIDTH;
        }
        u4DestIdx  = (((u4SrcIdx+BLOCK_WIDTH-1)/BLOCK_WIDTH)*BLOCK_HEIGHT*BLOCK_WIDTH);
        u4CopySize = (u4Size-u4Processed > u4CopySize) ? u4CopySize : (u4Size-u4Processed);
 
        x_memcpy((void *)pTmpDest+u4DestIdx, (void *)pTmpSrc+u4SrcIdx, u4CopySize);
        #if 1
        if(VDP_LogChkMsk(VDP_1,VDP_LOG_DBG_MSK_META))
        {
            Printf("0x%X<==0x%X %d Size:%u  Ratio:%u/%u Idx:%u TestData(0x%08X)\n", (void *)pTmpDest+u4DestIdx, (void *)pTmpSrc+u4SrcIdx,u1CurLine, 
                   u4CopySize, u4Processed, u4Size, u4SrcIdx, *(UINT32 *)(pTmpDest+u4DestIdx));
        }
        #endif
        if (fgSwitchBlockLine)
        {

            if(u1CurLine==BLOCK_HEIGHT)
            {
                pTmpDest=pTmpDest+u4DestIdx+BLOCK_WIDTH;
                u1CurLine=0;
            }
            else
            {
                pTmpDest=pTmpDest+u4DestIdx-BLOCK_WIDTH*BLOCK_HEIGHT*(LINE_LENGHT/BLOCK_WIDTH)+BLOCK_WIDTH;
            }
            pTmpSrc += (u4SrcIdx+u4CopySize);
            fgSwitchBlockLine = FALSE;
            u4SrcIdx   = 0;
            u4DestIdx  = 0;
            u4CopySize = 0;
            u1CurLine++;


        }
        else
        {
            u4SrcIdx += u4CopySize;
        }
        u4Processed += u4CopySize;
    }

    // Dcache invalid
    if (u4Size <= BLOCK_WIDTH-SIZE_LENGHT)
    {
        HalFlushDCacheMultipleLine((UPTR)pDest, (USIZE)(u4Size+SIZE_LENGHT));
    }
    else
    {
        HalFlushDCacheMultipleLine((UPTR)pDest, (USIZE)(pTmpDest+u4DestIdx+u4CopySize-pDest));
    }

    return ;
}

//sce capture setting function
void DRVCUST_SetScePixMonCapEnable(BOOL en)
{
	vIO32WriteFldAlign(DBG_CFG_MAIN, en, SCE_CAP_EN);
}

CUST_SCE_CAP_DATA_T* DRVCUST_SetScePixMonPos(CUST_CAP_POS_T* pPos)
{
	//CUST_SCE_CAP_DATA_T CUST_SCE_CAP_DATA;
	
	vIO32WriteFldAlign(POS_MAIN, pPos->u2X, SCE_POS_X);
	vIO32WriteFldAlign(POS_MAIN, pPos->u2Y, SCE_POS_Y);

	DRVCUST_GetScePixMonData(&CUST_SCE_CAP_DATA);

	return &CUST_SCE_CAP_DATA;
}

//sce ink setting function
void DRVCUST_SetScePixMonInkEnable(BOOL en)
{
	vIO32WriteFldAlign(DBG_CFG_MAIN, en, INK_EN);
}

void DRVCUST_SetScePixMonInkColor(CUST_CAP_DATA_T* pData)
{
	vIO32WriteFldAlign(INK_DATA_MAIN, pData->u2Y_G, INK_DATA_Y);
	vIO32WriteFldAlign(INK_DATA_MAIN, pData->u2Cb_B, INK_DATA_CB);
	vIO32WriteFldAlign(INK_DATA_MAIN_CR, pData->u2Cr_R, INK_DATA_CR);
}

// ostg capture setting function
void DRVCUST_SetOstgPixMonCapEnable(BOOL en)
{
	vIO32WriteFldAlign(DUMP_00, en, DUMP_EN);
}

CUST_CAP_DATA_T* DRVCUST_SetOstgPixMonPos(CUST_CAP_POS_T* pPos)
{
	//CUST_CAP_DATA_T CUST_CAP_DATA;
		
	vIO32WriteFldAlign(DUMP_01, pPos->u2X, POS_X);
	vIO32WriteFldAlign(DUMP_01, pPos->u2Y, POS_Y);

	DRVCUST_GetOstgPixMonData(&CUST_CAP_DATA);

	return &CUST_CAP_DATA;
}

//ostg curse setting
void DRVCUST_SetOstgPixMonCurseColor(CUST_CAP_DATA_T* pColor)
{
	vIO32WriteFldAlign(DUMP_02, pColor->u2Y_G, POS_G);
	vIO32WriteFldAlign(DUMP_02, pColor->u2Cr_R, POS_R);
	vIO32WriteFldAlign(DUMP_03, pColor->u2Cb_B, POS_B);
}

void DRVCUST_Set4BandFilterRang(CUST_4BAND_FILTER_RANGE *pData)
{
	if(pData!=NULL)
	{
        x_memcpy(&CUST_4BAND_HIST_FILTER_RANGE, pData, sizeof(CUST_4BAND_FILTER_RANGE));
	}
	else
	{		
        LOG(0, "DRVCUST_Set4BandFilterRang Failed !!!!\n");
	}
	u4BufFlag |= E_CUST_PQ_BUF_4BAND_FREQ_RANGE;
}

void DRVCUST_Set4BandHFilter(CUST_4BAND_H_FILTER *pData)
{
	if(pData!=NULL)
	{
        x_memcpy(&CUST_4BAND_HIST_FILTER, pData, sizeof(CUST_4BAND_H_FILTER));
	}
	else
	{		
        LOG(0, "DRVCUST_Set4BandHFilter Failed !!!!\n");
	}
	u4BufFlag |= E_CUST_PQ_BUF_4BAND_FREQ_FILTER;
}

void DRVCUST_SetOsdPixCountAlphaThresh(UINT8 u1Thresh)
{
	IO_WRITE32MSK(OSD_MIXER_OSTG1, 0, u1Thresh, OSD_MIXER_INDEX_THD_MASK);
    IO_WRITE32MSK(OSD_MIXER_OSTG2, 0, u1Thresh, OSD_MIXER_INDEX_THD_MASK);
}

INT32 DRVCUST_SetColorimetryConvTable(CUST_COL_CONV_TABLE_PARAM_T* pColConvTableParam)
{	
	UINT8 i;
	if(pColConvTableParam==NULL)
	{
		LOG(0, "Err!pColConvTableParam initial Failed !!!!\n");
		return -1;
	}

	if(pColConvTableParam->type>E_MODIFY_BY_MATRIX_COEFFICIENT)
	{
		LOG(0, "Err! type > 2 !!!!\n");
		return -1;
	}
	else if((pColConvTableParam->type==E_MODIFY_BY_CONVERT_PATTERN)||(pColConvTableParam->type==E_MODIFY_BY_MATRIX_COEFFICIENT))
	{
		if(!DRVCUST_SetConTblDFT(pColConvTableParam->input, pColConvTableParam->block, pColConvTableParam->src, pColConvTableParam->dst))
		{
			return -1;
		}
	}
	else if((pColConvTableParam->block==E_MTX_R2Y)&&(pColConvTableParam->type==E_MODIFY_BY_MATRIX_COEFFICIENT))
		{
			LOG(0, "Err! R2Y no need to set param !!!!\n");
			return -1;
		}

	else
	{
          
          }
		x_memcpy(&CUST_COL_CONV_TABLE_PARAM[u1ConvTblParamIDX], pColConvTableParam, sizeof(CUST_COL_CONV_TABLE_PARAM_T));//n is needed to defined
		u1ConvTblParamIDX++;
		
		for(i=0;i<15;i++)
		{
			LOG(0, "CUST_COL_CONV_TABLE_PARAM[%d]=%d !!!!\n",u1ConvTblParamIDX,CUST_COL_CONV_TABLE_PARAM[u1ConvTblParamIDX-1].matrix[i]);
		}
		LOG(0, "u1ConvTblParamIDX=%d !!!!\n",u1ConvTblParamIDX);
		return 0;
	
}
INT32 DRVCUST_SetDolbyConfigData(UPTR u4Offset, UINT32 u4Size)
{	
#ifdef CC_SUPPORT_DOLBY_VISION

	static UINT8 u1Smrt_Pic_DV_IDX = 0;
	
	u1Smrt_Pic_DV_IDX= (~u1Smrt_Pic_DV_IDX)&0x01;
	vDolbySetConfiFile(u1Smrt_Pic_DV_IDX,u4Offset,u4Size);
	LOG(3,"u1Smrt_Pic_DV_IDX=%d,u4Offset=0x%x;u4Size=%d\n",u1Smrt_Pic_DV_IDX,u4Offset,u4Size);
#endif
	return 0;
}

void DRVCUST_RegisterBeExtFunc(SONY_BE_EXT_FUNC_T* pfnBeCb)
{
	if(pfnBeCb)
	{
		sony_be_ext_func = pfnBeCb;
        LOG(2, "Sony Be Ext function registered \n");
	}
	else
	{
		LOG(2, "Sony Be Ext function NULL \n");
	}
}

void DRVCUST_EnSetTnr(UINT8 u1Enable)
{
	//if(IO32ReadFldAlign(TNR_FW_REG_002, TNR_CUST_SET_EN_DEBUG))
	//{
		vIO32WriteFldAlign(TNR_FW_REG_002, u1Enable, TNR_CUST_SET_EN); //monitor
		gU1EnSetTnr = u1Enable;
	//}

}
void DRVCUST_SetTnr(CUST_TNR_BLEND_RATIO* pTnrSet)
{
	if(pTnrSet==NULL)
	{
		LOG(0, "Err! Ptr pTnrSet null !!!!\n");
		return;
	}

	pTnrSet->u1BlendRatioBlky = CLIP(pTnrSet->u1BlendRatioBlky, 0, 31);
	pTnrSet->u1BlendRatioDe = CLIP(pTnrSet->u1BlendRatioDe, 0, 31);
	pTnrSet->u1BlendRatioTxtr = CLIP(pTnrSet->u1BlendRatioTxtr, 0, 31);
	pTnrSet->u1BlendRatioMv = CLIP(pTnrSet->u1BlendRatioMv, 0, 31);
	pTnrSet->u1FltStrMax = CLIP(pTnrSet->u1FltStrMax, 0, 32);

	//if(IO32ReadFldAlign(TNR_FW_REG_002, TNR_CUST_SET_EN_DEBUG))
	//{
		vIO32WriteFldAlign(TNR_FW_REG_001, pTnrSet->u1BlendRatioBlky, TNR_BLEND_RATIO_BLKY);
		vIO32WriteFldAlign(TNR_FW_REG_001, pTnrSet->u1BlendRatioDe, TNR_BLEND_RATIO_DE);
		vIO32WriteFldAlign(TNR_FW_REG_001, pTnrSet->u1BlendRatioTxtr, TNR_BLEND_RATIO_TXTR);
		vIO32WriteFldAlign(TNR_FW_REG_001, pTnrSet->u1BlendRatioMv, TNR_BLEND_RATIO_MV);
		vIO32WriteFldAlign(TNR_FW_REG_002, pTnrSet->u1FltStrMax, TNR_FLT_STR_MAX);
	//}
}

void DRVCUST_SetDemuraTransferSetting(E_CUST_DEMURA_CHANNEL eChannel, BOOL en )
{
	UINT8 u1enCHA, u1enCHB;
	if(eChannel == E_CUST_DEMURA_CHANNEL_A)
	{
		vIO32WriteFldAlign(MISC_CTRL,en, C_QPQE_CHANNEL_SEL_0);
	}
	else if(eChannel == E_CUST_DEMURA_CHANNEL_B)
	{
		vIO32WriteFldAlign(MISC_CTRL, en, C_QPQE_CHANNEL_SEL_1);
	}
	else
	{
		LOG(0, "Err! Channel only support A/B !!!!\n");
	}

	u1enCHA = IO32ReadFldAlign(MISC_CTRL, C_QPQE_CHANNEL_SEL_0);
	u1enCHB = IO32ReadFldAlign(MISC_CTRL, C_QPQE_CHANNEL_SEL_1);
	LOG(0, "[QPQE]Read out Chanel enable A = %d B = %d !!!!\n", u1enCHA, u1enCHB);
}
void DRVCUST_SetPqTdHistConfig(CUST_TDHIST_CONFIG_PARAM_T* pData)
{
	if(pData == NULL)
	{
		return;
	}

	vIO32WriteFldAlign(YSH_3D_HIST_CTRL_0,     pData->ysh_3d_hist_cen,         YSH_3D_HIST_CEN);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_9,   pData->ysh_3d_nonlinear_norm,   YSH_3D_NONLINEAR_NORM);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_9,   pData->ysh_3d_norm_variance,    YSH_3D_NORM_VARIANCE);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_0,   pData->ysh_3d_y_interval[0],    YSH_3D_Y_INTERVAL_0);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_0,   pData->ysh_3d_y_interval[1],    YSH_3D_Y_INTERVAL_1);
	
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_0,   pData->ysh_3d_s_interval[0],    YSH_3D_S_INTERVAL_0);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_1,   pData->ysh_3d_s_interval[1],    YSH_3D_S_INTERVAL_1);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_1,   pData->ysh_3d_s_interval[2],    YSH_3D_S_INTERVAL_2);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_2,   pData->ysh_3d_s_interval[3],    YSH_3D_S_INTERVAL_3);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_2,   pData->ysh_3d_s_interval[4],    YSH_3D_S_INTERVAL_4);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_3,   pData->ysh_3d_s_interval[5],    YSH_3D_S_INTERVAL_5);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_3,   pData->ysh_3d_s_interval[6],    YSH_3D_S_INTERVAL_6);
	
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_4,   pData->ysh_3d_h_interval[0],    YSH_3D_H_INTERVAL_0);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_4,   pData->ysh_3d_h_interval[1],    YSH_3D_H_INTERVAL_1);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_5,   pData->ysh_3d_h_interval[2],    YSH_3D_H_INTERVAL_2);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_5,   pData->ysh_3d_h_interval[3],    YSH_3D_H_INTERVAL_3);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_6,   pData->ysh_3d_h_interval[4],    YSH_3D_H_INTERVAL_4);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_6,   pData->ysh_3d_h_interval[5],    YSH_3D_H_INTERVAL_5);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_7,   pData->ysh_3d_h_interval[6],    YSH_3D_H_INTERVAL_6);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_7,   pData->ysh_3d_h_interval[7],    YSH_3D_H_INTERVAL_7);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_8,   pData->ysh_3d_h_interval[8],    YSH_3D_H_INTERVAL_8);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_8,   pData->ysh_3d_h_interval[9],    YSH_3D_H_INTERVAL_9);
	vIO32WriteFldAlign(YSH_3D_HIST_CONFIG_9,   pData->ysh_3d_h_interval[10],   YSH_3D_H_INTERVAL_10);
	
}

void DRVCUST_SetPqNewPartialSposition(UINT8* u1Point1, UINT8* u1Point2)
{	  
	if ((u1Point1 == NULL)||(u1Point2 == NULL))
	{
		return;
	}
	x_memcpy(u1SceSGainP1, u1Point1, SCE_HUE_SLICE);
	x_memcpy(u1SceSGainP2, u1Point2, SCE_HUE_SLICE);

	
	u4BufFlag |= E_CUST_PQ_BUF_SCE;
	u4BufFlag |= E_CUST_PQ_BUF_PARTIALS_P;
	//LOG(2, "DRVCUST_SetPqNewPartialSposition \n");
}

void DRVCUST_SetGDStrength(UINT8 u1Str)
{
	MAPI_LD_Set_GlobalDimmingStrength(u1Str);
}
void DRVCUST_SetLDStrength(UINT8 u1Str)
{
	MAPI_LD_Set_LocalDimmingStrength(u1Str);
}
void DRVCUST_SetLdCompensationBlend(UINT8 u1Alpha)
{
	MAPI_LD_Set_CompensationBlend(u1Alpha);
}
void DRVCUST_SetLdMeanMaxAlpha(UINT8 u1Alpha)
{
	MAPI_LD_Set_MeanMaxAlpha(u1Alpha);
}
void DRVCUST_SetLdBacklightInGamma(UINT8 u1Type)
{
	MAPI_LD_Set_BacklightInGamma(u1Type);
}
void DRVCUST_SetLdBacklightRemap(UINT8 u1Type)
{
	MAPI_LD_Set_BacklightRemap(u1Type);
}
void DRVCUST_SetLdMinClamp(UINT8 u1MinVal)
{
	MAPI_LD_Set_MinClamp(u1MinVal);
}
void DRVCUST_SetLdSpetialFilterStrength1(UINT8 u1Str)
{
	MAPI_LD_Set_SpetialFilterStrength1(u1Str);
}
void DRVCUST_SetLdSpetialFilterStrength2(UINT8 u1Str)
{
	MAPI_LD_Set_SpetialFilterStrength2(u1Str);
}
void DRVCUST_SetLdSpetialFilterStrength3(UINT8 u1Str)
{
	MAPI_LD_Set_SpetialFilterStrength3(u1Str);
}
void DRVCUST_SetLdSpetialFilterStrength4(UINT8 u1Str)
{
	MAPI_LD_Set_SpetialFilterStrength4(u1Str);
}
void DRVCUST_SetLdSpetialFilterStrength5(UINT8 u1Str)
{
	MAPI_LD_Set_SpetialFilterStrength5(u1Str);
}
void DRVCUST_SetLdTemporalFilterStrengthDn(UINT8 u1Str)
{
	MAPI_LD_Set_TemporalFilterStrengthDn(u1Str);
}
void DRVCUST_SetLdTemporalFilterStrengthUp(UINT8 u1Str)
{
	MAPI_LD_Set_TemporalFilterStrengthUp(u1Str);
}
void DRVCUST_SetLdTemporalFilterLowTh(UINT8 u1Th)
{
	MAPI_LD_Set_TemporalFilterLowTh(u1Th);
}
void DRVCUST_SetLdTemporalFilterHighTh(UINT8 u1Th)
{
	MAPI_LD_Set_TemporalFilterHighTh(u1Th);
}
void DRVCUST_SetLdTemporalFilterMaxSpeed(UINT8 u1Spd)
{
	MAPI_LD_Set_TemporalFilterMaxSpeed(u1Spd);
}
void DRVCUST_SetLDEn(BOOL bEn)
{
	MAPI_LD_En(bEn);
}
void DRVCUST_SetLdSaturationProtection(BOOL bEn, UINT8 u1StartPoint, UINT8 u1FinalGain)
{
	MAPI_LD_Set_Saturation_Protection(bEn, u1StartPoint, u1FinalGain);
}
void DRVCUST_SetLdGroupingStart(BOOL bEn)
{
	MAPI_LD_Set_GroupingStart(bEn);
}
/*void DRVCUST_SetLdGroupingEnd(BOOL bEn)
{
	MAPI_LD_Set_GroupingEnd(bEn);
}*/
void DRVCUST_MAPI_LD_Set_SPI_Output_En(BOOL bEn)
{
    MAPI_LD_Set_SPI_Output_En(bEn);
}


void DRVCUST_SetLED_ControlMode(UINT8 u1Mode)
{
	MAPI_LD_Set_LED_ControlMode(u1Mode);
}
void DRVCUST_SetLED_ControlNum(UINT16 u2Num)
{
	MAPI_LD_Set_LED_ControlNum(u2Num);
}
void DRVCUST_SetLED_Amp(UINT8 u1Amp)
{
	MAPI_LD_Set_LED_Amp(u1Amp);
}
void DRVCUST_SetLDB_Amp(UINT8 u1Amp)
{
	MAPI_LD_Set_LDB_Amp(u1Amp);
}

void DRVCUST_SetLdDynamicAlphaEn(UINT8 u1DynAlphEn)
{
	MAPI_LD_Set_DynamicAlphaEn( u1DynAlphEn);
}

void DRVCUST_SetLdfBlendAlpha(UINT8 u1BlendAlph)
{
	MAPI_LD_Set_LDFBlendAlpha(u1BlendAlph);
}

void DRVCUST_SetLdDynamicAlphaLUT(UINT8 u1Idx, UINT8 u1Val)
{
	MAPI_LD_Set_DynamicAlpha(u1Idx, u1Val);
}



void DRVCUST_SetXvyccRamTable(CUST_XVYCC_DEST_T* pData, UINT16*pRamData, UINT16 u2Size)
{
	UINT16 i;
	if((pData == NULL)||(pRamData == NULL))
	{
		LOG(0,"set DRVCUST_SetXvyccRamTable Pointer Null !! pData = %d pRamData =%d \n ",pData,pRamData);
		return;
	}
	if(u2Size > 4096)
	{
		LOG(0,"set DRVCUST_SetXvyccRamTable Size Err !! u2Size = %d ,need to <=4096 \n ",u2Size);
		return;
	}
	if(pData->block_no == 0) //xvycc1
	{
		if(pData->gamma_type == 0)//gm
		{	
			LOG(0,"//Setting parameter of xvycc1_Gm:\n");
			LOG(0,"0: BT709 gamma (default)\n");
			LOG(0,"1: HDR gamma\n");
			LOG(0,"2: HLG\n");
			LOG(0,"3: old sRGB\n");
			LOG(0,"4: programmable\n");

			for(i=0 ; i<4096 ; i++)
			{
				gbXVYCC1GmProgrmTbl[i] = pRamData[i];
			}
			vDrvxvYCCWriteGmProgrmbTable(gbXVYCC_TBL_SEL.xvycc1_gm,gbXVYCC1GmProgrmTbl);
		}
		else if(pData->gamma_type == 1)//agm
		{
			
			LOG(0,"//Setting parameter of xvycc1_Agm:\n");
			LOG(0,"0: BT709 gamma (default)\n");
			LOG(0,"1: sony HDR (500nits)\n");
			LOG(0,"2: sony HLG\n");
			LOG(0,"3: sony HDR10 (husky new)\n");
			LOG(0,"4: mtk SLD-500 (husky new)\n");
			LOG(0,"5: YT NHK\n");
			LOG(0,"6: BBC HLG\n");
			LOG(0,"7: old sRGB\n");
			LOG(0,"8: programmable\n");
			for(i=0 ; i<4096 ; i++)
			{
				gbXVYCC1AGmProgrmTbl[i] = pRamData[i];
			}
			vDrvxvYCCWriteAgmProgrmbTable(gbXVYCC_TBL_SEL.xvycc1_agm,gbXVYCC1AGmProgrmTbl);
		}
		else
		{
			LOG(0, "Err Gamma  setting , xvYCC0 only GM/AGM->0/1 \n");
		}
	}
	else if(pData->block_no == 1)//xvycc2
	{
		if(pData->gamma_type == 0)//gm
		{
			LOG(0,"//Setting parameter of xvycc2_Gm:\n");
			LOG(0,"0: BT709 gamma (default)\n");
			LOG(0,"1: HDR gamma\n");
			LOG(0,"2: HLG\n");
			LOG(0,"3: old sRGB\n");
			LOG(0,"4: programmable\n");
			
			for(i=0 ; i<4096 ; i++)
			{
				gbXVYCC2GmProgrmTbl[i] = pRamData[i];
			}
			vDrvxvYCC2WriteGmProgrmbTable(gbXVYCC_TBL_SEL.xvycc2_gm,gbXVYCC2GmProgrmTbl);
		}
		else if(pData->gamma_type == 1)//agm
		{
			LOG(0,"//Setting parameter of xvycc2_Agm:\n");
			LOG(0,"0: BT709 gamma (default)\n");
			LOG(0,"1: sony HDR (500nits)\n");
			LOG(0,"2: sony HLG\n");
			LOG(0,"3: sony HDR10 (husky new)\n");
			LOG(0,"4: mtk SLD-500 (husky new)\n");
			LOG(0,"5: YT NHK\n");
			LOG(0,"6: BBC HLG\n");
			LOG(0,"7: old sRGB\n");
			LOG(0,"8: programmable\n");
			for(i=0 ; i<4096 ; i++)
			{
				gbXVYCC2AGmProgrmTbl[i] = pRamData[i];
			}
			vDrvxvYCC2WriteAgmProgrmbTable(gbXVYCC_TBL_SEL.xvycc2_agm,gbXVYCC2AGmProgrmTbl);
		}
		else
		{
			LOG(0, "Err Gamma setting , xvYCC1 only GM/AGM->0/1 \n");
		}
	}
	else
	{
		LOG(0, "Err Block setting , xvYCC only0/1 position \n");
	}
}

void DRVCUST_SetXvyccGammaTableSel(CUST_XVYCC_GAMMA_TABLE_SEL_T *pData)
{
	if(pData == NULL)
	{
		LOG(0,"set DRVCUST_SetXvyccGammaTableSel Pointer Null !! pData = %d\n ",pData);
		return;
	}
	vIO32WriteFldAlign(XVYCC_01, pData->xvycc1_gm, REG_XVYCC_GM_TABLE_SEL);
	vIO32WriteFldAlign(XVYCC_01, pData->xvycc1_agm, REG_XVYCC_AGM_TABLE_SEL);
	vIO32WriteFldAlign(XVYCC_01, pData->xvycc2_gm, REG_XVS_GM_TABLE_SEL);
	vIO32WriteFldAlign(XVYCC_01, pData->xvycc2_agm, REG_XVS_AGM_TABLE_SEL);
	gbXVYCC_TBL_SEL.xvycc1_gm  = pData->xvycc1_gm;
	gbXVYCC_TBL_SEL.xvycc1_agm = pData->xvycc1_agm;
	gbXVYCC_TBL_SEL.xvycc2_gm  = pData->xvycc2_gm;
	gbXVYCC_TBL_SEL.xvycc2_agm = pData->xvycc2_agm;
	LOG(0,"gbXVYCC_TBL_SEL.xvycc1_gm  =%d\n",gbXVYCC_TBL_SEL.xvycc1_gm);
	LOG(0,"gbXVYCC_TBL_SEL.xvycc1_agm =%d\n",gbXVYCC_TBL_SEL.xvycc1_agm);
	LOG(0,"gbXVYCC_TBL_SEL.xvycc2_gm  =%d\n",gbXVYCC_TBL_SEL.xvycc2_gm);
	LOG(0,"gbXVYCC_TBL_SEL.xvycc1_agm =%d\n",gbXVYCC_TBL_SEL.xvycc2_agm);
}

UINT8 DRVCUST_SetRGBSensorParam(CUST_RGB_SENSOR_PARAM_T *pRgbSensorLevel)
{
    if (pRgbSensorLevel == NULL)
    {
        LOG(0, "set DRVCUST_SetRGBSensorParam Pointer Null !! pRgbSensorLevel = %d\n ", pRgbSensorLevel);
        return 1;
    }

    if (E_RGB_SENSOR_TYPE_0 != pRgbSensorLevel->eRgbSensorType)
    {
        LOG(0, "%s() Error: RGB Sensor Param(Type = %d) is not supported!\n", __FUNCTION__, pRgbSensorLevel->eRgbSensorType);
        return 1;
    }

    return CustomSetRGBSensorParam(pRgbSensorLevel->RgbSensorConfig.type0.it, pRgbSensorLevel->RgbSensorConfig.type0.gain1, pRgbSensorLevel->RgbSensorConfig.type0.gain2, pRgbSensorLevel->RgbSensorConfig.type0.hd);
}

void DRVCUST_SetPqSkinLumaHistDetPosition(CUST_SKIN_LUMA_POS_T* pPos)
{
	if(pPos == NULL)
	{
		LOG(0,"Err!! Pointer pPos is Null !\n");
		return ;
	}
	vIO32WriteFldAlign(SKIN_LUMA_CONTRAL_0, pPos->u2X_Start, SKIN_LUMA_HIST_X_START);
	vIO32WriteFldAlign(SKIN_LUMA_CONTRAL_0, pPos->u2X_End,   SKIN_LUMA_HIST_X_END);
	vIO32WriteFldAlign(SKIN_LUMA_CONTRAL_1, pPos->u2Y_Start, SKIN_LUMA_HIST_Y_START);
	vIO32WriteFldAlign(SKIN_LUMA_CONTRAL_1, pPos->u2Y_End,   SKIN_LUMA_HIST_Y_END);
	
}

void DRVCUST_SetPqSkinLumaHistDetThreshold(UINT16 u2Threshold)
{
	u2Threshold = u2Threshold > 511? 511 : u2Threshold; //9 bit only
	vIO32WriteFldAlign(SKIN_LUMA_CONTRAL_2, u2Threshold, SKIN_LUMA_HIST_THRESHOLD);
}

void DRVCUST_SetColorSensorSetting(CUST_COLOR_SENSOR_SETTING_T *pColorSensorSetting)
{
	if(pColorSensorSetting ==NULL)
	{
		LOG(0,"Err!! Pointer in DRVCUST_SetColorSensorSetting is Null !\n");
		return;
	}

	gbColorSensorSetting.eColorSensor      = pColorSensorSetting->eColorSensor;
	gbColorSensorSetting.eColorSensorLight = pColorSensorSetting->eColorSensorLight;
	gbColorSensorSetting.eColorSensorColor = pColorSensorSetting->eColorSensorColor;
	gbColorSensorSetting.eColorSensorGamma = pColorSensorSetting->eColorSensorGamma;
}

void DRVCUST_SetDV_GDLog(UINT8 u1OnOff)
{
	vIO32WriteFldAlign(DOLBY_DEBUG, u1OnOff, DOLBY_DEBUG_GD_LOG);
}

static void _vDrvSetBackLightMute(PFN_PANLE_SET_BACKLIGHT_MUTE_ON_FUNC pfnPanelSetBackLightMuteOnOffFunc)
{
    if(pfnPanelSetBackLightMuteOnOffFunc)
    {
        pfnPanelSetBackLightMuteOnOffFunc();
    }
}

void DRVCUST_SetBacklightMute(UINT8 u1OnOff)
{
    UINT32 gpio, value;
    
    if(DRVCUST_PanelQuery(eBackLightMuteGpio, &gpio) == 0 &&
       DRVCUST_PanelQuery(eBackLightMuteOnVal, &value) == 0)
    {
        PFN_PANLE_SET_BACKLIGHT_MUTE_ON_FUNC pfnPanelSetBackLightMuteOnOffFunc = NULL;
        if(u1OnOff == 1) {/* Backlight Mute On */
            /* Flag control first */
            _vDrvSetBackLightMute((PFN_PANLE_SET_BACKLIGHT_MUTE_ON_FUNC)DRVCUST_InitGetUptr(ePanelSetBackLightMuteOnFunc));
            /* GPIO control later */
            vDrvGpioSet((INT32)gpio, (INT32)value);
        }else{/* Backlight Mute Off */
            /* GPIO control first */
            vDrvGpioSet((INT32)gpio, (INT32)!value);
            /* Flag control later */
            _vDrvSetBackLightMute((PFN_PANLE_SET_BACKLIGHT_MUTE_ON_FUNC)DRVCUST_InitGetUptr(ePanelSetBackLightMuteOffFunc));
        }
        LOG(0,"%s: %d\n", __FUNCTION__, u1OnOff);
    }
}

extern UINT32 FlashPanel_GetVRRMin(void);
extern UINT32 FlashPanel_GetVRRMax(void); 

E_CUST_VSYNC_MODE DRVCUST_TYPE_CONV_AP(E_VRR_SYNC_MODE_TYPE eMode)
{
    E_CUST_VSYNC_MODE eNewMode = E_CUST_VSYNC_MODE_NOT_DIRECT;
    if(eMode == E_VRR_SYNC_MODE_DIRECT)
        eNewMode = E_CUST_VSYNC_MODE_DIRECT;

    return eNewMode;
}

E_VRR_SYNC_MODE_TYPE DRVCUST_TYPE_CONV_DRV(E_CUST_VSYNC_MODE eMode)
{
    E_VRR_SYNC_MODE_TYPE eNewMode = E_VRR_SYNC_MODE_NORMAL;
    if(eMode == E_CUST_VSYNC_MODE_DIRECT)
        eNewMode = E_VRR_SYNC_MODE_DIRECT;

    return eNewMode;
}


INT32 DRVCUST_SetVRRMode(E_CUST_VSYNC_MODE eVsyncMode)
{

#if 0
    if(eVsyncMode == E_CUST_VSYNC_MODE_DIRECT && 
        ((u1FrameRate > FlashPanel_GetVRRMax()) || (u1FrameRate < FlashPanel_GetVRRMin())))
    {
        LOG(0,"Err! not support VRR direct sync mode \n");
        return -1;
    }
#endif

    if(DRVCUST_TYPE_CONV_AP(eVRRGetSyncMode()) != eVsyncMode)
    {
        LOG(0,"[VRR] Ap update direct mode to:%d \n",eVsyncMode);
        vVRRSetSyncMode(DRVCUST_TYPE_CONV_DRV(eVsyncMode));
        
        if(bDrvVideoSignalStatus(SV_VP_MAIN) == (UINT8)SV_VDO_STABLE)
        {
            vVRRModChg(VRR_FLG_SCPIP_MODCHG);
            vSetMainFlg(MAIN_FLG_MODE_CHG);
            vSetMainFlg(MAIN_FLG_MODE_DET_DONE);
        }
        //ePreMode = eVsyncMode;
    }
    return 0;
}

void DRVCUST_SetOpenHdrColorimetryParam(CUST_OPENHDR_COLORIMETRY_T* pHwData)
{
    vDrvSetY2REn(pHwData->y2r_en);
    vDrvSetY2RRoundEn(pHwData->y2r_round_en);
    vDrvSetY2RInputFormat(pHwData->y2r_input_format);
    vDrvSetY2RMatrix(&pHwData->y2r_c00, sizeof(UINT16)*17);
    vDrvSetR2YEn(pHwData->r2y_en);
    vDrvSetR2YRoundEn(pHwData->r2y_round_en);
    vDrvSetR2YInputFormat(pHwData->r2y_input_format);
    vDrvSetR2YMatrix(&pHwData->r2y_c00, sizeof(UINT16)*15);
}

void DRVCUST_SetOpenHdrCscParam(CUST_OPENHDR_CSC_T* pHwData)
{
    UINT32 u4HDRGamutMatrix[15];
    vDrvSetGamutEn(pHwData->gamut_matrix_en);
    x_memcpy(u4HDRGamutMatrix, & pHwData->c00, sizeof(UINT32)*15);
    vDrvHDRSetCustMatrix(u4HDRGamutMatrix);
}

void DRVCUST_SetOpenHdrToneMapParam(CUST_OPENHDR_TONEMAP_REG_T* pHwData, CUST_OPENHDR_TONEMAP_SW_T* pSwData)
{
    TONE_MAP_T tHdrTonemap;
    
    tHdrTonemap.reg_p1  = MIN(pSwData->reg_p1, 524287);
    tHdrTonemap.reg_p2  = MIN(pSwData->reg_p2, 524287);
    tHdrTonemap.reg_p3  = MIN(pSwData->reg_p3, 524287);
    tHdrTonemap.reg_p4  = MIN(pSwData->reg_p4, 524287);
    tHdrTonemap.reg_p5  = MIN(pSwData->reg_p5, 524287);
    tHdrTonemap.reg_p6  = MIN(pSwData->reg_p6, 524287);
    tHdrTonemap.reg_p7  = MIN(pSwData->reg_p7, 524287);
    tHdrTonemap.reg_p8  = MIN(pSwData->reg_p8, 524287);
    tHdrTonemap.reg_p9  = MIN(pSwData->reg_p9, 524287);
    tHdrTonemap.reg_p10 = MIN(pSwData->reg_p10, 524287);
    tHdrTonemap.reg_p11 = MIN(pSwData->reg_p11, 524287);
    tHdrTonemap.reg_p12 = MIN(pSwData->reg_p12, 524287);
    tHdrTonemap.reg_p13 = MIN(pSwData->reg_p13, 524287);
    tHdrTonemap.reg_p14 = MIN(pSwData->reg_p14, 524287);
    tHdrTonemap.reg_p15 = MIN(pSwData->reg_p15, 524287);
    tHdrTonemap.reg_p16 = MIN(pSwData->reg_p16, 524287);
    
    x_memcpy(&tHdrTonemap.reg_slope0, &pSwData->reg_slope0, sizeof(UINT32)*16);
    vDrvSetHDRToneMapParam(&tHdrTonemap, pSwData->act_panel_nit, pSwData->hw_src_nit);
    vDrvSetHDRGainCurve(pSwData->system_gamma_sel);

    vDrvSetHDRLumaGainEn(pHwData->reg_luma_gain_en);
    vDrvSetHDRTonemapEn(pHwData->tone_map_en);
    vDrvSetHDRBypass(pHwData ->c_hdr2sdr_main_bypass_0);    
}

void DRVCUST_SetOpenHdrGammaRamTable(E_CUST_OPENHDR_GAMMA_DEST dest, UINT32* pRamData, UINT16 size)
{
    if (dest == OPENHDR_GAMMA_EOTF)
    {
        if (size  != sizeof(UINT32)* 1024)  //2048 points
        {
            LOG(0, "%s, OPENHDR_GAMMA_EOTF size error!!!\n", __FUNCTION__);
            return;
        }

        vDrvSetHDREOTFCurve(pRamData);
    }
    else if(dest == OPENHDR_GAMMA_OETF)
    {
        if (size  != sizeof(UINT32)* 2048)  //2048 points
        {
            LOG(0, "%s, OPENHDR_GAMMA_OETF size error!!!\n", __FUNCTION__);
            return;
        }
        vDrvSetHDROETFCurve(pRamData);
    }
}

void DRVCUST_GetVRRMode(UINT8 *pVsyncMode)
{
    *pVsyncMode = (UINT8)DRVCUST_TYPE_CONV_AP(eVRRGetSyncMode());
}
