/******************************************************************************
 *
 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
 *                                        
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU 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 the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/

/*============================================================
// include files
============================================================*/

#include "mp_precomp.h"
#include "../phydm_precomp.h"

#if (RTL8822B_SUPPORT == 1)


VOID
phydm_dynamic_switch_htstf_mumimo_8822b(
	IN		PDM_ODM_T		pDM_Odm
	)
{
	/*if rssi > 40dBm, enable HT-STF gain controller, otherwise, if rssi < 40dBm, disable the controller*/
	/*add by Chun-Hung Ho 20160711 */
		if (pDM_Odm->RSSI_Min >= 40)
			ODM_SetBBReg(pDM_Odm, 0x8d8, BIT17, 0x1);
		else if (pDM_Odm->RSSI_Min < 35)
			ODM_SetBBReg(pDM_Odm, 0x8d8, BIT17, 0x0);

		ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("%s, RSSI_Min = %d\n", __func__, pDM_Odm->RSSI_Min));
}		


static
VOID
_setTxACaliValue(
	IN		PDM_ODM_T		pDM_Odm,
	IN		u1Byte	 		eRFPath,
	IN		u1Byte	 		offset,
	IN		u1Byte	 		TxABiaOffset
	)
{
	u4Byte modiTxAValue = 0;
	u1Byte tmp1Byte = 0;
	BOOLEAN bMinus = FALSE;
	u1Byte compValue = 0;
	
	switch(offset)
	{
		case 0x0:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X10124);
			break;
		case 0x1:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X10524);
			break;
		case 0x2:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X10924);
			break;
		case 0x3:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X10D24);
			break;
		case 0x4:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X30164);
			break;
		case 0x5:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X30564);
			break;
		case 0x6:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X30964);
			break;
		case 0x7:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X30D64);
			break;
		case 0x8:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X50195);
			break;
		case 0x9:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X50595);
			break;
		case 0xa:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X50995);
			break;
		case 0xb:
			ODM_SetRFReg(pDM_Odm, eRFPath, 0x18, 0xFFFFF, 0X50D95);
			break;
		default:
			ODM_RT_TRACE(pDM_Odm,ODM_COMP_API,ODM_DBG_TRACE,("Invalid TxA band offset...\n"));
			return;
			break;
	}

	// Get TxA value
	modiTxAValue = ODM_GetRFReg(pDM_Odm,eRFPath, 0x61, 0xFFFFF);	
	tmp1Byte = (u1Byte)modiTxAValue&(BIT3|BIT2|BIT1|BIT0);

	// check how much need to calibration
	switch(TxABiaOffset)
	{
		case 0xF6:
			bMinus = TRUE;
			compValue = 3;
			break;
			
		case 0xF4:
			bMinus = TRUE;
			compValue = 2;
			break;
			
		case 0xF2:
			bMinus = TRUE;
			compValue = 1;
			break;
			
		case 0xF3:
			bMinus = FALSE;
			compValue = 1;
			break;
			
		case 0xF5:
			bMinus = FALSE;
			compValue = 2;	
			break;
			
		case 0xF7:
			bMinus = FALSE;
			compValue = 3;
			break;
			
		case 0xF9:
			bMinus = FALSE;
			compValue = 4;
			break;
		
		// do nothing case
		case 0xF0:
		default:
			ODM_RT_TRACE(pDM_Odm,ODM_COMP_API,ODM_DBG_TRACE,("No need to do TxA bias current calibration\n"));
			return;
			break;
	}

	// calc correct value to calibrate
	if(bMinus)
	{
		if(tmp1Byte >= compValue)
		{
			tmp1Byte -= compValue;
			//modiTxAValue += tmp1Byte;
		}
		else
		{
			tmp1Byte = 0;
		}
	}
	else
	{
		tmp1Byte += compValue;
		if(tmp1Byte >= 7)
		{
			tmp1Byte = 7;
		}
	}

	// Write back to RF reg
	ODM_SetRFReg(pDM_Odm, eRFPath, 0x30, 0xFFFF, (offset<<12|(modiTxAValue&0xFF0)|tmp1Byte));
}


static
VOID
_txaBiasCali4eachPath(
	IN		PDM_ODM_T		pDM_Odm,
	IN		u1Byte	 		eRFPath,
	IN		u1Byte	 		efuseValue
	)
{
	// switch on set TxA bias
	ODM_SetRFReg(pDM_Odm, eRFPath, 0xEF, 0xFFFFF, 0x200);

	// Set 12 sets of TxA value
	_setTxACaliValue(pDM_Odm, eRFPath, 0x0, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x1, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x2, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x3, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x4, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x5, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x6, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x7, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x8, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0x9, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0xa, efuseValue);
	_setTxACaliValue(pDM_Odm, eRFPath, 0xb, efuseValue);

	// switch off set TxA bias
	ODM_SetRFReg(pDM_Odm, eRFPath, 0xEF, 0xFFFFF, 0x0);
}


VOID
phydm_TXCurrentCalibrantion(
		IN		PDM_ODM_T		pDM_Odm
)
{
	u1Byte			efuse0x3D8, efuse0x3D7;
	u4Byte			origRF0x18PathA = 0, origRF0x18PathB = 0;

	// save original 0x18 value
	origRF0x18PathA = ODM_GetRFReg(pDM_Odm,ODM_RF_PATH_A,0x18, 0xFFFFF);
	origRF0x18PathB = ODM_GetRFReg(pDM_Odm,ODM_RF_PATH_B,0x18, 0xFFFFF);

	// define efuse content
	efuse0x3D8 = pDM_Odm->Efuse0x3D8;
	efuse0x3D7 = pDM_Odm->Efuse0x3D7;
	
	// check efuse content to judge whether need to calibration or not
	if(0xFF == efuse0x3D7)
	{
		ODM_RT_TRACE(pDM_Odm,ODM_COMP_API,ODM_DBG_TRACE,("efuse content 0x3D7 == 0xFF, No need to do TxA cali\n"));
		return;
	}

	// write RF register for calibration
	_txaBiasCali4eachPath(pDM_Odm, ODM_RF_PATH_A, efuse0x3D7);
	_txaBiasCali4eachPath(pDM_Odm, ODM_RF_PATH_B, efuse0x3D8);
	

	// restore original 0x18 value
	ODM_SetRFReg(pDM_Odm,ODM_RF_PATH_A,0x18,0xFFFFF, origRF0x18PathA);
	ODM_SetRFReg(pDM_Odm,ODM_RF_PATH_B,0x18,0xFFFFF, origRF0x18PathB);	
	
}


VOID
phydm_hwsetting_8822b(
	IN		PDM_ODM_T		pDM_Odm
	)
{
	phydm_dynamic_switch_htstf_mumimo_8822b(pDM_Odm);
}

#endif	/* RTL8822B_SUPPORT == 1 */

