summaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8723bs/hal/odm_CfoTracking.c')
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_CfoTracking.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
new file mode 100644
index 0000000..9cde6c6
--- /dev/null
+++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
@@ -0,0 +1,338 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+ bool bEEPROMCheck;
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ bEEPROMCheck = (pHalData->EEPROMVersion >= 0x01) ? true : false;
+
+ if (pCfoTrack->CrystalCap == CrystalCap)
+ return;
+
+ pCfoTrack->CrystalCap = CrystalCap;
+
+ /* 0x2C[23:18] = 0x2C[17:12] = CrystalCap */
+ CrystalCap = CrystalCap & 0x3F;
+ PHY_SetBBReg(
+ pDM_Odm->Adapter,
+ REG_MAC_PHY_CTRL,
+ 0x00FFF000,
+ (CrystalCap | (CrystalCap << 6))
+ );
+
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "odm_SetCrystalCap(): CrystalCap = 0x%x\n",
+ CrystalCap
+ )
+ );
+}
+
+static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ u8 CrystalCap = 0x20;
+
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
+
+ CrystalCap = pHalData->CrystalCap;
+
+ CrystalCap = CrystalCap & 0x3f;
+
+ return CrystalCap;
+}
+
+static void odm_SetATCStatus(void *pDM_VOID, bool ATCStatus)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ if (pCfoTrack->bATCStatus == ATCStatus)
+ return;
+
+ PHY_SetBBReg(
+ pDM_Odm->Adapter,
+ ODM_REG(BB_ATC, pDM_Odm),
+ ODM_BIT(BB_ATC, pDM_Odm),
+ ATCStatus
+ );
+ pCfoTrack->bATCStatus = ATCStatus;
+}
+
+static bool odm_GetATCStatus(void *pDM_VOID)
+{
+ bool ATCStatus;
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+
+ ATCStatus = (bool)PHY_QueryBBReg(
+ pDM_Odm->Adapter,
+ ODM_REG(BB_ATC, pDM_Odm),
+ ODM_BIT(BB_ATC, pDM_Odm)
+ );
+ return ATCStatus;
+}
+
+void ODM_CfoTrackingReset(void *pDM_VOID)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ pCfoTrack->DefXCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
+ pCfoTrack->bAdjust = true;
+
+ odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
+ odm_SetATCStatus(pDM_Odm, true);
+}
+
+void ODM_CfoTrackingInit(void *pDM_VOID)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+
+ pCfoTrack->DefXCap =
+ pCfoTrack->CrystalCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
+ pCfoTrack->bATCStatus = odm_GetATCStatus(pDM_Odm);
+ pCfoTrack->bAdjust = true;
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking_init() =========>\n")
+ );
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking_init(): bATCStatus = %d, CrystalCap = 0x%x\n",
+ pCfoTrack->bATCStatus,
+ pCfoTrack->DefXCap
+ )
+ );
+}
+
+void ODM_CfoTracking(void *pDM_VOID)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+ int CFO_kHz_A, CFO_kHz_B, CFO_ave = 0;
+ int CFO_ave_diff;
+ int CrystalCap = (int)pCfoTrack->CrystalCap;
+ u8 Adjust_Xtal = 1;
+
+ /* 4 Support ability */
+ if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) {
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking(): Return: SupportAbility ODM_BB_CFO_TRACKING is disabled\n")
+ );
+ return;
+ }
+
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking() =========>\n")
+ );
+
+ if (!pDM_Odm->bLinked || !pDM_Odm->bOneEntryOnly) {
+ /* 4 No link or more than one entry */
+ ODM_CfoTrackingReset(pDM_Odm);
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking(): Reset: bLinked = %d, bOneEntryOnly = %d\n",
+ pDM_Odm->bLinked,
+ pDM_Odm->bOneEntryOnly
+ )
+ );
+ } else {
+ /* 3 1. CFO Tracking */
+ /* 4 1.1 No new packet */
+ if (pCfoTrack->packetCount == pCfoTrack->packetCount_pre) {
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking(): packet counter doesn't change\n"
+ )
+ );
+ return;
+ }
+ pCfoTrack->packetCount_pre = pCfoTrack->packetCount;
+
+ /* 4 1.2 Calculate CFO */
+ CFO_kHz_A = (int)(pCfoTrack->CFO_tail[0] * 3125) / 1280;
+ CFO_kHz_B = (int)(pCfoTrack->CFO_tail[1] * 3125) / 1280;
+
+ if (pDM_Odm->RFType < ODM_2T2R)
+ CFO_ave = CFO_kHz_A;
+ else
+ CFO_ave = (int)(CFO_kHz_A + CFO_kHz_B) >> 1;
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking(): CFO_kHz_A = %dkHz, CFO_kHz_B = %dkHz, CFO_ave = %dkHz\n",
+ CFO_kHz_A,
+ CFO_kHz_B,
+ CFO_ave
+ )
+ );
+
+ /* 4 1.3 Avoid abnormal large CFO */
+ CFO_ave_diff =
+ (pCfoTrack->CFO_ave_pre >= CFO_ave) ?
+ (pCfoTrack->CFO_ave_pre-CFO_ave) :
+ (CFO_ave-pCfoTrack->CFO_ave_pre);
+
+ if (
+ CFO_ave_diff > 20 &&
+ pCfoTrack->largeCFOHit == 0 &&
+ !pCfoTrack->bAdjust
+ ) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking(): first large CFO hit\n"));
+ pCfoTrack->largeCFOHit = 1;
+ return;
+ } else
+ pCfoTrack->largeCFOHit = 0;
+ pCfoTrack->CFO_ave_pre = CFO_ave;
+
+ /* 4 1.4 Dynamic Xtal threshold */
+ if (pCfoTrack->bAdjust == false) {
+ if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH))
+ pCfoTrack->bAdjust = true;
+ } else {
+ if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW))
+ pCfoTrack->bAdjust = false;
+ }
+
+ /* 4 1.5 BT case: Disable CFO tracking */
+ if (pDM_Odm->bBtEnabled) {
+ pCfoTrack->bAdjust = false;
+ odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking(): Disable CFO tracking for BT!!\n")
+ );
+ }
+
+ /* 4 1.6 Big jump */
+ if (pCfoTrack->bAdjust) {
+ if (CFO_ave > CFO_TH_XTAL_LOW)
+ Adjust_Xtal = Adjust_Xtal+((CFO_ave-CFO_TH_XTAL_LOW)>>2);
+ else if (CFO_ave < (-CFO_TH_XTAL_LOW))
+ Adjust_Xtal = Adjust_Xtal+((CFO_TH_XTAL_LOW-CFO_ave)>>2);
+
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking(): Crystal cap offset = %d\n",
+ Adjust_Xtal
+ )
+ );
+ }
+
+ /* 4 1.7 Adjust Crystal Cap. */
+ if (pCfoTrack->bAdjust) {
+ if (CFO_ave > CFO_TH_XTAL_LOW)
+ CrystalCap = CrystalCap + Adjust_Xtal;
+ else if (CFO_ave < (-CFO_TH_XTAL_LOW))
+ CrystalCap = CrystalCap - Adjust_Xtal;
+
+ if (CrystalCap > 0x3f)
+ CrystalCap = 0x3f;
+ else if (CrystalCap < 0)
+ CrystalCap = 0;
+
+ odm_SetCrystalCap(pDM_Odm, (u8)CrystalCap);
+ }
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ (
+ "ODM_CfoTracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n",
+ pCfoTrack->CrystalCap,
+ pCfoTrack->DefXCap
+ )
+ );
+
+ /* 3 2. Dynamic ATC switch */
+ if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) {
+ odm_SetATCStatus(pDM_Odm, false);
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking(): Disable ATC!!\n")
+ );
+ } else {
+ odm_SetATCStatus(pDM_Odm, true);
+ ODM_RT_TRACE(
+ pDM_Odm,
+ ODM_COMP_CFO_TRACKING,
+ ODM_DBG_LOUD,
+ ("ODM_CfoTracking(): Enable ATC!!\n")
+ );
+ }
+ }
+}
+
+void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail)
+{
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ PODM_PACKET_INFO_T pPktinfo = (PODM_PACKET_INFO_T)pPktinfo_VOID;
+ PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
+ u8 i;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING))
+ return;
+
+ if (pPktinfo->StationID != 0) {
+ /* 3 Update CFO report for path-A & path-B */
+ /* Only paht-A and path-B have CFO tail and short CFO */
+ for (i = ODM_RF_PATH_A; i <= ODM_RF_PATH_B; i++)
+ pCfoTrack->CFO_tail[i] = (int)pcfotail[i];
+
+ /* 3 Update packet counter */
+ if (pCfoTrack->packetCount == 0xffffffff)
+ pCfoTrack->packetCount = 0;
+ else
+ pCfoTrack->packetCount++;
+ }
+}
OpenPOWER on IntegriCloud