/* 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 =============================================================================
#include "drv_tdtv_drvif.h"
#include "drv_video.h"
#include "x_gpio.h"
#include "x_pinmux.h"

// === HW INCLUDE =============================================================================

// === DEFINE =============================================================================
// === FUNCTION PROTOTYPE =================================================================

// === EXTERN FUNCTION ====================================================================
#ifdef DRV_USE_EXTERNAL_3D_FRC

#include "panel.h"

EXTERN  void vOSTGSetBorderColor(UINT32 u4VdpId, UINT32 u4RGB);
EXTERN void vOSTGSetBorderParam(UINT32 u4VdpId, UINT32 u4X, UINT32 u4Y, UINT32 u4Width, UINT32 u4Height, UINT32 u4Thickness);
EXTERN void vOSTGSetBorderOnOff(UINT32 u4VdpId, UINT32 u4OnOff);

enum
{
    VDO_2D,
    VDO_3D_FS,
    VDO_3D_SBS,
    VDO_3D_TAB,
    VDO_3D_TTD, 
    VDO_3D_SS
};

EXTERN INT32 drv_extmjc_set_3D_fmt(
     UINT8                u13D_fmt,
     UINT32                u4Para0,
     UINT32                u4Para1,
     UINT8*              pui1_msg_error
     );

EXTERN INT32 drv_extmjc_set_Mode_Change(
     UINT8*              pui1_msg_error
     );
#endif

// === GLOBAL VARIABLE ====================================================================
#ifdef DRV_USE_EXTERNAL_3D_FRC
UINT64 u8VdoPathProcCfgExt[NUM_OF_PACKING_TYPE]=
{
    //2D
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_2D_I,E_TD_OUT_NATIVE), SCL(E_TD_IN_2D_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_2D_P,E_TD_OUT_NATIVE), SCL(E_TD_IN_2D_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //TTD   
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_2D_I,E_TD_OUT_NATIVE), SCL(E_TD_IN_2D_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_2D_P,E_TD_OUT_NATIVE), SCL(E_TD_IN_2D_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //FS  
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_FS_I,E_TDTV_DECODER_OUTPUT_3D_FS  ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_FS_I,E_TD_OUT_NATIVE), SCL(E_TD_IN_FS_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_FS_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_FS_P,E_TD_OUT_3D_FS)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_FS_P,E_TDTV_DECODER_OUTPUT_3D_FS  ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_FS_P,E_TD_OUT_NATIVE), SCL(E_TD_IN_FS_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_FS_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_FS_P,E_TD_OUT_3D_FS)),
    //FP   
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_FP_I,E_TDTV_DECODER_OUTPUT_3D_FS  ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_FS_I,E_TD_OUT_NATIVE), SCL(E_TD_IN_FS_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_FS_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_FS_P,E_TD_OUT_3D_FS)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_FP_P,E_TDTV_DECODER_OUTPUT_3D_FS  ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_FS_P,E_TD_OUT_NATIVE), SCL(E_TD_IN_FS_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_FS_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_FS_P,E_TD_OUT_3D_FS)),
    //TB  
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_TB_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_TB_I,E_TD_OUT_NATIVE), SCL(E_TD_IN_TB_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_TB_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_TB_P,E_TD_OUT_NATIVE), SCL(E_TD_IN_TB_P ,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //SBS
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_SBS_I,E_TDTV_DECODER_OUTPUT_NATIVE),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_SBS_I,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_SBS_P,E_TDTV_DECODER_OUTPUT_NATIVE),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //RD
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_SBS_I,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_2D_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //Sensio
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_SS_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_SS_I,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_I,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_SS_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_SS_P,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //Line Interleave MT5389 Only can handle LI by SCL, no DQC
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_LI_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_I,E_TD_OUT_NATIVE),MIB(E_TD_IN_LI_I ,E_TD_OUT_NATIVE),SCL(E_TD_IN_LI_P ,E_TD_OUT_3D_SBS),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_LI_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MIB(E_TD_IN_LI_P ,E_TD_OUT_NATIVE),SCL(E_TD_IN_LI_P ,E_TD_OUT_3D_SBS),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //Checker Board
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_CB_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_CB_I,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_I,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_CB_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_CB_P,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    //Dot Alternative
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_DA_I,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_DA_I,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_I,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
    TD_TBL_PACK(DEC(E_TDTV_DECODER_INPUT_DA_P,E_TDTV_DECODER_OUTPUT_NATIVE ),DQC(E_TD_IN_DA_P,E_TD_OUT_3D_SBS),MIB(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),SCL(E_TD_IN_SBS_P,E_TD_OUT_NATIVE),TTD(E_TD_IN_2D_P,E_TD_OUT_NATIVE),MJC(E_TD_IN_2D_P,E_TD_OUT_NATIVE)),
};

#endif

// === EXTERN VARIABLE ====================================================================


// === STATIC VARIABLE ====================================================================
// === END OF STATIC VARIABLE =============================================================
// === BODY ===============================================================================
#ifdef DRV_USE_EXTERNAL_3D_FRC

#define IS_INV          0
#define IS_INV_EN       1
#define IS_PROTUDE_EN   2
#define IS_DISTANT_EN   3
#define IS_OSDDEP_EN    4


static UINT8 u13DFrcDepth=16;
static UINT8 u1Vdo3DFmt=VDO_2D;
static UINT8 u1IsInverse=SV_OFF;
static UINT8 u1FrcProtude=2;
static UINT8 u1DistanceFromTV=10;
static UINT8 u1FrcOSDDepth=16;

#define IS_INV                          0
#define IS_INV_EN                       1
#define IS_PROTUDE_DISTANCE_OSDDEP_EN   2


static inline void DRVCUST_SendFrc3DCmd()
{
    UINT8 u1ErrMsg;
    UINT32 u4Para0=u13DFrcDepth;    
    UINT32 u4Para1=(u1FrcOSDDepth<<24)|(u1DistanceFromTV<<16)|(u1FrcProtude<<8) |
        (1<<IS_PROTUDE_DISTANCE_OSDDEP_EN)|(1<<IS_INV_EN)|u1IsInverse;

    drv_extmjc_set_3D_fmt(u1Vdo3DFmt,u4Para0,u4Para1,&u1ErrMsg);
}

VOID DRVCUST_SetExtFrc3DDepth(UINT32 u4Depth)
{
    u13DFrcDepth=(UINT8)u4Depth;    
    DRVCUST_SendFrc3DCmd();
}

VOID DRVCUST_SetExtFrc3DInverse(UINT32 u4IsInverse)
{
    UINT8 u1ErrMsg;
    u1IsInverse=(UINT8)u4IsInverse; 
    DRVCUST_SendFrc3DCmd();
    drv_extmjc_set_Mode_Change(&u1ErrMsg);
}

VOID DRVCUST_SetExtFrcProtrude(UINT32 u4Protrude)
{
    u1FrcProtude=(UINT8)u4Protrude; 
    DRVCUST_SendFrc3DCmd();
}

VOID DRVCUST_SetExtFrcDistanceFromTV(UINT32 u4Distance)
{
    u1DistanceFromTV=(UINT8)u4Distance; 
    DRVCUST_SendFrc3DCmd();
}

VOID DRVCUST_SetExtFrcOSDDepth(UINT32 u4OSDDepth)
{
    u1FrcOSDDepth=(UINT8)u4OSDDepth; 
    DRVCUST_SendFrc3DCmd();
}

VOID DRVCUST_SetExtFrc3DFormat(E_TDTV_UI_3D_PACKING eUIPackingSel)
{

    UINT8 u1ErrMsg;
    static E_TDTV_UI_3D_PACKING ePreFMT=E_TDTV_UI_3D_MODE_END;

    if(bDrvVideoSignalStatus(SV_VP_MAIN)!=SV_VDO_STABLE)
    {
        eUIPackingSel=E_TDTV_UI_3D_MODE_OFF;
    }
    
    if(ePreFMT!=eUIPackingSel)
    {   
        switch(eUIPackingSel)
        {
            case E_TDTV_UI_3D_MODE_FS:
                u1Vdo3DFmt=VDO_3D_FS;
                break;
            case E_TDTV_UI_3D_MODE_SBS:
            case E_TDTV_UI_3D_MODE_RD:     
            case E_TDTV_UI_3D_MODE_SS:
            case E_TDTV_UI_3D_MODE_LI:                
            case E_TDTV_UI_3D_MODE_CB:
            case E_TDTV_UI_3D_MODE_DA:
                u1Vdo3DFmt=VDO_3D_SBS;
                break;
            case E_TDTV_UI_3D_MODE_TB:
                u1Vdo3DFmt=VDO_3D_TAB;
                break;
            case E_TDTV_UI_3D_MODE_TTD:
                u1Vdo3DFmt=VDO_3D_TTD;
                break;              
            default:
                u1Vdo3DFmt=VDO_2D;                
        }

        DRVCUST_SendFrc3DCmd();
        drv_extmjc_set_Mode_Change(&u1ErrMsg);
        ePreFMT=eUIPackingSel;
    }

	UINT32 u4Ext3DEnableGPIO, u4Ext3DLRPin, u4Ext3DLRPinFunc;
    if( (E_TDTV_UI_3D_MODE_OFF!=eUIPackingSel) && 
			bDrvVideoSignalStatus(SV_VP_MAIN)==SV_VDO_STABLE)
	{	
		//Enable 3D Enable Signal
		if (DRVCUST_OptQuery(e3DEnableGPIO,&u4Ext3DEnableGPIO)==0)
		{
			LOG(3, "[3D]3D_EN: GPIO%d output 1\n", u4Ext3DEnableGPIO);
			GPIO_SetOut(u4Ext3DEnableGPIO, 1);	
		}
		//Enable 3D LR Signal
		if ((DRVCUST_OptQuery(e3DLRPin,&u4Ext3DLRPin)==0)&&(DRVCUST_OptQuery(e3DLRPinFunc,&u4Ext3DLRPinFunc)==0))
		{
			LOG(3, "[3D]3D_LR: 0x%x set to FUNCTION%d\n", u4Ext3DLRPin, u4Ext3DLRPinFunc);
			BSP_PinSet(u4Ext3DLRPin, u4Ext3DLRPinFunc);
		}
	}
	else
	{
		//Disable 3D LR Signal
		if (DRVCUST_OptQuery(e3DLRPin,&u4Ext3DLRPin)==0)
		{
			LOG(3, "[3D]3D_LR: 0x%x set to FUNCTION0\n", u4Ext3DLRPin);
			BSP_PinSet(u4Ext3DLRPin, 0);
		}
		//Disable 3D Enable Signal
		if (DRVCUST_OptQuery(e3DEnableGPIO,&u4Ext3DEnableGPIO)==0)
		{
			LOG(3, "[3D]3D_EN: GPIO%d output 0\n", u4Ext3DEnableGPIO);
			GPIO_SetOut(u4Ext3DEnableGPIO, 0);	
		}
	}
}
#endif

#ifdef DRV_USE_EXTERNAL_3D_FRC // MT8283_FLIP_MIRROR
INT32 drv_extmjc_set_flip_mirror(UINT8 u1FlipOnOff, UINT8 u1MirrorOnOff, UINT8* pui1_msg_error);
#include "drv_display.h"

VOID DRVCUST_SetExtFrcFlipMirror(UINT32 u4FlipMirror)
{
    UINT8 u1ErrMsg;
	drv_extmjc_set_flip_mirror((u4FlipMirror&SYS_FLIP_CONFIG_ON)?1:0,
		(u4FlipMirror&SYS_MIRROR_CONFIG_ON)?1:0,
		&u1ErrMsg);
}
#endif


