// SPDX-License-Identifier: GPL-2.0 /****************************************************************************** * * Copyright(c) 2007 - 2016 Realtek Corporation. * * Contact Information: * wlanfae * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * * Larry Finger * *****************************************************************************/ #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); }