/* 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.
 *
 *****************************************************************************/


/**
 * @file HDMI customization file for 3:1 passive switch Pericom PI3HDMI1310
 *
 *
 * @author josh.pan@mediatek.com
 */
#ifndef _PI3HDMI1310_HDMI_CONF_C_
#define _PI3HDMI1310_HDMI_CONF_C_

#include "x_gpio.h"
#include "drv_hdmi.h"
#include "x_printf.h"


#include "hw_vdoin.h"
#include "hw_hdmi.h"
#include "hw_ckgen.h"

#include "drv_adcset.h"
#include "drv_video.h"
#include "drv_hdmi.h"

#include "sv_const.h"
#include "source_table.h"


#define HDMI_SWITCH_PI3HDMI1310 1

//Change the following definition for gpio customization
// Hot-plug
#define HDMI_GPIO_HPD1 208 //PAD_HDMI_HPD1
#define HDMI_GPIO_HPD2 219 //PAD_HDMI_HPD2 

// Port select
#define HDMI_SWITCH_SEL0 404
#define HDMI_SWITCH_SEL1 402

#define PWR5V_RX3_OSCL2 22
#define PWR5V_RX4_OSDA2 21

void vHDMIHPDHigh(UINT8 bSwitch)
{
	 switch(bSwitch)
	 {
		  case HDMI_SWITCH_1:	   
		       GPIO_GetIn(HDMI_GPIO_HPD1);
			     break;
			  
		  case HDMI_SWITCH_2:
		  case HDMI_SWITCH_3:
		  case HDMI_SWITCH_4:
		       GPIO_GetIn(HDMI_GPIO_HPD2);
        break;

		  default: /* disable all */
        break;
	 }
}

void vHDMIHPDLow(UINT8 bSwitch)
{
	 INT32 i4Val = 1;

	 switch(bSwitch)
	 {
		  case HDMI_SWITCH_1:
		  		   i4Val = 0;
		       GPIO_Output(HDMI_GPIO_HPD1, &i4Val);
			     break;
			
		  case HDMI_SWITCH_2:
		  case HDMI_SWITCH_3:
		  case HDMI_SWITCH_4:
		       i4Val = 1;
			      GPIO_Output(HDMI_GPIO_HPD2, &i4Val);
			     break;
			
		  default: /* disable all */
			     break;
	 }
}

UINT8 bHDMIPort5VStatus(UINT8 port)
{
 	switch(port)
	 {
	   case HDMI_SWITCH_1: 
	      	return RegReadFldAlign(SRST, PWR5V_RX1);	    
          
	   case HDMI_SWITCH_2:            
	      	return RegReadFldAlign(SRST, PWR5V_RX2);
	      	
    case HDMI_SWITCH_3:            
	      	return GPIO_GetIn(PWR5V_RX3_OSCL2);
      	
    case HDMI_SWITCH_4:            
	      	return GPIO_GetIn(PWR5V_RX4_OSDA2);

		  default: 
			     return 0;
	 }
}

void vHDMISetPI3Hdmi310Switch(UINT8 bSwitch)
{
  INT32 dHigh = 1, dLow = 0;
 
		switch(bSwitch)
		{
			case HDMI_SWITCH_2:
			     GPIO_Output(HDMI_SWITCH_SEL0, &dLow);
			     GPIO_Output(HDMI_SWITCH_SEL1, &dLow);
				   break;
				   
			case HDMI_SWITCH_3:
			     GPIO_Output(HDMI_SWITCH_SEL0, &dLow);
			     GPIO_Output(HDMI_SWITCH_SEL1, &dHigh);
				   break;
				   
			case HDMI_SWITCH_4:
			     GPIO_Output(HDMI_SWITCH_SEL0, &dHigh);
			     GPIO_Output(HDMI_SWITCH_SEL1, &dLow);
				   break;
				   
			default: /* disable all */
			     GPIO_Output(HDMI_SWITCH_SEL0, &dHigh); 
			     GPIO_Output(HDMI_SWITCH_SEL1, &dHigh);
				   break;
		}		
}

#if HDMI_SWITCH_PI3HDMI1310
void vHDMISwitchInit(void)
{
  // set as input        
  GPIO_GetIn(PWR5V_RX3_OSCL2);
  GPIO_GetIn(PWR5V_RX4_OSDA2);	 

  // disable pad pull-up
  #if defined(CC_MT5363)
  vIO32WriteFldAlign(CKGEN_PADPUCFG, 0, FLD_QFP);
  vIO32WriteFldAlign(CKGEN_PADPUCFG, 0, FLD_SIF);
  #endif
}

void vHDMISetSwitch(UINT8 bSwitch)
{

	 if (_bHDMICurrSwitch != bSwitch)
	 {
		  _bHDMICurrSwitch = bSwitch;

		  vHDMIHPDLow(bSwitch);
		  
		  // set internal switch
		  switch(bSwitch)
	   {
			   case HDMI_SWITCH_1:
				       vRegWriteFldAlign(ANA_INTF_2,0x2,RG_HDMI_SW_EN);
				       vRegWriteFldAlign(HDMI_DDC_PAD,0x1,HDMI_DDC_MUX_MASK);
			        vHDMIHPDHigh(HDMI_SWITCH_2);
				      break;
				
		  	 case HDMI_SWITCH_2:
			   case HDMI_SWITCH_3:
			   case HDMI_SWITCH_4:
				       vRegWriteFldAlign(ANA_INTF_2,0x4,RG_HDMI_SW_EN);
				       vRegWriteFldAlign(HDMI_DDC_PAD,0x2,HDMI_DDC_MUX_MASK);
			        vHDMIHPDHigh(HDMI_SWITCH_1);
				      break;
				      
				  default:
				      break;
		  }							
		  
		  // set external switch
		  vHDMISetPI3Hdmi310Switch(bSwitch);
						       
		  #if MUTE_TEMP
		  vHDMIVideoOutOff();
		  #endif
		
		  _bHDMIState = HDMI_STATE_INIT;
	 }
}
#else
void vHDMISwitchInit(void)
{
}
void vHDMISetSwitch(UINT8 bSwitch)
{
}
#endif

#endif
