linux/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 ******************************************************************************/
  15
  16#include "odm_precomp.h"
  17
  18static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap)
  19{
  20        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
  21        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
  22        bool bEEPROMCheck;
  23        struct adapter *Adapter = pDM_Odm->Adapter;
  24        struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
  25
  26        bEEPROMCheck = (pHalData->EEPROMVersion >= 0x01) ? true : false;
  27
  28        if (pCfoTrack->CrystalCap == CrystalCap)
  29                return;
  30
  31        pCfoTrack->CrystalCap = CrystalCap;
  32
  33        /*  0x2C[23:18] = 0x2C[17:12] = CrystalCap */
  34        CrystalCap = CrystalCap & 0x3F;
  35        PHY_SetBBReg(
  36                pDM_Odm->Adapter,
  37                REG_MAC_PHY_CTRL,
  38                0x00FFF000,
  39                (CrystalCap | (CrystalCap << 6))
  40        );
  41
  42        ODM_RT_TRACE(
  43                pDM_Odm,
  44                ODM_COMP_CFO_TRACKING,
  45                ODM_DBG_LOUD,
  46                (
  47                        "odm_SetCrystalCap(): CrystalCap = 0x%x\n",
  48                        CrystalCap
  49                )
  50        );
  51}
  52
  53static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID)
  54{
  55        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
  56        u8 CrystalCap = 0x20;
  57
  58        struct adapter *Adapter = pDM_Odm->Adapter;
  59        struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
  60
  61        CrystalCap = pHalData->CrystalCap;
  62
  63        CrystalCap = CrystalCap & 0x3f;
  64
  65        return CrystalCap;
  66}
  67
  68static void odm_SetATCStatus(void *pDM_VOID, bool ATCStatus)
  69{
  70        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
  71        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
  72
  73        if (pCfoTrack->bATCStatus == ATCStatus)
  74                return;
  75
  76        PHY_SetBBReg(
  77                pDM_Odm->Adapter,
  78                ODM_REG(BB_ATC, pDM_Odm),
  79                ODM_BIT(BB_ATC, pDM_Odm),
  80                ATCStatus
  81        );
  82        pCfoTrack->bATCStatus = ATCStatus;
  83}
  84
  85static bool odm_GetATCStatus(void *pDM_VOID)
  86{
  87        bool ATCStatus;
  88        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
  89
  90        ATCStatus = (bool)PHY_QueryBBReg(
  91                pDM_Odm->Adapter,
  92                ODM_REG(BB_ATC, pDM_Odm),
  93                ODM_BIT(BB_ATC, pDM_Odm)
  94        );
  95        return ATCStatus;
  96}
  97
  98void ODM_CfoTrackingReset(void *pDM_VOID)
  99{
 100        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
 101        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
 102
 103        pCfoTrack->DefXCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
 104        pCfoTrack->bAdjust = true;
 105
 106        odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
 107        odm_SetATCStatus(pDM_Odm, true);
 108}
 109
 110void ODM_CfoTrackingInit(void *pDM_VOID)
 111{
 112        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
 113        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
 114
 115        pCfoTrack->DefXCap =
 116                pCfoTrack->CrystalCap = odm_GetDefaultCrytaltalCap(pDM_Odm);
 117        pCfoTrack->bATCStatus = odm_GetATCStatus(pDM_Odm);
 118        pCfoTrack->bAdjust = true;
 119        ODM_RT_TRACE(
 120                pDM_Odm,
 121                ODM_COMP_CFO_TRACKING,
 122                ODM_DBG_LOUD,
 123                ("ODM_CfoTracking_init() =========>\n")
 124        );
 125        ODM_RT_TRACE(
 126                pDM_Odm,
 127                ODM_COMP_CFO_TRACKING,
 128                ODM_DBG_LOUD,
 129                (
 130                        "ODM_CfoTracking_init(): bATCStatus = %d, CrystalCap = 0x%x\n",
 131                        pCfoTrack->bATCStatus,
 132                        pCfoTrack->DefXCap
 133                )
 134        );
 135}
 136
 137void ODM_CfoTracking(void *pDM_VOID)
 138{
 139        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
 140        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
 141        int CFO_kHz_A, CFO_kHz_B, CFO_ave = 0;
 142        int CFO_ave_diff;
 143        int CrystalCap = (int)pCfoTrack->CrystalCap;
 144        u8 Adjust_Xtal = 1;
 145
 146        /* 4 Support ability */
 147        if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) {
 148                ODM_RT_TRACE(
 149                        pDM_Odm,
 150                        ODM_COMP_CFO_TRACKING,
 151                        ODM_DBG_LOUD,
 152                        ("ODM_CfoTracking(): Return: SupportAbility ODM_BB_CFO_TRACKING is disabled\n")
 153                );
 154                return;
 155        }
 156
 157        ODM_RT_TRACE(
 158                pDM_Odm,
 159                ODM_COMP_CFO_TRACKING,
 160                ODM_DBG_LOUD,
 161                ("ODM_CfoTracking() =========>\n")
 162        );
 163
 164        if (!pDM_Odm->bLinked || !pDM_Odm->bOneEntryOnly) {
 165                /* 4 No link or more than one entry */
 166                ODM_CfoTrackingReset(pDM_Odm);
 167                ODM_RT_TRACE(
 168                        pDM_Odm,
 169                        ODM_COMP_CFO_TRACKING,
 170                        ODM_DBG_LOUD,
 171                        (
 172                                "ODM_CfoTracking(): Reset: bLinked = %d, bOneEntryOnly = %d\n",
 173                                pDM_Odm->bLinked,
 174                                pDM_Odm->bOneEntryOnly
 175                        )
 176                );
 177        } else {
 178                /* 3 1. CFO Tracking */
 179                /* 4 1.1 No new packet */
 180                if (pCfoTrack->packetCount == pCfoTrack->packetCount_pre) {
 181                        ODM_RT_TRACE(
 182                                pDM_Odm,
 183                                ODM_COMP_CFO_TRACKING,
 184                                ODM_DBG_LOUD,
 185                                (
 186                                        "ODM_CfoTracking(): packet counter doesn't change\n"
 187                                )
 188                        );
 189                        return;
 190                }
 191                pCfoTrack->packetCount_pre = pCfoTrack->packetCount;
 192
 193                /* 4 1.2 Calculate CFO */
 194                CFO_kHz_A =  (int)(pCfoTrack->CFO_tail[0] * 3125)  / 1280;
 195                CFO_kHz_B =  (int)(pCfoTrack->CFO_tail[1] * 3125)  / 1280;
 196
 197                if (pDM_Odm->RFType < ODM_2T2R)
 198                        CFO_ave = CFO_kHz_A;
 199                else
 200                        CFO_ave = (int)(CFO_kHz_A + CFO_kHz_B) >> 1;
 201                ODM_RT_TRACE(
 202                        pDM_Odm,
 203                        ODM_COMP_CFO_TRACKING,
 204                        ODM_DBG_LOUD,
 205                        (
 206                                "ODM_CfoTracking(): CFO_kHz_A = %dkHz, CFO_kHz_B = %dkHz, CFO_ave = %dkHz\n",
 207                                CFO_kHz_A,
 208                                CFO_kHz_B,
 209                                CFO_ave
 210                        )
 211                );
 212
 213                /* 4 1.3 Avoid abnormal large CFO */
 214                CFO_ave_diff =
 215                        (pCfoTrack->CFO_ave_pre >= CFO_ave) ?
 216                        (pCfoTrack->CFO_ave_pre-CFO_ave) :
 217                        (CFO_ave-pCfoTrack->CFO_ave_pre);
 218
 219                if (
 220                        CFO_ave_diff > 20 &&
 221                        pCfoTrack->largeCFOHit == 0 &&
 222                        !pCfoTrack->bAdjust
 223                ) {
 224                        ODM_RT_TRACE(pDM_Odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking(): first large CFO hit\n"));
 225                        pCfoTrack->largeCFOHit = 1;
 226                        return;
 227                } else
 228                        pCfoTrack->largeCFOHit = 0;
 229                pCfoTrack->CFO_ave_pre = CFO_ave;
 230
 231                /* 4 1.4 Dynamic Xtal threshold */
 232                if (pCfoTrack->bAdjust == false) {
 233                        if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH))
 234                                pCfoTrack->bAdjust = true;
 235                } else {
 236                        if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW))
 237                                pCfoTrack->bAdjust = false;
 238                }
 239
 240                /* 4 1.5 BT case: Disable CFO tracking */
 241                if (pDM_Odm->bBtEnabled) {
 242                        pCfoTrack->bAdjust = false;
 243                        odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap);
 244                        ODM_RT_TRACE(
 245                                pDM_Odm,
 246                                ODM_COMP_CFO_TRACKING,
 247                                ODM_DBG_LOUD,
 248                                ("ODM_CfoTracking(): Disable CFO tracking for BT!!\n")
 249                        );
 250                }
 251
 252                /* 4 1.6 Big jump */
 253                if (pCfoTrack->bAdjust) {
 254                        if (CFO_ave > CFO_TH_XTAL_LOW)
 255                                Adjust_Xtal = Adjust_Xtal+((CFO_ave-CFO_TH_XTAL_LOW)>>2);
 256                        else if (CFO_ave < (-CFO_TH_XTAL_LOW))
 257                                Adjust_Xtal = Adjust_Xtal+((CFO_TH_XTAL_LOW-CFO_ave)>>2);
 258
 259                        ODM_RT_TRACE(
 260                                pDM_Odm,
 261                                ODM_COMP_CFO_TRACKING,
 262                                ODM_DBG_LOUD,
 263                                (
 264                                        "ODM_CfoTracking(): Crystal cap offset = %d\n",
 265                                        Adjust_Xtal
 266                                )
 267                        );
 268                }
 269
 270                /* 4 1.7 Adjust Crystal Cap. */
 271                if (pCfoTrack->bAdjust) {
 272                        if (CFO_ave > CFO_TH_XTAL_LOW)
 273                                CrystalCap = CrystalCap + Adjust_Xtal;
 274                        else if (CFO_ave < (-CFO_TH_XTAL_LOW))
 275                                CrystalCap = CrystalCap - Adjust_Xtal;
 276
 277                        if (CrystalCap > 0x3f)
 278                                CrystalCap = 0x3f;
 279                        else if (CrystalCap < 0)
 280                                CrystalCap = 0;
 281
 282                        odm_SetCrystalCap(pDM_Odm, (u8)CrystalCap);
 283                }
 284                ODM_RT_TRACE(
 285                        pDM_Odm,
 286                        ODM_COMP_CFO_TRACKING,
 287                        ODM_DBG_LOUD,
 288                        (
 289                                "ODM_CfoTracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n",
 290                                pCfoTrack->CrystalCap,
 291                                pCfoTrack->DefXCap
 292                        )
 293                );
 294
 295                /* 3 2. Dynamic ATC switch */
 296                if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) {
 297                        odm_SetATCStatus(pDM_Odm, false);
 298                        ODM_RT_TRACE(
 299                                pDM_Odm,
 300                                ODM_COMP_CFO_TRACKING,
 301                                ODM_DBG_LOUD,
 302                                ("ODM_CfoTracking(): Disable ATC!!\n")
 303                        );
 304                } else {
 305                        odm_SetATCStatus(pDM_Odm, true);
 306                        ODM_RT_TRACE(
 307                                pDM_Odm,
 308                                ODM_COMP_CFO_TRACKING,
 309                                ODM_DBG_LOUD,
 310                                ("ODM_CfoTracking(): Enable ATC!!\n")
 311                        );
 312                }
 313        }
 314}
 315
 316void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail)
 317{
 318        PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
 319        PODM_PACKET_INFO_T pPktinfo = (PODM_PACKET_INFO_T)pPktinfo_VOID;
 320        PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack;
 321        u8 i;
 322
 323        if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING))
 324                return;
 325
 326        if (pPktinfo->StationID != 0) {
 327                /* 3 Update CFO report for path-A & path-B */
 328                /*  Only paht-A and path-B have CFO tail and short CFO */
 329                for (i = ODM_RF_PATH_A; i <= ODM_RF_PATH_B; i++)
 330                        pCfoTrack->CFO_tail[i] = (int)pcfotail[i];
 331
 332                /* 3 Update packet counter */
 333                if (pCfoTrack->packetCount == 0xffffffff)
 334                        pCfoTrack->packetCount = 0;
 335                else
 336                        pCfoTrack->packetCount++;
 337        }
 338}
 339