blob: a05c8aa53b0e7eb43036780ef4f25da92ca7a1b2 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
*
* Copyright(c) 2007 - 2016 Realtek Corporation.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../mp_precomp.h"
#include "../phydm_precomp.h"
static void phydm_dynamic_switch_htstf_mumimo_8822b(struct phy_dm_struct *dm)
{
/*if rssi > 40dBm, enable HT-STF gain controller,
*otherwise, if rssi < 40dBm, disable the controller
*/
/*add by Chun-Hung Ho 20160711 */
if (dm->rssi_min >= 40)
odm_set_bb_reg(dm, 0x8d8, BIT(17), 0x1);
else if (dm->rssi_min < 35)
odm_set_bb_reg(dm, 0x8d8, BIT(17), 0x0);
ODM_RT_TRACE(dm, ODM_COMP_COMMON, "%s, rssi_min = %d\n", __func__,
dm->rssi_min);
}
static void _set_tx_a_cali_value(struct phy_dm_struct *dm, u8 rf_path,
u8 offset, u8 tx_a_bias_offset)
{
u32 modi_tx_a_value = 0;
u8 tmp1_byte = 0;
bool is_minus = false;
u8 comp_value = 0;
switch (offset) {
case 0x0:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10124);
break;
case 0x1:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10524);
break;
case 0x2:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10924);
break;
case 0x3:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10D24);
break;
case 0x4:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30164);
break;
case 0x5:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30564);
break;
case 0x6:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30964);
break;
case 0x7:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30D64);
break;
case 0x8:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50195);
break;
case 0x9:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50595);
break;
case 0xa:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50995);
break;
case 0xb:
odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50D95);
break;
default:
ODM_RT_TRACE(dm, ODM_COMP_COMMON,
"Invalid TxA band offset...\n");
return;
}
/* Get TxA value */
modi_tx_a_value = odm_get_rf_reg(dm, rf_path, 0x61, 0xFFFFF);
tmp1_byte = (u8)modi_tx_a_value & (BIT(3) | BIT(2) | BIT(1) | BIT(0));
/* check how much need to calibration */
switch (tx_a_bias_offset) {
case 0xF6:
is_minus = true;
comp_value = 3;
break;
case 0xF4:
is_minus = true;
comp_value = 2;
break;
case 0xF2:
is_minus = true;
comp_value = 1;
break;
case 0xF3:
is_minus = false;
comp_value = 1;
break;
case 0xF5:
is_minus = false;
comp_value = 2;
break;
case 0xF7:
is_minus = false;
comp_value = 3;
break;
case 0xF9:
is_minus = false;
comp_value = 4;
break;
/* do nothing case */
case 0xF0:
default:
ODM_RT_TRACE(dm, ODM_COMP_COMMON,
"No need to do TxA bias current calibration\n");
return;
}
/* calc correct value to calibrate */
if (is_minus) {
if (tmp1_byte >= comp_value) {
tmp1_byte -= comp_value;
/*modi_tx_a_value += tmp1_byte;*/
} else {
tmp1_byte = 0;
}
} else {
tmp1_byte += comp_value;
if (tmp1_byte >= 7)
tmp1_byte = 7;
}
/* Write back to RF reg */
odm_set_rf_reg(dm, rf_path, 0x30, 0xFFFF,
(offset << 12 | (modi_tx_a_value & 0xFF0) | tmp1_byte));
}
static void _txa_bias_cali_4_each_path(struct phy_dm_struct *dm, u8 rf_path,
u8 efuse_value)
{
/* switch on set TxA bias */
odm_set_rf_reg(dm, rf_path, 0xEF, 0xFFFFF, 0x200);
/* Set 12 sets of TxA value */
_set_tx_a_cali_value(dm, rf_path, 0x0, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x1, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x2, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x3, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x4, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x5, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x6, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x7, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x8, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0x9, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0xa, efuse_value);
_set_tx_a_cali_value(dm, rf_path, 0xb, efuse_value);
/* switch off set TxA bias */
odm_set_rf_reg(dm, rf_path, 0xEF, 0xFFFFF, 0x0);
}
/*
* for 8822B PCIE D-cut patch only
* Normal driver and MP driver need this patch
*/
void phydm_txcurrentcalibration(struct phy_dm_struct *dm)
{
u8 efuse0x3D8, efuse0x3D7;
u32 orig_rf0x18_path_a = 0, orig_rf0x18_path_b = 0;
/* save original 0x18 value */
orig_rf0x18_path_a = odm_get_rf_reg(dm, ODM_RF_PATH_A, 0x18, 0xFFFFF);
orig_rf0x18_path_b = odm_get_rf_reg(dm, ODM_RF_PATH_B, 0x18, 0xFFFFF);
/* define efuse content */
efuse0x3D8 = dm->efuse0x3d8;
efuse0x3D7 = dm->efuse0x3d7;
/* check efuse content to judge whether need to calibration or not */
if (efuse0x3D7 == 0xFF) {
ODM_RT_TRACE(
dm, ODM_COMP_COMMON,
"efuse content 0x3D7 == 0xFF, No need to do TxA cali\n");
return;
}
/* write RF register for calibration */
_txa_bias_cali_4_each_path(dm, ODM_RF_PATH_A, efuse0x3D7);
_txa_bias_cali_4_each_path(dm, ODM_RF_PATH_B, efuse0x3D8);
/* restore original 0x18 value */
odm_set_rf_reg(dm, ODM_RF_PATH_A, 0x18, 0xFFFFF, orig_rf0x18_path_a);
odm_set_rf_reg(dm, ODM_RF_PATH_B, 0x18, 0xFFFFF, orig_rf0x18_path_b);
}
void phydm_hwsetting_8822b(struct phy_dm_struct *dm)
{
phydm_dynamic_switch_htstf_mumimo_8822b(dm);
}