linux/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2010  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../base.h"
   6#include "../pci.h"
   7#include "../core.h"
   8#include "reg.h"
   9#include "def.h"
  10#include "phy.h"
  11#include "dm.h"
  12#include "fw.h"
  13#include "trx.h"
  14#include "../btcoexist/rtl_btc.h"
  15
  16static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = {
  17        0x081, /* 0, -12.0dB */
  18        0x088, /* 1, -11.5dB */
  19        0x090, /* 2, -11.0dB */
  20        0x099, /* 3, -10.5dB */
  21        0x0A2, /* 4, -10.0dB */
  22        0x0AC, /* 5, -9.5dB */
  23        0x0B6, /* 6, -9.0dB */
  24        0x0C0, /* 7, -8.5dB */
  25        0x0CC, /* 8, -8.0dB */
  26        0x0D8, /* 9, -7.5dB */
  27        0x0E5, /* 10, -7.0dB */
  28        0x0F2, /* 11, -6.5dB */
  29        0x101, /* 12, -6.0dB */
  30        0x110, /* 13, -5.5dB */
  31        0x120, /* 14, -5.0dB */
  32        0x131, /* 15, -4.5dB */
  33        0x143, /* 16, -4.0dB */
  34        0x156, /* 17, -3.5dB */
  35        0x16A, /* 18, -3.0dB */
  36        0x180, /* 19, -2.5dB */
  37        0x197, /* 20, -2.0dB */
  38        0x1AF, /* 21, -1.5dB */
  39        0x1C8, /* 22, -1.0dB */
  40        0x1E3, /* 23, -0.5dB */
  41        0x200, /* 24, +0  dB */
  42        0x21E, /* 25, +0.5dB */
  43        0x23E, /* 26, +1.0dB */
  44        0x261, /* 27, +1.5dB */
  45        0x285, /* 28, +2.0dB */
  46        0x2AB, /* 29, +2.5dB */
  47        0x2D3, /* 30, +3.0dB */
  48        0x2FE, /* 31, +3.5dB */
  49        0x32B, /* 32, +4.0dB */
  50        0x35C, /* 33, +4.5dB */
  51        0x38E, /* 34, +5.0dB */
  52        0x3C4, /* 35, +5.5dB */
  53        0x3FE  /* 36, +6.0dB */
  54};
  55
  56static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = {
  57        0x081, /* 0, -12.0dB */
  58        0x088, /* 1, -11.5dB */
  59        0x090, /* 2, -11.0dB */
  60        0x099, /* 3, -10.5dB */
  61        0x0A2, /* 4, -10.0dB */
  62        0x0AC, /* 5, -9.5dB */
  63        0x0B6, /* 6, -9.0dB */
  64        0x0C0, /* 7, -8.5dB */
  65        0x0CC, /* 8, -8.0dB */
  66        0x0D8, /* 9, -7.5dB */
  67        0x0E5, /* 10, -7.0dB */
  68        0x0F2, /* 11, -6.5dB */
  69        0x101, /* 12, -6.0dB */
  70        0x110, /* 13, -5.5dB */
  71        0x120, /* 14, -5.0dB */
  72        0x131, /* 15, -4.5dB */
  73        0x143, /* 16, -4.0dB */
  74        0x156, /* 17, -3.5dB */
  75        0x16A, /* 18, -3.0dB */
  76        0x180, /* 19, -2.5dB */
  77        0x197, /* 20, -2.0dB */
  78        0x1AF, /* 21, -1.5dB */
  79        0x1C8, /* 22, -1.0dB */
  80        0x1E3, /* 23, -0.5dB */
  81        0x200, /* 24, +0  dB */
  82        0x21E, /* 25, +0.5dB */
  83        0x23E, /* 26, +1.0dB */
  84        0x261, /* 27, +1.5dB */
  85        0x285, /* 28, +2.0dB */
  86        0x2AB, /* 29, +2.5dB */
  87        0x2D3, /* 30, +3.0dB */
  88        0x2FE, /* 31, +3.5dB */
  89        0x32B, /* 32, +4.0dB */
  90        0x35C, /* 33, +4.5dB */
  91        0x38E, /* 34, +5.0dB */
  92        0x3C4, /* 35, +5.5dB */
  93        0x3FE  /* 36, +6.0dB */
  94};
  95
  96static const u32 edca_setting_dl[PEER_MAX] = {
  97        0xa44f,         /* 0 UNKNOWN */
  98        0x5ea44f,       /* 1 REALTEK_90 */
  99        0x5e4322,       /* 2 REALTEK_92SE */
 100        0x5ea42b,               /* 3 BROAD      */
 101        0xa44f,         /* 4 RAL */
 102        0xa630,         /* 5 ATH */
 103        0x5ea630,               /* 6 CISCO */
 104        0x5ea42b,               /* 7 MARVELL */
 105};
 106
 107static const u32 edca_setting_ul[PEER_MAX] = {
 108        0x5e4322,       /* 0 UNKNOWN */
 109        0xa44f,         /* 1 REALTEK_90 */
 110        0x5ea44f,       /* 2 REALTEK_92SE */
 111        0x5ea32b,       /* 3 BROAD */
 112        0x5ea422,       /* 4 RAL */
 113        0x5ea322,       /* 5 ATH */
 114        0x3ea430,       /* 6 CISCO */
 115        0x5ea44f,       /* 7 MARV */
 116};
 117
 118static const u8 rtl8818e_delta_swing_table_idx_24gb_p[] = {
 119        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4,
 120        4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9};
 121
 122static const u8 rtl8818e_delta_swing_table_idx_24gb_n[] = {
 123        0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,
 124        7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11};
 125
 126static const u8 rtl8812ae_delta_swing_table_idx_24gb_n[]  = {
 127        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 128        6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 129
 130static const u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = {
 131        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 132        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 133
 134static const u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = {
 135        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 136        6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 137
 138static const u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = {
 139        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 140        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 141
 142static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = {
 143        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 144        6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 145
 146static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = {
 147        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 148        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 149
 150static const u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = {
 151        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 152        6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 153
 154static const u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = {
 155        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 156        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 157
 158static const u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = {
 159        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7,
 160        7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13},
 161        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
 162        7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13},
 163        {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11,
 164        12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18},
 165};
 166
 167static const u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = {
 168        {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8,
 169        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 170        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 171        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 172        {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9,
 173        9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 174};
 175
 176static const u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 177        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 178        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13},
 179        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9,
 180        9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13},
 181        {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11,
 182        12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18},
 183};
 184
 185static const u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 186        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8,
 187        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 188        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 189        9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 190        {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9,
 191        10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 192};
 193
 194static const u8 rtl8821ae_delta_swing_table_idx_24ga_n[]  = {
 195        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 196        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 197
 198static const u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = {
 199        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 200        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 201
 202static const u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = {
 203        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 204        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 205
 206static const u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = {
 207        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 208        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 209
 210static const u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 211        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 212        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 213        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 214        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 215        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 216        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 217};
 218
 219static const u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 220        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 221        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 222        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 223        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 224        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 225        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 226};
 227
 228void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw,
 229                                       u8 type, u8 *pdirection,
 230                                       u32 *poutwrite_val)
 231{
 232        struct rtl_priv *rtlpriv = rtl_priv(hw);
 233        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 234        u8 pwr_val = 0;
 235
 236        if (type == 0) {
 237                if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <=
 238                        rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) {
 239                        *pdirection = 1;
 240                        pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] -
 241                                        rtldm->swing_idx_ofdm[RF90_PATH_A];
 242                } else {
 243                        *pdirection = 2;
 244                        pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] -
 245                                rtldm->swing_idx_ofdm_base[RF90_PATH_A];
 246                }
 247        } else if (type == 1) {
 248                if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) {
 249                        *pdirection = 1;
 250                        pwr_val = rtldm->swing_idx_cck_base -
 251                                        rtldm->swing_idx_cck;
 252                } else {
 253                        *pdirection = 2;
 254                        pwr_val = rtldm->swing_idx_cck -
 255                                rtldm->swing_idx_cck_base;
 256                }
 257        }
 258
 259        if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 260                pwr_val = TXPWRTRACK_MAX_IDX;
 261
 262        *poutwrite_val = pwr_val | (pwr_val << 8)|
 263                                (pwr_val << 16)|
 264                                (pwr_val << 24);
 265}
 266
 267void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw)
 268{
 269        struct rtl_priv *rtlpriv = rtl_priv(hw);
 270        struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 271        struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 272        u8 p = 0;
 273
 274        rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 275        rtldm->swing_idx_cck = rtldm->default_cck_index;
 276        rtldm->cck_index = 0;
 277
 278        for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) {
 279                rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index;
 280                rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index;
 281                rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 282
 283                rtldm->power_index_offset[p] = 0;
 284                rtldm->delta_power_index[p] = 0;
 285                rtldm->delta_power_index_last[p] = 0;
 286                /*Initial Mix mode power tracking*/
 287                rtldm->absolute_ofdm_swing_idx[p] = 0;
 288                rtldm->remnant_ofdm_swing_idx[p] = 0;
 289        }
 290        /*Initial at Modify Tx Scaling Mode*/
 291        rtldm->modify_txagc_flag_path_a = false;
 292        /*Initial at Modify Tx Scaling Mode*/
 293        rtldm->modify_txagc_flag_path_b = false;
 294        rtldm->remnant_cck_idx = 0;
 295        rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 296        rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 297        rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 298}
 299
 300static u8  rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw)
 301{
 302        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 303        u8 i = 0;
 304        u32  bb_swing;
 305
 306        bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype,
 307                                          RF90_PATH_A);
 308
 309        for (i = 0; i < TXSCALE_TABLE_SIZE; ++i)
 310                if (bb_swing == rtl8821ae_txscaling_table[i])
 311                        break;
 312
 313        return i;
 314}
 315
 316void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(
 317                                struct ieee80211_hw *hw)
 318{
 319        struct rtl_priv *rtlpriv = rtl_priv(hw);
 320        struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 321        struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 322        u8 default_swing_index  = 0;
 323        u8 p = 0;
 324
 325        rtlpriv->dm.txpower_track_control = true;
 326        rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 327        rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 328        rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 329        default_swing_index = rtl8821ae_dm_get_swing_index(hw);
 330
 331        rtldm->default_ofdm_index =
 332                (default_swing_index == TXSCALE_TABLE_SIZE) ?
 333                24 : default_swing_index;
 334        rtldm->default_cck_index = 24;
 335
 336        rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 337        rtldm->cck_index = rtldm->default_cck_index;
 338
 339        for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) {
 340                rtldm->swing_idx_ofdm_base[p] =
 341                        rtldm->default_ofdm_index;
 342                rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 343                rtldm->delta_power_index[p] = 0;
 344                rtldm->power_index_offset[p] = 0;
 345                rtldm->delta_power_index_last[p] = 0;
 346        }
 347}
 348
 349void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
 350{
 351        struct rtl_priv *rtlpriv = rtl_priv(hw);
 352
 353        rtlpriv->dm.current_turbo_edca = false;
 354        rtlpriv->dm.is_any_nonbepkts = false;
 355        rtlpriv->dm.is_cur_rdlstate = false;
 356}
 357
 358void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 359{
 360        struct rtl_priv *rtlpriv = rtl_priv(hw);
 361        struct rate_adaptive *p_ra = &rtlpriv->ra;
 362
 363        p_ra->ratr_state = DM_RATR_STA_INIT;
 364        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 365
 366        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 367        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 368                rtlpriv->dm.useramask = true;
 369        else
 370                rtlpriv->dm.useramask = false;
 371
 372        p_ra->high_rssi_thresh_for_ra = 50;
 373        p_ra->low_rssi_thresh_for_ra40m = 20;
 374}
 375
 376static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 377{
 378        struct rtl_priv *rtlpriv = rtl_priv(hw);
 379
 380        rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 381
 382        rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
 383        rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 384}
 385
 386static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw)
 387{
 388        struct rtl_priv *rtlpriv = rtl_priv(hw);
 389        struct rtl_phy *rtlphy = &rtlpriv->phy;
 390        u8 tmp;
 391
 392        rtlphy->cck_high_power =
 393                (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC,
 394                                    ODM_BIT_CCK_RPT_FORMAT_11AC);
 395
 396        tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC,
 397                                ODM_BIT_BB_RX_PATH_11AC);
 398        if (tmp & BIT(0))
 399                rtlpriv->dm.rfpath_rxenable[0] = true;
 400        if (tmp & BIT(1))
 401                rtlpriv->dm.rfpath_rxenable[1] = true;
 402}
 403
 404void rtl8821ae_dm_init(struct ieee80211_hw *hw)
 405{
 406        struct rtl_priv *rtlpriv = rtl_priv(hw);
 407        struct rtl_phy *rtlphy = &rtlpriv->phy;
 408        u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 409
 410        spin_lock(&rtlpriv->locks.iqk_lock);
 411        rtlphy->lck_inprogress = false;
 412        spin_unlock(&rtlpriv->locks.iqk_lock);
 413
 414        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 415        rtl8821ae_dm_common_info_self_init(hw);
 416        rtl_dm_diginit(hw, cur_igvalue);
 417        rtl8821ae_dm_init_rate_adaptive_mask(hw);
 418        rtl8821ae_dm_init_edca_turbo(hw);
 419        rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw);
 420        rtl8821ae_dm_init_dynamic_atc_switch(hw);
 421}
 422
 423static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 424{
 425        struct rtl_priv *rtlpriv = rtl_priv(hw);
 426        struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 427        struct rtl_mac *mac = rtl_mac(rtlpriv);
 428
 429        /* Determine the minimum RSSI  */
 430        if ((mac->link_state < MAC80211_LINKED) &&
 431            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 432                rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 433                pr_debug("rtl8821ae: Not connected to any AP\n");
 434        }
 435        if (mac->link_state >= MAC80211_LINKED) {
 436                if (mac->opmode == NL80211_IFTYPE_AP ||
 437                    mac->opmode == NL80211_IFTYPE_ADHOC) {
 438                        rtl_dm_dig->min_undec_pwdb_for_dm =
 439                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 440                        rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 441                                "AP Client PWDB = 0x%lx\n",
 442                                rtlpriv->dm.entry_min_undec_sm_pwdb);
 443                } else {
 444                        rtl_dm_dig->min_undec_pwdb_for_dm =
 445                            rtlpriv->dm.undec_sm_pwdb;
 446                        rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 447                                "STA Default Port PWDB = 0x%x\n",
 448                                rtl_dm_dig->min_undec_pwdb_for_dm);
 449                }
 450        } else {
 451                rtl_dm_dig->min_undec_pwdb_for_dm =
 452                    rtlpriv->dm.entry_min_undec_sm_pwdb;
 453                rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 454                        "AP Ext Port or disconnect PWDB = 0x%x\n",
 455                        rtl_dm_dig->min_undec_pwdb_for_dm);
 456        }
 457        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 458                "MinUndecoratedPWDBForDM =%d\n",
 459                rtl_dm_dig->min_undec_pwdb_for_dm);
 460}
 461
 462static void  rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw)
 463{
 464        struct rtl_priv *rtlpriv = rtl_priv(hw);
 465
 466        rtl_write_byte(rtlpriv, RA_RSSI_DUMP,
 467                       rtlpriv->stats.rx_rssi_percentage[0]);
 468        rtl_write_byte(rtlpriv, RB_RSSI_DUMP,
 469                       rtlpriv->stats.rx_rssi_percentage[1]);
 470
 471        /* Rx EVM*/
 472        rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP,
 473                       rtlpriv->stats.rx_evm_dbm[0]);
 474        rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP,
 475                       rtlpriv->stats.rx_evm_dbm[1]);
 476
 477        /*Rx SNR*/
 478        rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP,
 479                       (u8)(rtlpriv->stats.rx_snr_db[0]));
 480        rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP,
 481                       (u8)(rtlpriv->stats.rx_snr_db[1]));
 482
 483        /*Rx Cfo_Short*/
 484        rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP,
 485                       rtlpriv->stats.rx_cfo_short[0]);
 486        rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP,
 487                       rtlpriv->stats.rx_cfo_short[1]);
 488
 489        /*Rx Cfo_Tail*/
 490        rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP,
 491                       rtlpriv->stats.rx_cfo_tail[0]);
 492        rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP,
 493                       rtlpriv->stats.rx_cfo_tail[1]);
 494}
 495
 496static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 497{
 498        struct rtl_priv *rtlpriv = rtl_priv(hw);
 499        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 500        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 501        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 502        struct rtl_sta_info *drv_priv;
 503        u8 h2c_parameter[4] = { 0 };
 504        long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 505        u8 stbc_tx = 0;
 506        u64 cur_rxokcnt = 0;
 507        static u64 last_txokcnt = 0, last_rxokcnt;
 508
 509        cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt;
 510        last_txokcnt = rtlpriv->stats.txbytesunicast;
 511        last_rxokcnt = rtlpriv->stats.rxbytesunicast;
 512        if (cur_rxokcnt > (last_txokcnt * 6))
 513                h2c_parameter[3] = 0x01;
 514        else
 515                h2c_parameter[3] = 0x00;
 516
 517        /* AP & ADHOC & MESH */
 518        if (mac->opmode == NL80211_IFTYPE_AP ||
 519            mac->opmode == NL80211_IFTYPE_ADHOC ||
 520            mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 521                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 522                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 523                        if (drv_priv->rssi_stat.undec_sm_pwdb <
 524                                        tmp_entry_min_pwdb)
 525                                tmp_entry_min_pwdb =
 526                                        drv_priv->rssi_stat.undec_sm_pwdb;
 527                        if (drv_priv->rssi_stat.undec_sm_pwdb >
 528                                        tmp_entry_max_pwdb)
 529                                tmp_entry_max_pwdb =
 530                                        drv_priv->rssi_stat.undec_sm_pwdb;
 531                }
 532                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 533
 534                /* If associated entry is found */
 535                if (tmp_entry_max_pwdb != 0) {
 536                        rtlpriv->dm.entry_max_undec_sm_pwdb =
 537                                tmp_entry_max_pwdb;
 538                        RTPRINT(rtlpriv, FDM, DM_PWDB,
 539                                "EntryMaxPWDB = 0x%lx(%ld)\n",
 540                                tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 541                } else {
 542                        rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 543                }
 544                /* If associated entry is found */
 545                if (tmp_entry_min_pwdb != 0xff) {
 546                        rtlpriv->dm.entry_min_undec_sm_pwdb =
 547                                tmp_entry_min_pwdb;
 548                        RTPRINT(rtlpriv, FDM, DM_PWDB,
 549                                "EntryMinPWDB = 0x%lx(%ld)\n",
 550                                tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 551                } else {
 552                        rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 553                }
 554        }
 555        /* Indicate Rx signal strength to FW. */
 556        if (rtlpriv->dm.useramask) {
 557                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
 558                        if (mac->mode == WIRELESS_MODE_AC_24G ||
 559                            mac->mode == WIRELESS_MODE_AC_5G ||
 560                            mac->mode == WIRELESS_MODE_AC_ONLY)
 561                                stbc_tx = (mac->vht_cur_stbc &
 562                                           STBC_VHT_ENABLE_TX) ? 1 : 0;
 563                        else
 564                                stbc_tx = (mac->ht_cur_stbc &
 565                                           STBC_HT_ENABLE_TX) ? 1 : 0;
 566                        h2c_parameter[3] |= stbc_tx << 1;
 567                }
 568                h2c_parameter[2] =
 569                        (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 570                h2c_parameter[1] = 0x20;
 571                h2c_parameter[0] = 0;
 572                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 573                        rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4,
 574                                               h2c_parameter);
 575                else
 576                        rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3,
 577                                               h2c_parameter);
 578        } else {
 579                rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
 580        }
 581        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 582                rtl8812ae_dm_rssi_dump_to_register(hw);
 583        rtl8821ae_dm_find_minimum_rssi(hw);
 584        dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 585}
 586
 587void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca)
 588{
 589        struct rtl_priv *rtlpriv = rtl_priv(hw);
 590        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 591
 592        if (dm_digtable->cur_cck_cca_thres != current_cca)
 593                rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca);
 594
 595        dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
 596        dm_digtable->cur_cck_cca_thres = current_cca;
 597}
 598
 599void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 600{
 601        struct rtl_priv *rtlpriv = rtl_priv(hw);
 602        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 603
 604        if (dm_digtable->stop_dig)
 605                return;
 606
 607        if (dm_digtable->cur_igvalue != current_igi) {
 608                rtl_set_bbreg(hw, DM_REG_IGI_A_11AC,
 609                              DM_BIT_IGI_11AC, current_igi);
 610                if (rtlpriv->phy.rf_type != RF_1T1R)
 611                        rtl_set_bbreg(hw, DM_REG_IGI_B_11AC,
 612                                      DM_BIT_IGI_11AC, current_igi);
 613        }
 614        dm_digtable->cur_igvalue = current_igi;
 615}
 616
 617static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 618{
 619        struct rtl_priv *rtlpriv = rtl_priv(hw);
 620        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 621        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 622        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 623        u8 dig_min_0;
 624        u8 dig_max_of_min;
 625        bool first_connect, first_disconnect;
 626        u8 dm_dig_max, dm_dig_min, offset;
 627        u8 current_igi = dm_digtable->cur_igvalue;
 628
 629        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "\n");
 630
 631        if (mac->act_scanning) {
 632                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 633                        "Return: In Scan Progress\n");
 634                return;
 635        }
 636
 637        /*add by Neil Chen to avoid PSD is processing*/
 638        dig_min_0 = dm_digtable->dig_min_0;
 639        first_connect = (mac->link_state >= MAC80211_LINKED) &&
 640                        (!dm_digtable->media_connect_0);
 641        first_disconnect = (mac->link_state < MAC80211_LINKED) &&
 642                        (dm_digtable->media_connect_0);
 643
 644        /*1 Boundary Decision*/
 645
 646        dm_dig_max = 0x5A;
 647
 648        if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 649                dm_dig_min = DM_DIG_MIN;
 650        else
 651                dm_dig_min = 0x1C;
 652
 653        dig_max_of_min = DM_DIG_MAX_AP;
 654
 655        if (mac->link_state >= MAC80211_LINKED) {
 656                if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 657                        offset = 20;
 658                else
 659                        offset = 10;
 660
 661                if ((dm_digtable->rssi_val_min + offset) > dm_dig_max)
 662                        dm_digtable->rx_gain_max = dm_dig_max;
 663                else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min)
 664                        dm_digtable->rx_gain_max = dm_dig_min;
 665                else
 666                        dm_digtable->rx_gain_max =
 667                                dm_digtable->rssi_val_min + offset;
 668
 669                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 670                        "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x\n",
 671                        dm_digtable->rssi_val_min,
 672                        dm_digtable->rx_gain_max);
 673                if (rtlpriv->dm.one_entry_only) {
 674                        offset = 0;
 675
 676                        if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 677                                dig_min_0 = dm_dig_min;
 678                        else if (dm_digtable->rssi_val_min -
 679                                offset > dig_max_of_min)
 680                                dig_min_0 = dig_max_of_min;
 681                        else
 682                                dig_min_0 =
 683                                        dm_digtable->rssi_val_min - offset;
 684
 685                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 686                                "bOneEntryOnly=TRUE, dig_min_0=0x%x\n",
 687                                dig_min_0);
 688                } else {
 689                        dig_min_0 = dm_dig_min;
 690                }
 691        } else {
 692                dm_digtable->rx_gain_max = dm_dig_max;
 693                dig_min_0 = dm_dig_min;
 694                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
 695        }
 696
 697        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 698                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 699                        "Abnormally false alarm case.\n");
 700
 701                if (dm_digtable->large_fa_hit != 3)
 702                        dm_digtable->large_fa_hit++;
 703                if (dm_digtable->forbidden_igi < current_igi) {
 704                        dm_digtable->forbidden_igi = current_igi;
 705                        dm_digtable->large_fa_hit = 1;
 706                }
 707
 708                if (dm_digtable->large_fa_hit >= 3) {
 709                        if ((dm_digtable->forbidden_igi + 1) >
 710                                dm_digtable->rx_gain_max)
 711                                dm_digtable->rx_gain_min =
 712                                        dm_digtable->rx_gain_max;
 713                        else
 714                                dm_digtable->rx_gain_min =
 715                                        (dm_digtable->forbidden_igi + 1);
 716                        dm_digtable->recover_cnt = 3600;
 717                }
 718        } else {
 719                /*Recovery mechanism for IGI lower bound*/
 720                if (dm_digtable->recover_cnt != 0) {
 721                        dm_digtable->recover_cnt--;
 722                } else {
 723                        if (dm_digtable->large_fa_hit < 3) {
 724                                if ((dm_digtable->forbidden_igi - 1) <
 725                                    dig_min_0) {
 726                                        dm_digtable->forbidden_igi =
 727                                                dig_min_0;
 728                                        dm_digtable->rx_gain_min =
 729                                                dig_min_0;
 730                                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 731                                                "Normal Case: At Lower Bound\n");
 732                                } else {
 733                                        dm_digtable->forbidden_igi--;
 734                                        dm_digtable->rx_gain_min =
 735                                          (dm_digtable->forbidden_igi + 1);
 736                                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 737                                                "Normal Case: Approach Lower Bound\n");
 738                                }
 739                        } else {
 740                                dm_digtable->large_fa_hit = 0;
 741                        }
 742                }
 743        }
 744        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 745                "pDM_DigTable->LargeFAHit=%d\n",
 746                dm_digtable->large_fa_hit);
 747
 748        if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10)
 749                dm_digtable->rx_gain_min = dm_dig_min;
 750
 751        if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 752                dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 753
 754        /*Adjust initial gain by false alarm*/
 755        if (mac->link_state >= MAC80211_LINKED) {
 756                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 757                        "DIG AfterLink\n");
 758                if (first_connect) {
 759                        if (dm_digtable->rssi_val_min <= dig_max_of_min)
 760                                current_igi = dm_digtable->rssi_val_min;
 761                        else
 762                                current_igi = dig_max_of_min;
 763                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 764                                "First Connect\n");
 765                } else {
 766                        if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 767                                current_igi = current_igi + 4;
 768                        else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 769                                current_igi = current_igi + 2;
 770                        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 771                                current_igi = current_igi - 2;
 772
 773                        if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) &&
 774                            (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) {
 775                                current_igi = dm_digtable->rx_gain_min;
 776                                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 777                                        "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n");
 778                        }
 779                }
 780        } else {
 781                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 782                        "DIG BeforeLink\n");
 783                if (first_disconnect) {
 784                        current_igi = dm_digtable->rx_gain_min;
 785                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 786                                "First DisConnect\n");
 787                } else {
 788                        /* 2012.03.30 LukeLee: enable DIG before
 789                         * link but with very high thresholds
 790                         */
 791                        if (rtlpriv->falsealm_cnt.cnt_all > 2000)
 792                                current_igi = current_igi + 4;
 793                        else if (rtlpriv->falsealm_cnt.cnt_all > 600)
 794                                current_igi = current_igi + 2;
 795                        else if (rtlpriv->falsealm_cnt.cnt_all < 300)
 796                                current_igi = current_igi - 2;
 797
 798                        if (current_igi >= 0x3e)
 799                                current_igi = 0x3e;
 800
 801                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
 802                }
 803        }
 804        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 805                "DIG End Adjust IGI\n");
 806        /* Check initial gain by upper/lower bound*/
 807
 808        if (current_igi > dm_digtable->rx_gain_max)
 809                current_igi = dm_digtable->rx_gain_max;
 810        if (current_igi < dm_digtable->rx_gain_min)
 811                current_igi = dm_digtable->rx_gain_min;
 812
 813        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 814                "rx_gain_max=0x%x, rx_gain_min=0x%x\n",
 815                dm_digtable->rx_gain_max, dm_digtable->rx_gain_min);
 816        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 817                "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all);
 818        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 819                "CurIGValue=0x%x\n", current_igi);
 820
 821        rtl8821ae_dm_write_dig(hw, current_igi);
 822        dm_digtable->media_connect_0 =
 823                ((mac->link_state >= MAC80211_LINKED) ? true : false);
 824        dm_digtable->dig_min_0 = dig_min_0;
 825}
 826
 827static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
 828{
 829        struct rtl_priv *rtlpriv = rtl_priv(hw);
 830        u8 cnt = 0;
 831        struct rtl_sta_info *drv_priv;
 832
 833        rtlpriv->dm.tx_rate = 0xff;
 834
 835        rtlpriv->dm.one_entry_only = false;
 836
 837        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
 838            rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
 839                rtlpriv->dm.one_entry_only = true;
 840                return;
 841        }
 842
 843        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
 844            rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
 845            rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
 846                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 847                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list)
 848                        cnt++;
 849                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 850
 851                if (cnt == 1)
 852                        rtlpriv->dm.one_entry_only = true;
 853        }
 854}
 855
 856static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 857{
 858        struct rtl_priv *rtlpriv = rtl_priv(hw);
 859        struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 860        u32 cck_enable = 0;
 861
 862        /*read OFDM FA counter*/
 863        falsealm_cnt->cnt_ofdm_fail =
 864                rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD);
 865        falsealm_cnt->cnt_cck_fail =
 866                rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD);
 867
 868        cck_enable =  rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28));
 869        if (cck_enable)  /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/
 870                falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
 871                                        falsealm_cnt->cnt_cck_fail;
 872        else
 873                falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 874
 875        /*reset OFDM FA coutner*/
 876        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
 877        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
 878        /* reset CCK FA counter*/
 879        rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
 880        rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
 881
 882        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n",
 883                falsealm_cnt->cnt_cck_fail);
 884        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n",
 885                falsealm_cnt->cnt_ofdm_fail);
 886        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n",
 887                falsealm_cnt->cnt_all);
 888}
 889
 890static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
 891                struct ieee80211_hw *hw)
 892{
 893        struct rtl_priv *rtlpriv = rtl_priv(hw);
 894
 895        if (!rtlpriv->dm.tm_trigger) {
 896                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
 897                              BIT(17) | BIT(16), 0x03);
 898                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 899                        "Trigger 8812 Thermal Meter!!\n");
 900                rtlpriv->dm.tm_trigger = 1;
 901                return;
 902        }
 903        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 904                "Schedule TxPowerTracking direct call!!\n");
 905        rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
 906}
 907
 908static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
 909{
 910        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 911        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 912        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 913
 914        if (mac->link_state >= MAC80211_LINKED) {
 915                if (rtldm->linked_interval < 3)
 916                        rtldm->linked_interval++;
 917
 918                if (rtldm->linked_interval == 2) {
 919                        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 920                                rtl8812ae_phy_iq_calibrate(hw, false);
 921                        else
 922                                rtl8821ae_phy_iq_calibrate(hw, false);
 923                }
 924        } else {
 925                rtldm->linked_interval = 0;
 926        }
 927}
 928
 929static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
 930                                            const u8 **up_a,
 931                                            const u8 **down_a,
 932                                            const u8 **up_b,
 933                                            const u8 **down_b)
 934{
 935        struct rtl_priv *rtlpriv = rtl_priv(hw);
 936        struct rtl_phy *rtlphy = &rtlpriv->phy;
 937        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 938        u8 channel = rtlphy->current_channel;
 939        u8 rate = rtldm->tx_rate;
 940
 941        if (1 <= channel && channel <= 14) {
 942                if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
 943                        *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
 944                        *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
 945                        *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
 946                        *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
 947                } else {
 948                        *up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
 949                        *down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
 950                        *up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
 951                        *down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
 952                }
 953        } else if (36 <= channel && channel <= 64) {
 954                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
 955                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
 956                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
 957                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
 958        } else if (100 <= channel && channel <= 140) {
 959                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
 960                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
 961                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
 962                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
 963        } else if (149 <= channel && channel <= 173) {
 964                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
 965                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
 966                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
 967                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
 968        } else {
 969                *up_a = rtl8818e_delta_swing_table_idx_24gb_p;
 970                *down_a = rtl8818e_delta_swing_table_idx_24gb_n;
 971                *up_b = rtl8818e_delta_swing_table_idx_24gb_p;
 972                *down_b = rtl8818e_delta_swing_table_idx_24gb_n;
 973        }
 974}
 975
 976void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
 977{
 978        struct rtl_priv *rtlpriv = rtl_priv(hw);
 979        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
 980        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 981        u8 p = 0;
 982
 983        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 984                "Get C2H Command! Rate=0x%x\n", rate);
 985
 986        rtldm->tx_rate = rate;
 987
 988        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
 989                rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
 990        } else {
 991                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
 992                        rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
 993        }
 994}
 995
 996u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
 997{
 998        struct rtl_priv *rtlpriv = rtl_priv(hw);
 999        u8 ret_rate = MGN_1M;
1000
1001        switch (rate) {
1002        case DESC_RATE1M:
1003                ret_rate = MGN_1M;
1004                break;
1005        case DESC_RATE2M:
1006                ret_rate = MGN_2M;
1007                break;
1008        case DESC_RATE5_5M:
1009                ret_rate = MGN_5_5M;
1010                break;
1011        case DESC_RATE11M:
1012                ret_rate = MGN_11M;
1013                break;
1014        case DESC_RATE6M:
1015                ret_rate = MGN_6M;
1016                break;
1017        case DESC_RATE9M:
1018                ret_rate = MGN_9M;
1019                break;
1020        case DESC_RATE12M:
1021                ret_rate = MGN_12M;
1022                break;
1023        case DESC_RATE18M:
1024                ret_rate = MGN_18M;
1025                break;
1026        case DESC_RATE24M:
1027                ret_rate = MGN_24M;
1028                break;
1029        case DESC_RATE36M:
1030                ret_rate = MGN_36M;
1031                break;
1032        case DESC_RATE48M:
1033                ret_rate = MGN_48M;
1034                break;
1035        case DESC_RATE54M:
1036                ret_rate = MGN_54M;
1037                break;
1038        case DESC_RATEMCS0:
1039                ret_rate = MGN_MCS0;
1040                break;
1041        case DESC_RATEMCS1:
1042                ret_rate = MGN_MCS1;
1043                break;
1044        case DESC_RATEMCS2:
1045                ret_rate = MGN_MCS2;
1046                break;
1047        case DESC_RATEMCS3:
1048                ret_rate = MGN_MCS3;
1049                break;
1050        case DESC_RATEMCS4:
1051                ret_rate = MGN_MCS4;
1052                break;
1053        case DESC_RATEMCS5:
1054                ret_rate = MGN_MCS5;
1055                break;
1056        case DESC_RATEMCS6:
1057                ret_rate = MGN_MCS6;
1058                break;
1059        case DESC_RATEMCS7:
1060                ret_rate = MGN_MCS7;
1061                break;
1062        case DESC_RATEMCS8:
1063                ret_rate = MGN_MCS8;
1064                break;
1065        case DESC_RATEMCS9:
1066                ret_rate = MGN_MCS9;
1067                break;
1068        case DESC_RATEMCS10:
1069                ret_rate = MGN_MCS10;
1070                break;
1071        case DESC_RATEMCS11:
1072                ret_rate = MGN_MCS11;
1073                break;
1074        case DESC_RATEMCS12:
1075                ret_rate = MGN_MCS12;
1076                break;
1077        case DESC_RATEMCS13:
1078                ret_rate = MGN_MCS13;
1079                break;
1080        case DESC_RATEMCS14:
1081                ret_rate = MGN_MCS14;
1082                break;
1083        case DESC_RATEMCS15:
1084                ret_rate = MGN_MCS15;
1085                break;
1086        case DESC_RATEVHT1SS_MCS0:
1087                ret_rate = MGN_VHT1SS_MCS0;
1088                break;
1089        case DESC_RATEVHT1SS_MCS1:
1090                ret_rate = MGN_VHT1SS_MCS1;
1091                break;
1092        case DESC_RATEVHT1SS_MCS2:
1093                ret_rate = MGN_VHT1SS_MCS2;
1094                break;
1095        case DESC_RATEVHT1SS_MCS3:
1096                ret_rate = MGN_VHT1SS_MCS3;
1097                break;
1098        case DESC_RATEVHT1SS_MCS4:
1099                ret_rate = MGN_VHT1SS_MCS4;
1100                break;
1101        case DESC_RATEVHT1SS_MCS5:
1102                ret_rate = MGN_VHT1SS_MCS5;
1103                break;
1104        case DESC_RATEVHT1SS_MCS6:
1105                ret_rate = MGN_VHT1SS_MCS6;
1106                break;
1107        case DESC_RATEVHT1SS_MCS7:
1108                ret_rate = MGN_VHT1SS_MCS7;
1109                break;
1110        case DESC_RATEVHT1SS_MCS8:
1111                ret_rate = MGN_VHT1SS_MCS8;
1112                break;
1113        case DESC_RATEVHT1SS_MCS9:
1114                ret_rate = MGN_VHT1SS_MCS9;
1115                break;
1116        case DESC_RATEVHT2SS_MCS0:
1117                ret_rate = MGN_VHT2SS_MCS0;
1118                break;
1119        case DESC_RATEVHT2SS_MCS1:
1120                ret_rate = MGN_VHT2SS_MCS1;
1121                break;
1122        case DESC_RATEVHT2SS_MCS2:
1123                ret_rate = MGN_VHT2SS_MCS2;
1124                break;
1125        case DESC_RATEVHT2SS_MCS3:
1126                ret_rate = MGN_VHT2SS_MCS3;
1127                break;
1128        case DESC_RATEVHT2SS_MCS4:
1129                ret_rate = MGN_VHT2SS_MCS4;
1130                break;
1131        case DESC_RATEVHT2SS_MCS5:
1132                ret_rate = MGN_VHT2SS_MCS5;
1133                break;
1134        case DESC_RATEVHT2SS_MCS6:
1135                ret_rate = MGN_VHT2SS_MCS6;
1136                break;
1137        case DESC_RATEVHT2SS_MCS7:
1138                ret_rate = MGN_VHT2SS_MCS7;
1139                break;
1140        case DESC_RATEVHT2SS_MCS8:
1141                ret_rate = MGN_VHT2SS_MCS8;
1142                break;
1143        case DESC_RATEVHT2SS_MCS9:
1144                ret_rate = MGN_VHT2SS_MCS9;
1145                break;
1146        default:
1147                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1148                        "HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1149                        rate);
1150                break;
1151        }
1152        return ret_rate;
1153}
1154
1155/*-----------------------------------------------------------------------------
1156 * Function:    odm_TxPwrTrackSetPwr88E()
1157 *
1158 * Overview:    88E change all channel tx power accordign to flag.
1159 *                              OFDM & CCK are all different.
1160 *
1161 * Input:               NONE
1162 *
1163 * Output:              NONE
1164 *
1165 * Return:              NONE
1166 *
1167 * Revised History:
1168 *      When            Who             Remark
1169 *      04/23/2012      MHC             Create Version 0.
1170 *
1171 *---------------------------------------------------------------------------
1172 */
1173void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1174                                      enum pwr_track_control_method method,
1175                                      u8 rf_path, u8 channel_mapped_index)
1176{
1177        struct rtl_priv *rtlpriv = rtl_priv(hw);
1178        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1179        struct rtl_phy *rtlphy = &rtlpriv->phy;
1180        u32 final_swing_idx[2];
1181        u8 pwr_tracking_limit = 26; /*+1.0dB*/
1182        u8 tx_rate = 0xFF;
1183        s8 final_ofdm_swing_index = 0;
1184
1185        if (rtldm->tx_rate != 0xFF)
1186                tx_rate =
1187                        rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1188
1189        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1190                "===>%s\n", __func__);
1191        /*20130429 Mimic Modify High Rate BBSwing Limit.*/
1192        if (tx_rate != 0xFF) {
1193                /*CCK*/
1194                if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1195                        pwr_tracking_limit = 32; /*+4dB*/
1196                /*OFDM*/
1197                else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1198                        pwr_tracking_limit = 30; /*+3dB*/
1199                else if (tx_rate == MGN_54M)
1200                        pwr_tracking_limit = 28; /*+2dB*/
1201                /*HT*/
1202                 /*QPSK/BPSK*/
1203                else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1204                        pwr_tracking_limit = 34; /*+5dB*/
1205                 /*16QAM*/
1206                else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1207                        pwr_tracking_limit = 30; /*+3dB*/
1208                 /*64QAM*/
1209                else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1210                        pwr_tracking_limit = 28; /*+2dB*/
1211                 /*QPSK/BPSK*/
1212                else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1213                        pwr_tracking_limit = 34; /*+5dB*/
1214                 /*16QAM*/
1215                else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1216                        pwr_tracking_limit = 30; /*+3dB*/
1217                 /*64QAM*/
1218                else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1219                        pwr_tracking_limit = 28; /*+2dB*/
1220
1221                /*2 VHT*/
1222                 /*QPSK/BPSK*/
1223                else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1224                         (tx_rate <= MGN_VHT1SS_MCS2))
1225                        pwr_tracking_limit = 34; /*+5dB*/
1226                 /*16QAM*/
1227                else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1228                         (tx_rate <= MGN_VHT1SS_MCS4))
1229                        pwr_tracking_limit = 30; /*+3dB*/
1230                 /*64QAM*/
1231                else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1232                         (tx_rate <= MGN_VHT1SS_MCS6))
1233                        pwr_tracking_limit = 28; /*+2dB*/
1234                else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1235                        pwr_tracking_limit = 26; /*+1dB*/
1236                else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1237                        pwr_tracking_limit = 24; /*+0dB*/
1238                else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1239                        pwr_tracking_limit = 22; /*-1dB*/
1240                 /*QPSK/BPSK*/
1241                else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1242                         (tx_rate <= MGN_VHT2SS_MCS2))
1243                        pwr_tracking_limit = 34; /*+5dB*/
1244                 /*16QAM*/
1245                else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1246                         (tx_rate <= MGN_VHT2SS_MCS4))
1247                        pwr_tracking_limit = 30; /*+3dB*/
1248                 /*64QAM*/
1249                else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1250                         (tx_rate <= MGN_VHT2SS_MCS6))
1251                        pwr_tracking_limit = 28; /*+2dB*/
1252                else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1253                        pwr_tracking_limit = 26; /*+1dB*/
1254                else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1255                        pwr_tracking_limit = 24; /*+0dB*/
1256                else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1257                        pwr_tracking_limit = 22; /*-1dB*/
1258                else
1259                        pwr_tracking_limit = 24;
1260        }
1261        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1262                "TxRate=0x%x, PwrTrackingLimit=%d\n",
1263                tx_rate, pwr_tracking_limit);
1264
1265        if (method == BBSWING) {
1266                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1267                        "===>%s\n", __func__);
1268
1269                if (rf_path == RF90_PATH_A) {
1270                        u32 tmp;
1271
1272                        final_swing_idx[RF90_PATH_A] =
1273                                (rtldm->ofdm_index[RF90_PATH_A] >
1274                                pwr_tracking_limit) ?
1275                                pwr_tracking_limit :
1276                                rtldm->ofdm_index[RF90_PATH_A];
1277                        tmp = final_swing_idx[RF90_PATH_A];
1278                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1279                                "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1280                                rtldm->ofdm_index[RF90_PATH_A],
1281                                final_swing_idx[RF90_PATH_A]);
1282
1283                        rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1284                                      txscaling_tbl[tmp]);
1285                } else {
1286                        u32 tmp;
1287
1288                        final_swing_idx[RF90_PATH_B] =
1289                                rtldm->ofdm_index[RF90_PATH_B] >
1290                                pwr_tracking_limit ?
1291                                pwr_tracking_limit :
1292                                rtldm->ofdm_index[RF90_PATH_B];
1293                        tmp = final_swing_idx[RF90_PATH_B];
1294                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1295                                "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1296                                rtldm->ofdm_index[RF90_PATH_B],
1297                                final_swing_idx[RF90_PATH_B]);
1298
1299                        rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1300                                      txscaling_tbl[tmp]);
1301                }
1302        } else if (method == MIX_MODE) {
1303                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1304                        "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1305                        rtldm->default_ofdm_index,
1306                        rtldm->absolute_ofdm_swing_idx[rf_path],
1307                        rf_path);
1308
1309                final_ofdm_swing_index = rtldm->default_ofdm_index +
1310                                rtldm->absolute_ofdm_swing_idx[rf_path];
1311
1312                if (rf_path == RF90_PATH_A) {
1313                        /*BBSwing higher then Limit*/
1314                        if (final_ofdm_swing_index > pwr_tracking_limit) {
1315                                rtldm->remnant_cck_idx =
1316                                        final_ofdm_swing_index -
1317                                        pwr_tracking_limit;
1318                                /* CCK Follow the same compensation value
1319                                 * as Path A
1320                                 */
1321                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1322                                        final_ofdm_swing_index -
1323                                        pwr_tracking_limit;
1324
1325                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1326                                              txscaling_tbl[pwr_tracking_limit]);
1327
1328                                rtldm->modify_txagc_flag_path_a = true;
1329
1330                                /*Set TxAGC Page C{};*/
1331                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1332                                        rtlphy->current_channel,
1333                                        RF90_PATH_A);
1334
1335                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1336                                        "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1337                                        pwr_tracking_limit,
1338                                        rtldm->remnant_ofdm_swing_idx[rf_path]);
1339                        } else if (final_ofdm_swing_index < 0) {
1340                                rtldm->remnant_cck_idx = final_ofdm_swing_index;
1341                                /* CCK Follow the same compensate value as Path A*/
1342                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1343                                        final_ofdm_swing_index;
1344
1345                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1346                                        txscaling_tbl[0]);
1347
1348                                rtldm->modify_txagc_flag_path_a = true;
1349
1350                                /*Set TxAGC Page C{};*/
1351                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1352                                        rtlphy->current_channel, RF90_PATH_A);
1353
1354                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1355                                        "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1356                                        rtldm->remnant_ofdm_swing_idx[rf_path]);
1357                        } else {
1358                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1359                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
1360
1361                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1362                                        "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1363                                        final_ofdm_swing_index);
1364                                /*If TxAGC has changed, reset TxAGC again*/
1365                                if (rtldm->modify_txagc_flag_path_a) {
1366                                        rtldm->remnant_cck_idx = 0;
1367                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1368
1369                                        /*Set TxAGC Page C{};*/
1370                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
1371                                                rtlphy->current_channel, RF90_PATH_A);
1372                                        rtldm->modify_txagc_flag_path_a = false;
1373
1374                                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
1375                                                DBG_LOUD,
1376                                                "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1377                                }
1378                        }
1379                }
1380                /*BBSwing higher then Limit*/
1381                if (rf_path == RF90_PATH_B) {
1382                        if (final_ofdm_swing_index > pwr_tracking_limit) {
1383                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1384                                        final_ofdm_swing_index -
1385                                        pwr_tracking_limit;
1386
1387                                rtl_set_bbreg(hw, RB_TXSCALE,
1388                                        0xFFE00000,
1389                                        txscaling_tbl[pwr_tracking_limit]);
1390
1391                                rtldm->modify_txagc_flag_path_b = true;
1392
1393                                /*Set TxAGC Page E{};*/
1394                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1395                                        rtlphy->current_channel, RF90_PATH_B);
1396
1397                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1398                                        "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1399                                        pwr_tracking_limit,
1400                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
1401                        } else if (final_ofdm_swing_index < 0) {
1402                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1403                                        final_ofdm_swing_index;
1404
1405                                rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1406                                              txscaling_tbl[0]);
1407
1408                                rtldm->modify_txagc_flag_path_b = true;
1409
1410                                /*Set TxAGC Page E{};*/
1411                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1412                                        rtlphy->current_channel, RF90_PATH_B);
1413
1414                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1415                                        "******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1416                                        rtldm->remnant_ofdm_swing_idx[rf_path]);
1417                        } else {
1418                                rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1419                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
1420
1421                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1422                                        "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1423                                        final_ofdm_swing_index);
1424                                 /*If TxAGC has changed, reset TxAGC again*/
1425                                if (rtldm->modify_txagc_flag_path_b) {
1426                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1427
1428                                        /*Set TxAGC Page E{};*/
1429                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
1430                                        rtlphy->current_channel, RF90_PATH_B);
1431
1432                                        rtldm->modify_txagc_flag_path_b =
1433                                                false;
1434
1435                                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1436                                                "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1437                                }
1438                        }
1439                }
1440        } else {
1441                return;
1442        }
1443}
1444
1445void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1446        struct ieee80211_hw *hw)
1447{
1448        struct rtl_priv *rtlpriv = rtl_priv(hw);
1449        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1450        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1451        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1452        u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1453        u8 thermal_value_avg_count = 0;
1454        u32 thermal_value_avg = 0;
1455        /* OFDM BB Swing should be less than +3.0dB, */
1456        u8 ofdm_min_index = 6;
1457         /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1458        u8 index_for_channel = 0;
1459        /* 1. The following TWO tables decide
1460         * the final index of OFDM/CCK swing table.
1461         */
1462        const u8 *delta_swing_table_idx_tup_a;
1463        const u8 *delta_swing_table_idx_tdown_a;
1464        const u8 *delta_swing_table_idx_tup_b;
1465        const u8 *delta_swing_table_idx_tdown_b;
1466
1467        /*2. Initilization ( 7 steps in total )*/
1468        rtl8812ae_get_delta_swing_table(hw,
1469                &delta_swing_table_idx_tup_a,
1470                &delta_swing_table_idx_tdown_a,
1471                &delta_swing_table_idx_tup_b,
1472                &delta_swing_table_idx_tdown_b);
1473
1474        rtldm->txpower_trackinginit = true;
1475
1476        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1477                "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1478                rtldm->swing_idx_cck_base,
1479                rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1480                rtldm->default_ofdm_index);
1481
1482        thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1483                /*0x42: RF Reg[15:10] 88E*/
1484                RF_T_METER_8812A, 0xfc00);
1485        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1486                "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1487                thermal_value, rtlefuse->eeprom_thermalmeter);
1488        if (!rtldm->txpower_track_control ||
1489            rtlefuse->eeprom_thermalmeter == 0 ||
1490            rtlefuse->eeprom_thermalmeter == 0xFF)
1491                return;
1492
1493        /* 3. Initialize ThermalValues of RFCalibrateInfo*/
1494
1495        if (rtlhal->reloadtxpowerindex)
1496                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1497                        "reload ofdm index for band switch\n");
1498
1499        /*4. Calculate average thermal meter*/
1500        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1501        rtldm->thermalvalue_avg_index++;
1502        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1503                /*Average times =  c.AverageThermalNum*/
1504                rtldm->thermalvalue_avg_index = 0;
1505
1506        for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1507                if (rtldm->thermalvalue_avg[i]) {
1508                        thermal_value_avg += rtldm->thermalvalue_avg[i];
1509                        thermal_value_avg_count++;
1510                }
1511        }
1512        /*Calculate Average ThermalValue after average enough times*/
1513        if (thermal_value_avg_count) {
1514                thermal_value = (u8)(thermal_value_avg /
1515                                thermal_value_avg_count);
1516                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1517                        "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1518                        thermal_value, rtlefuse->eeprom_thermalmeter);
1519        }
1520
1521        /*5. Calculate delta, delta_LCK, delta_IQK.
1522         *"delta" here is used to determine whether
1523         *thermal value changes or not.
1524         */
1525        delta = (thermal_value > rtldm->thermalvalue) ?
1526                (thermal_value - rtldm->thermalvalue) :
1527                (rtldm->thermalvalue - thermal_value);
1528        delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1529                (thermal_value - rtldm->thermalvalue_lck) :
1530                (rtldm->thermalvalue_lck - thermal_value);
1531        delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1532                (thermal_value - rtldm->thermalvalue_iqk) :
1533                (rtldm->thermalvalue_iqk - thermal_value);
1534
1535        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1536                "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1537                delta, delta_lck, delta_iqk);
1538
1539        /* 6. If necessary, do LCK.
1540         * Delta temperature is equal to or larger than 20 centigrade.
1541         */
1542        if (delta_lck >= IQK_THRESHOLD) {
1543                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1544                        "delta_LCK(%d) >= Threshold_IQK(%d)\n",
1545                        delta_lck, IQK_THRESHOLD);
1546                rtldm->thermalvalue_lck = thermal_value;
1547                rtl8821ae_phy_lc_calibrate(hw);
1548        }
1549
1550        /*7. If necessary, move the index of swing table to adjust Tx power.*/
1551
1552        if (delta > 0 && rtldm->txpower_track_control) {
1553                /* "delta" here is used to record the
1554                 * absolute value of differrence.
1555                 */
1556                delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1557                        (thermal_value - rtlefuse->eeprom_thermalmeter) :
1558                        (rtlefuse->eeprom_thermalmeter - thermal_value);
1559
1560                if (delta >= TXPWR_TRACK_TABLE_SIZE)
1561                        delta = TXPWR_TRACK_TABLE_SIZE - 1;
1562
1563                /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1564
1565                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1566                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1567                                "delta_swing_table_idx_tup_a[%d] = %d\n",
1568                                delta, delta_swing_table_idx_tup_a[delta]);
1569                        rtldm->delta_power_index_last[RF90_PATH_A] =
1570                                rtldm->delta_power_index[RF90_PATH_A];
1571                        rtldm->delta_power_index[RF90_PATH_A] =
1572                                delta_swing_table_idx_tup_a[delta];
1573
1574                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1575                                delta_swing_table_idx_tup_a[delta];
1576                        /*Record delta swing for mix mode power tracking*/
1577
1578                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1579                                "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1580                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1581
1582                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1583                                "delta_swing_table_idx_tup_b[%d] = %d\n",
1584                                delta, delta_swing_table_idx_tup_b[delta]);
1585                        rtldm->delta_power_index_last[RF90_PATH_B] =
1586                                rtldm->delta_power_index[RF90_PATH_B];
1587                        rtldm->delta_power_index[RF90_PATH_B] =
1588                                delta_swing_table_idx_tup_b[delta];
1589
1590                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1591                                delta_swing_table_idx_tup_b[delta];
1592                        /*Record delta swing for mix mode power tracking*/
1593
1594                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1595                                "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1596                                rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1597                } else {
1598                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1599                                "delta_swing_table_idx_tdown_a[%d] = %d\n",
1600                                delta, delta_swing_table_idx_tdown_a[delta]);
1601
1602                        rtldm->delta_power_index_last[RF90_PATH_A] =
1603                                rtldm->delta_power_index[RF90_PATH_A];
1604                        rtldm->delta_power_index[RF90_PATH_A] =
1605                                -1 * delta_swing_table_idx_tdown_a[delta];
1606
1607                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1608                                -1 * delta_swing_table_idx_tdown_a[delta];
1609                        /* Record delta swing for mix mode power tracking*/
1610                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1611                                "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1612                                rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1613
1614                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1615                                "deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1616                                delta, delta_swing_table_idx_tdown_b[delta]);
1617
1618                        rtldm->delta_power_index_last[RF90_PATH_B] =
1619                                rtldm->delta_power_index[RF90_PATH_B];
1620                        rtldm->delta_power_index[RF90_PATH_B] =
1621                                -1 * delta_swing_table_idx_tdown_b[delta];
1622
1623                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1624                                -1 * delta_swing_table_idx_tdown_b[delta];
1625                        /*Record delta swing for mix mode power tracking*/
1626
1627                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1628                                "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1629                                rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1630                }
1631
1632                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1633                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1634                                "============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1635                                (p == RF90_PATH_A ? 'A' : 'B'));
1636
1637                        if (rtldm->delta_power_index[p] ==
1638                                rtldm->delta_power_index_last[p])
1639                                /*If Thermal value changes but lookup
1640                                table value still the same*/
1641                                rtldm->power_index_offset[p] = 0;
1642                        else
1643                                rtldm->power_index_offset[p] =
1644                                        rtldm->delta_power_index[p] -
1645                                        rtldm->delta_power_index_last[p];
1646                                /* Power Index Diff between 2
1647                                 * times Power Tracking
1648                                 */
1649                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1650                                "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1651                                (p == RF90_PATH_A ? 'A' : 'B'),
1652                                rtldm->power_index_offset[p],
1653                                rtldm->delta_power_index[p],
1654                                rtldm->delta_power_index_last[p]);
1655
1656                        rtldm->ofdm_index[p] =
1657                                        rtldm->swing_idx_ofdm_base[p] +
1658                                        rtldm->power_index_offset[p];
1659                        rtldm->cck_index =
1660                                        rtldm->swing_idx_cck_base +
1661                                        rtldm->power_index_offset[p];
1662
1663                        rtldm->swing_idx_cck = rtldm->cck_index;
1664                        rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1665
1666                        /****Print BB Swing Base and Index Offset */
1667
1668                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1669                                "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1670                                rtldm->swing_idx_cck,
1671                                rtldm->swing_idx_cck_base,
1672                                rtldm->power_index_offset[p]);
1673                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1674                                "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1675                                rtldm->swing_idx_ofdm[p],
1676                                (p == RF90_PATH_A ? 'A' : 'B'),
1677                                rtldm->swing_idx_ofdm_base[p],
1678                                rtldm->power_index_offset[p]);
1679
1680                        /*7.1 Handle boundary conditions of index.*/
1681
1682                        if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1683                                rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1684                        else if (rtldm->ofdm_index[p] < ofdm_min_index)
1685                                rtldm->ofdm_index[p] = ofdm_min_index;
1686                }
1687                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1688                        "\n\n====================================================================================\n");
1689                if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1690                        rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1691                else if (rtldm->cck_index < 0)
1692                        rtldm->cck_index = 0;
1693        } else {
1694                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1695                        "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1696                        rtldm->txpower_track_control,
1697                        thermal_value,
1698                        rtldm->thermalvalue);
1699
1700                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1701                        rtldm->power_index_offset[p] = 0;
1702        }
1703        /*Print Swing base & current*/
1704        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1705                "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1706                rtldm->cck_index, rtldm->swing_idx_cck_base);
1707        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1708                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1709                        "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1710                        rtldm->ofdm_index[p],
1711                        (p == RF90_PATH_A ? 'A' : 'B'),
1712                        rtldm->swing_idx_ofdm_base[p]);
1713        }
1714
1715        if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1716                rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1717                rtldm->txpower_track_control) {
1718                /*7.2 Configure the Swing Table to adjust Tx Power.
1719                 *Always TRUE after Tx Power is adjusted by power tracking.
1720                 *
1721                 *2012/04/23 MH According to Luke's suggestion,
1722                 *we can not write BB digital
1723                 *to increase TX power. Otherwise, EVM will be bad.
1724                 *
1725                 *2012/04/25 MH Add for tx power tracking to set
1726                 *tx power in tx agc for 88E.
1727                 */
1728                if (thermal_value > rtldm->thermalvalue) {
1729                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1730                                "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1731                                rtldm->power_index_offset[RF90_PATH_A],
1732                                delta, thermal_value,
1733                                rtlefuse->eeprom_thermalmeter,
1734                                rtldm->thermalvalue);
1735
1736                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1737                                "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1738                                rtldm->power_index_offset[RF90_PATH_B],
1739                                delta, thermal_value,
1740                                rtlefuse->eeprom_thermalmeter,
1741                                rtldm->thermalvalue);
1742                } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1743                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1744                                "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1745                                rtldm->power_index_offset[RF90_PATH_A],
1746                                delta, thermal_value,
1747                                rtlefuse->eeprom_thermalmeter,
1748                                rtldm->thermalvalue);
1749
1750                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1751                                "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1752                                rtldm->power_index_offset[RF90_PATH_B],
1753                                delta, thermal_value,
1754                                rtlefuse->eeprom_thermalmeter,
1755                                rtldm->thermalvalue);
1756                }
1757
1758                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1759                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1760                                "Temperature(%d) higher than PG value(%d)\n",
1761                                thermal_value, rtlefuse->eeprom_thermalmeter);
1762
1763                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1764                                "**********Enter POWER Tracking MIX_MODE**********\n");
1765                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1766                                rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1767                                                                 p, 0);
1768                } else {
1769                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1770                                "Temperature(%d) lower than PG value(%d)\n",
1771                                thermal_value, rtlefuse->eeprom_thermalmeter);
1772
1773                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1774                                "**********Enter POWER Tracking MIX_MODE**********\n");
1775                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1776                                rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1777                                                                 p, index_for_channel);
1778                }
1779                /*Record last time Power Tracking result as base.*/
1780                rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1781                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1782                                rtldm->swing_idx_ofdm_base[p] =
1783                                        rtldm->swing_idx_ofdm[p];
1784
1785                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1786                        "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1787                        rtldm->thermalvalue, thermal_value);
1788                /*Record last Power Tracking Thermal Value*/
1789                rtldm->thermalvalue = thermal_value;
1790        }
1791        /*Delta temperature is equal to or larger than
1792        20 centigrade (When threshold is 8).*/
1793        if (delta_iqk >= IQK_THRESHOLD)
1794                rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1795
1796        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1797                "<===%s\n", __func__);
1798}
1799
1800static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw,
1801                                            const u8 **up_a,
1802                                            const u8 **down_a)
1803{
1804        struct rtl_priv *rtlpriv = rtl_priv(hw);
1805        struct rtl_phy *rtlphy = &rtlpriv->phy;
1806        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1807        u8 channel = rtlphy->current_channel;
1808        u8 rate = rtldm->tx_rate;
1809
1810        if (1 <= channel && channel <= 14) {
1811                if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1812                        *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1813                        *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1814                } else {
1815                        *up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1816                        *down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1817                }
1818        } else if (36 <= channel && channel <= 64) {
1819                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
1820                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
1821        } else if (100 <= channel && channel <= 140) {
1822                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
1823                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
1824        } else if (149 <= channel && channel <= 173) {
1825                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
1826                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
1827        } else {
1828                *up_a = rtl8818e_delta_swing_table_idx_24gb_p;
1829                *down_a = rtl8818e_delta_swing_table_idx_24gb_n;
1830        }
1831        return;
1832}
1833
1834/*-----------------------------------------------------------------------------
1835 * Function:    odm_TxPwrTrackSetPwr88E()
1836 *
1837 * Overview:    88E change all channel tx power accordign to flag.
1838 *                              OFDM & CCK are all different.
1839 *
1840 * Input:               NONE
1841 *
1842 * Output:              NONE
1843 *
1844 * Return:              NONE
1845 *
1846 * Revised History:
1847 *      When            Who             Remark
1848 *      04/23/2012      MHC             Create Version 0.
1849 *
1850 *---------------------------------------------------------------------------
1851 */
1852void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1853                                      enum pwr_track_control_method method,
1854                                      u8 rf_path, u8 channel_mapped_index)
1855{
1856        struct rtl_priv *rtlpriv = rtl_priv(hw);
1857        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1858        struct rtl_phy *rtlphy = &rtlpriv->phy;
1859        u32 final_swing_idx[1];
1860        u8 pwr_tracking_limit = 26; /*+1.0dB*/
1861        u8 tx_rate = 0xFF;
1862        s8 final_ofdm_swing_index = 0;
1863
1864        if (rtldm->tx_rate != 0xFF)
1865                tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1866
1867        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
1868
1869        if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
1870                /*CCK*/
1871                if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1872                        pwr_tracking_limit = 32; /*+4dB*/
1873                /*OFDM*/
1874                else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1875                        pwr_tracking_limit = 30; /*+3dB*/
1876                else if (tx_rate == MGN_54M)
1877                        pwr_tracking_limit = 28; /*+2dB*/
1878                /*HT*/
1879                /*QPSK/BPSK*/
1880                else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1881                        pwr_tracking_limit = 34; /*+5dB*/
1882                /*16QAM*/
1883                else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1884                        pwr_tracking_limit = 30; /*+3dB*/
1885                /*64QAM*/
1886                else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1887                        pwr_tracking_limit = 28; /*+2dB*/
1888                /*2 VHT*/
1889                /*QPSK/BPSK*/
1890                else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1891                        (tx_rate <= MGN_VHT1SS_MCS2))
1892                        pwr_tracking_limit = 34; /*+5dB*/
1893                /*16QAM*/
1894                else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1895                        (tx_rate <= MGN_VHT1SS_MCS4))
1896                        pwr_tracking_limit = 30; /*+3dB*/
1897                /*64QAM*/
1898                else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1899                        (tx_rate <= MGN_VHT1SS_MCS6))
1900                        pwr_tracking_limit = 28; /*+2dB*/
1901                else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1902                        pwr_tracking_limit = 26; /*+1dB*/
1903                else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1904                        pwr_tracking_limit = 24; /*+0dB*/
1905                else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1906                        pwr_tracking_limit = 22; /*-1dB*/
1907                else
1908                        pwr_tracking_limit = 24;
1909        }
1910        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1911                "TxRate=0x%x, PwrTrackingLimit=%d\n",
1912                tx_rate, pwr_tracking_limit);
1913
1914        if (method == BBSWING) {
1915                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1916                        "===>%s\n", __func__);
1917                if (rf_path == RF90_PATH_A) {
1918                        final_swing_idx[RF90_PATH_A] =
1919                                (rtldm->ofdm_index[RF90_PATH_A] >
1920                                pwr_tracking_limit) ?
1921                                pwr_tracking_limit :
1922                                rtldm->ofdm_index[RF90_PATH_A];
1923                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1924                                "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1925                                rtldm->ofdm_index[RF90_PATH_A],
1926                                final_swing_idx[RF90_PATH_A]);
1927
1928                        rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1929                                txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
1930                }
1931        } else if (method == MIX_MODE) {
1932                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1933                        "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1934                        rtldm->default_ofdm_index,
1935                        rtldm->absolute_ofdm_swing_idx[rf_path],
1936                        rf_path);
1937
1938                final_ofdm_swing_index =
1939                        rtldm->default_ofdm_index +
1940                        rtldm->absolute_ofdm_swing_idx[rf_path];
1941                /*BBSwing higher then Limit*/
1942                if (rf_path == RF90_PATH_A) {
1943                        if (final_ofdm_swing_index > pwr_tracking_limit) {
1944                                rtldm->remnant_cck_idx =
1945                                        final_ofdm_swing_index -
1946                                        pwr_tracking_limit;
1947                                /* CCK Follow the same compensate value as Path A*/
1948                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1949                                        final_ofdm_swing_index -
1950                                        pwr_tracking_limit;
1951
1952                                rtl_set_bbreg(hw, RA_TXSCALE,
1953                                        0xFFE00000,
1954                                        txscaling_tbl[pwr_tracking_limit]);
1955
1956                                rtldm->modify_txagc_flag_path_a = true;
1957
1958                                /*Set TxAGC Page C{};*/
1959                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1960                                        rtlphy->current_channel,
1961                                        RF90_PATH_A);
1962
1963                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1964                                        " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1965                                        pwr_tracking_limit,
1966                                        rtldm->remnant_ofdm_swing_idx[rf_path]);
1967                        } else if (final_ofdm_swing_index < 0) {
1968                                rtldm->remnant_cck_idx = final_ofdm_swing_index;
1969                                /* CCK Follow the same compensate value as Path A*/
1970                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1971                                        final_ofdm_swing_index;
1972
1973                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1974                                        txscaling_tbl[0]);
1975
1976                                rtldm->modify_txagc_flag_path_a = true;
1977
1978                                /*Set TxAGC Page C{};*/
1979                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1980                                        rtlphy->current_channel, RF90_PATH_A);
1981
1982                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1983                                        "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1984                                        rtldm->remnant_ofdm_swing_idx[rf_path]);
1985                        } else {
1986                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1987                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
1988
1989                                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1990                                        "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1991                                        final_ofdm_swing_index);
1992                                /*If TxAGC has changed, reset TxAGC again*/
1993                                if (rtldm->modify_txagc_flag_path_a) {
1994                                        rtldm->remnant_cck_idx = 0;
1995                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1996
1997                                        /*Set TxAGC Page C{};*/
1998                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
1999                                                rtlphy->current_channel, RF90_PATH_A);
2000
2001                                        rtldm->modify_txagc_flag_path_a = false;
2002
2003                                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
2004                                                DBG_LOUD,
2005                                                "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2006                                }
2007                        }
2008                }
2009        } else {
2010                return;
2011        }
2012}
2013
2014void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2015        struct ieee80211_hw *hw)
2016{
2017        struct rtl_priv *rtlpriv = rtl_priv(hw);
2018        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2019        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2020        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2021        struct rtl_phy *rtlphy = &rtlpriv->phy;
2022
2023        u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2024        u8 thermal_value_avg_count = 0;
2025        u32 thermal_value_avg = 0;
2026
2027        u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2028        /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2029        u8 index_for_channel = 0;
2030
2031        /* 1. The following TWO tables decide the final
2032         * index of OFDM/CCK swing table.
2033         */
2034        const u8 *delta_swing_table_idx_tup_a;
2035        const u8 *delta_swing_table_idx_tdown_a;
2036
2037        /*2. Initilization ( 7 steps in total )*/
2038        rtl8821ae_get_delta_swing_table(hw,
2039                                        &delta_swing_table_idx_tup_a,
2040                                        &delta_swing_table_idx_tdown_a);
2041
2042        rtldm->txpower_trackinginit = true;
2043
2044        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2045                "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2046                __func__,
2047                rtldm->swing_idx_cck_base,
2048                rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2049                rtldm->default_ofdm_index);
2050        /*0x42: RF Reg[15:10] 88E*/
2051        thermal_value = (u8)rtl_get_rfreg(hw,
2052                RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2053        if (!rtldm->txpower_track_control ||
2054                rtlefuse->eeprom_thermalmeter == 0 ||
2055                rtlefuse->eeprom_thermalmeter == 0xFF)
2056                return;
2057
2058        /* 3. Initialize ThermalValues of RFCalibrateInfo*/
2059
2060        if (rtlhal->reloadtxpowerindex) {
2061                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2062                        "reload ofdm index for band switch\n");
2063        }
2064
2065        /*4. Calculate average thermal meter*/
2066        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2067        rtldm->thermalvalue_avg_index++;
2068        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2069                /*Average times =  c.AverageThermalNum*/
2070                rtldm->thermalvalue_avg_index = 0;
2071
2072        for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2073                if (rtldm->thermalvalue_avg[i]) {
2074                        thermal_value_avg += rtldm->thermalvalue_avg[i];
2075                        thermal_value_avg_count++;
2076                }
2077        }
2078        /*Calculate Average ThermalValue after average enough times*/
2079        if (thermal_value_avg_count) {
2080                thermal_value = (u8)(thermal_value_avg /
2081                                thermal_value_avg_count);
2082                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2083                        "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2084                        thermal_value, rtlefuse->eeprom_thermalmeter);
2085        }
2086
2087        /*5. Calculate delta, delta_LCK, delta_IQK.
2088         *"delta" here is used to determine whether
2089         * thermal value changes or not.
2090         */
2091        delta = (thermal_value > rtldm->thermalvalue) ?
2092                (thermal_value - rtldm->thermalvalue) :
2093                (rtldm->thermalvalue - thermal_value);
2094        delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2095                (thermal_value - rtldm->thermalvalue_lck) :
2096                (rtldm->thermalvalue_lck - thermal_value);
2097        delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2098                (thermal_value - rtldm->thermalvalue_iqk) :
2099                (rtldm->thermalvalue_iqk - thermal_value);
2100
2101        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2102                "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2103                delta, delta_lck, delta_iqk);
2104
2105        /* 6. If necessary, do LCK.     */
2106        /*Delta temperature is equal to or larger than 20 centigrade.*/
2107        if (delta_lck >= IQK_THRESHOLD) {
2108                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2109                        "delta_LCK(%d) >= Threshold_IQK(%d)\n",
2110                        delta_lck, IQK_THRESHOLD);
2111                rtldm->thermalvalue_lck = thermal_value;
2112                rtl8821ae_phy_lc_calibrate(hw);
2113        }
2114
2115        /*7. If necessary, move the index of swing table to adjust Tx power.*/
2116
2117        if (delta > 0 && rtldm->txpower_track_control) {
2118                /*"delta" here is used to record the
2119                 * absolute value of differrence.
2120                 */
2121                delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2122                        (thermal_value - rtlefuse->eeprom_thermalmeter) :
2123                        (rtlefuse->eeprom_thermalmeter - thermal_value);
2124
2125                if (delta >= TXSCALE_TABLE_SIZE)
2126                        delta = TXSCALE_TABLE_SIZE - 1;
2127
2128                /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2129
2130                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2131                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2132                                "delta_swing_table_idx_tup_a[%d] = %d\n",
2133                                delta, delta_swing_table_idx_tup_a[delta]);
2134                        rtldm->delta_power_index_last[RF90_PATH_A] =
2135                                rtldm->delta_power_index[RF90_PATH_A];
2136                        rtldm->delta_power_index[RF90_PATH_A] =
2137                                delta_swing_table_idx_tup_a[delta];
2138
2139                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2140                                delta_swing_table_idx_tup_a[delta];
2141                        /*Record delta swing for mix mode power tracking*/
2142
2143                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2144                                "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2145                                rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2146                } else {
2147                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2148                                "delta_swing_table_idx_tdown_a[%d] = %d\n",
2149                                delta, delta_swing_table_idx_tdown_a[delta]);
2150
2151                        rtldm->delta_power_index_last[RF90_PATH_A] =
2152                                rtldm->delta_power_index[RF90_PATH_A];
2153                        rtldm->delta_power_index[RF90_PATH_A] =
2154                                -1 * delta_swing_table_idx_tdown_a[delta];
2155
2156                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2157                                -1 * delta_swing_table_idx_tdown_a[delta];
2158                        /* Record delta swing for mix mode power tracking*/
2159                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2160                                "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2161                                rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2162                }
2163
2164                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2165                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2166                                "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2167                                (p == RF90_PATH_A ? 'A' : 'B'));
2168                        /*If Thermal value changes but lookup table value
2169                         * still the same
2170                         */
2171                        if (rtldm->delta_power_index[p] ==
2172                                rtldm->delta_power_index_last[p])
2173
2174                                rtldm->power_index_offset[p] = 0;
2175                        else
2176                                rtldm->power_index_offset[p] =
2177                                        rtldm->delta_power_index[p] -
2178                                        rtldm->delta_power_index_last[p];
2179                        /*Power Index Diff between 2 times Power Tracking*/
2180
2181                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2182                                "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2183                                (p == RF90_PATH_A ? 'A' : 'B'),
2184                                rtldm->power_index_offset[p],
2185                                rtldm->delta_power_index[p] ,
2186                                rtldm->delta_power_index_last[p]);
2187
2188                        rtldm->ofdm_index[p] =
2189                                        rtldm->swing_idx_ofdm_base[p] +
2190                                        rtldm->power_index_offset[p];
2191                        rtldm->cck_index =
2192                                        rtldm->swing_idx_cck_base +
2193                                        rtldm->power_index_offset[p];
2194
2195                        rtldm->swing_idx_cck = rtldm->cck_index;
2196                        rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2197
2198                        /*********Print BB Swing Base and Index Offset********/
2199
2200                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2201                                "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2202                                rtldm->swing_idx_cck,
2203                                rtldm->swing_idx_cck_base,
2204                                rtldm->power_index_offset[p]);
2205                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2206                                "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2207                                rtldm->swing_idx_ofdm[p],
2208                                (p == RF90_PATH_A ? 'A' : 'B'),
2209                                rtldm->swing_idx_ofdm_base[p],
2210                                rtldm->power_index_offset[p]);
2211
2212                        /*7.1 Handle boundary conditions of index.*/
2213
2214                        if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2215                                rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2216                        else if (rtldm->ofdm_index[p] < ofdm_min_index)
2217                                rtldm->ofdm_index[p] = ofdm_min_index;
2218                }
2219                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2220                        "\n\n========================================================================================================\n");
2221                if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2222                        rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2223                else if (rtldm->cck_index < 0)
2224                        rtldm->cck_index = 0;
2225        } else {
2226                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2227                        "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2228                        rtldm->txpower_track_control,
2229                        thermal_value,
2230                        rtldm->thermalvalue);
2231
2232                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2233                        rtldm->power_index_offset[p] = 0;
2234        }
2235        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2236                "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2237                /*Print Swing base & current*/
2238                rtldm->cck_index, rtldm->swing_idx_cck_base);
2239        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2240                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2241                        "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2242                        rtldm->ofdm_index[p],
2243                        (p == RF90_PATH_A ? 'A' : 'B'),
2244                        rtldm->swing_idx_ofdm_base[p]);
2245        }
2246
2247        if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2248                rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2249                rtldm->txpower_track_control) {
2250                /*7.2 Configure the Swing Table to adjust Tx Power.*/
2251                /*Always TRUE after Tx Power is adjusted by power tracking.*/
2252                /*
2253                 *  2012/04/23 MH According to Luke's suggestion,
2254                 *  we can not write BB digital
2255                 *  to increase TX power. Otherwise, EVM will be bad.
2256                 *
2257                 *  2012/04/25 MH Add for tx power tracking to
2258                 *  set tx power in tx agc for 88E.
2259                 */
2260                if (thermal_value > rtldm->thermalvalue) {
2261                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2262                                "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2263                                rtldm->power_index_offset[RF90_PATH_A],
2264                                delta, thermal_value,
2265                                rtlefuse->eeprom_thermalmeter,
2266                                rtldm->thermalvalue);
2267                } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2268                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2269                                "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2270                                rtldm->power_index_offset[RF90_PATH_A],
2271                                delta, thermal_value,
2272                                rtlefuse->eeprom_thermalmeter,
2273                                rtldm->thermalvalue);
2274                }
2275
2276                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2277                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2278                                "Temperature(%d) higher than PG value(%d)\n",
2279                                thermal_value, rtlefuse->eeprom_thermalmeter);
2280
2281                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2282                                "****Enter POWER Tracking MIX_MODE****\n");
2283                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2284                                        rtl8821ae_dm_txpwr_track_set_pwr(hw,
2285                                                MIX_MODE, p, index_for_channel);
2286                } else {
2287                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2288                                "Temperature(%d) lower than PG value(%d)\n",
2289                                thermal_value, rtlefuse->eeprom_thermalmeter);
2290
2291                        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2292                                "*****Enter POWER Tracking MIX_MODE*****\n");
2293                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2294                                rtl8812ae_dm_txpwr_track_set_pwr(hw,
2295                                        MIX_MODE, p, index_for_channel);
2296                }
2297                /*Record last time Power Tracking result as base.*/
2298                rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2299                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2300                        rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2301
2302                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2303                        "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2304                        rtldm->thermalvalue, thermal_value);
2305                /*Record last Power Tracking Thermal Value*/
2306                rtldm->thermalvalue = thermal_value;
2307        }
2308        /* Delta temperature is equal to or larger than
2309         * 20 centigrade (When threshold is 8).
2310         */
2311        if (delta_iqk >= IQK_THRESHOLD) {
2312                if (!rtlphy->lck_inprogress) {
2313                        spin_lock(&rtlpriv->locks.iqk_lock);
2314                        rtlphy->lck_inprogress = true;
2315                        spin_unlock(&rtlpriv->locks.iqk_lock);
2316
2317                        rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2318
2319                        spin_lock(&rtlpriv->locks.iqk_lock);
2320                        rtlphy->lck_inprogress = false;
2321                        spin_unlock(&rtlpriv->locks.iqk_lock);
2322                }
2323        }
2324
2325        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2326}
2327
2328void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2329{
2330        struct rtl_priv *rtlpriv = rtl_priv(hw);
2331        if (!rtlpriv->dm.tm_trigger) {
2332                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2333                              0x03);
2334                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2335                        "Trigger 8821ae Thermal Meter!!\n");
2336                rtlpriv->dm.tm_trigger = 1;
2337                return;
2338        } else {
2339                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2340                        "Schedule TxPowerTracking !!\n");
2341
2342                rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2343                rtlpriv->dm.tm_trigger = 0;
2344        }
2345}
2346
2347static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2348{
2349        struct rtl_priv *rtlpriv = rtl_priv(hw);
2350        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2351        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2352        struct rate_adaptive *p_ra = &rtlpriv->ra;
2353        u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2354        u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2355        u8 go_up_gap = 5;
2356        struct ieee80211_sta *sta = NULL;
2357
2358        if (is_hal_stop(rtlhal)) {
2359                rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2360                        "driver is going to unload\n");
2361                return;
2362        }
2363
2364        if (!rtlpriv->dm.useramask) {
2365                rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2366                        "driver does not control rate adaptive mask\n");
2367                return;
2368        }
2369
2370        if (mac->link_state == MAC80211_LINKED &&
2371                mac->opmode == NL80211_IFTYPE_STATION) {
2372                switch (p_ra->pre_ratr_state) {
2373                case DM_RATR_STA_MIDDLE:
2374                        high_rssithresh_for_ra += go_up_gap;
2375                        break;
2376                case DM_RATR_STA_LOW:
2377                        high_rssithresh_for_ra += go_up_gap;
2378                        low_rssithresh_for_ra += go_up_gap;
2379                        break;
2380                default:
2381                        break;
2382                }
2383
2384                if (rtlpriv->dm.undec_sm_pwdb >
2385                    (long)high_rssithresh_for_ra)
2386                        p_ra->ratr_state = DM_RATR_STA_HIGH;
2387                else if (rtlpriv->dm.undec_sm_pwdb >
2388                         (long)low_rssithresh_for_ra)
2389                        p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2390                else
2391                        p_ra->ratr_state = DM_RATR_STA_LOW;
2392
2393                if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2394                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2395                                "RSSI = %ld\n",
2396                                rtlpriv->dm.undec_sm_pwdb);
2397                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2398                                "RSSI_LEVEL = %d\n", p_ra->ratr_state);
2399                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2400                                "PreState = %d, CurState = %d\n",
2401                                p_ra->pre_ratr_state, p_ra->ratr_state);
2402
2403                        rcu_read_lock();
2404                        sta = rtl_find_sta(hw, mac->bssid);
2405                        if (sta)
2406                                rtlpriv->cfg->ops->update_rate_tbl(hw,
2407                                                sta, p_ra->ratr_state, true);
2408                        rcu_read_unlock();
2409
2410                        p_ra->pre_ratr_state = p_ra->ratr_state;
2411                }
2412        }
2413}
2414
2415static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2416{
2417        struct rtl_priv *rtlpriv = rtl_priv(hw);
2418        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2419        struct rtl_mac *mac = &rtlpriv->mac80211;
2420        static u8 stage;
2421        u8 cur_stage = 0;
2422        u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2423
2424        if (mac->link_state < MAC80211_LINKED)
2425                cur_stage = 0;
2426        else if (dm_digtable->rssi_val_min < 25)
2427                cur_stage = 1;
2428        else if (dm_digtable->rssi_val_min > 30)
2429                cur_stage = 3;
2430        else
2431                cur_stage = 2;
2432
2433        if (cur_stage != stage) {
2434                if (cur_stage == 1) {
2435                        basic_rate &= (!(basic_rate ^ mac->basic_rates));
2436                        rtlpriv->cfg->ops->set_hw_reg(hw,
2437                                HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2438                } else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2439                        rtlpriv->cfg->ops->set_hw_reg(hw,
2440                                HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2441                }
2442        }
2443        stage = cur_stage;
2444}
2445
2446static void rtl8821ae_dm_edca_choose_traffic_idx(
2447        struct ieee80211_hw *hw, u64 cur_tx_bytes,
2448        u64 cur_rx_bytes, bool b_bias_on_rx,
2449        bool *pb_is_cur_rdl_state)
2450{
2451        struct rtl_priv *rtlpriv = rtl_priv(hw);
2452
2453        if (b_bias_on_rx) {
2454                if (cur_tx_bytes > (cur_rx_bytes*4)) {
2455                        *pb_is_cur_rdl_state = false;
2456                        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2457                                "Uplink Traffic\n");
2458                } else {
2459                        *pb_is_cur_rdl_state = true;
2460                        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2461                                "Balance Traffic\n");
2462                }
2463        } else {
2464                if (cur_rx_bytes > (cur_tx_bytes*4)) {
2465                        *pb_is_cur_rdl_state = true;
2466                        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2467                                "Downlink       Traffic\n");
2468                } else {
2469                        *pb_is_cur_rdl_state = false;
2470                        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2471                                "Balance Traffic\n");
2472                }
2473        }
2474        return;
2475}
2476
2477static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2478{
2479        struct rtl_priv *rtlpriv = rtl_priv(hw);
2480        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2481        struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2482
2483        /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2484        u64 cur_tx_ok_cnt = 0;
2485        u64 cur_rx_ok_cnt = 0;
2486        u32 edca_be_ul = 0x5ea42b;
2487        u32 edca_be_dl = 0x5ea42b;
2488        u32 edca_be = 0x5ea42b;
2489        u8 iot_peer = 0;
2490        bool *pb_is_cur_rdl_state = NULL;
2491        bool b_bias_on_rx = false;
2492        bool b_edca_turbo_on = false;
2493
2494        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2495                "%s=====>\n", __func__);
2496        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2497                "Original BE PARAM: 0x%x\n",
2498                rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2499
2500        if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2501                rtlpriv->dm.is_any_nonbepkts = true;
2502        rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2503
2504        /*===============================
2505         * list paramter for different platform
2506         *===============================
2507         */
2508        pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2509
2510        cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2511        cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2512
2513        rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2514        rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2515
2516        iot_peer = rtlpriv->mac80211.vendor;
2517        b_bias_on_rx = false;
2518        b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2519                           (!rtlpriv->dm.disable_framebursting)) ?
2520                           true : false;
2521
2522        if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2523                if ((iot_peer == PEER_CISCO) &&
2524                        (mac->mode == WIRELESS_MODE_N_24G)) {
2525                        edca_be_dl = edca_setting_dl[iot_peer];
2526                        edca_be_ul = edca_setting_ul[iot_peer];
2527                }
2528        }
2529
2530        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2531                "bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2532                rtlpriv->dm.is_any_nonbepkts,
2533                rtlpriv->dm.disable_framebursting);
2534
2535        rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2536                "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2537                b_edca_turbo_on, b_bias_on_rx);
2538
2539        if (b_edca_turbo_on) {
2540                rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2541                        "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2542                rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2543                        "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2544                if (b_bias_on_rx)
2545                        rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2546                                cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2547                else
2548                        rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2549                                cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2550
2551                edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2552
2553                rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2554
2555                rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2556                        "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2557
2558                rtlpriv->dm.current_turbo_edca = true;
2559
2560                rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2561                        "EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2562                        edca_be_dl, edca_be_ul, edca_be);
2563        } else {
2564                if (rtlpriv->dm.current_turbo_edca) {
2565                        u8 tmp = AC0_BE;
2566                        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2567                                                      (u8 *)(&tmp));
2568                }
2569                rtlpriv->dm.current_turbo_edca = false;
2570        }
2571
2572        rtlpriv->dm.is_any_nonbepkts = false;
2573        rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2574        rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2575}
2576
2577static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2578{
2579        struct rtl_priv *rtlpriv = rtl_priv(hw);
2580        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2581        u8 cur_cck_cca_thresh;
2582
2583        if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2584                if (dm_digtable->rssi_val_min > 25) {
2585                        cur_cck_cca_thresh = 0xcd;
2586                } else if ((dm_digtable->rssi_val_min <= 25) &&
2587                           (dm_digtable->rssi_val_min > 10)) {
2588                        cur_cck_cca_thresh = 0x83;
2589                } else {
2590                        if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2591                                cur_cck_cca_thresh = 0x83;
2592                        else
2593                                cur_cck_cca_thresh = 0x40;
2594                }
2595        } else {
2596                if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2597                        cur_cck_cca_thresh = 0x83;
2598                else
2599                        cur_cck_cca_thresh = 0x40;
2600        }
2601
2602        if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2603                rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2604                               cur_cck_cca_thresh);
2605
2606        dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2607        dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2608        rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
2609                "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2610}
2611
2612static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2613{
2614        struct rtl_priv *rtlpriv = rtl_priv(hw);
2615        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2616        u8 crystal_cap;
2617        u32 packet_count;
2618        int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2619        int cfo_ave_diff;
2620
2621        if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2622                /*1.Enable ATC*/
2623                if (rtldm->atc_status == ATC_STATUS_OFF) {
2624                        rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2625                        rtldm->atc_status = ATC_STATUS_ON;
2626                }
2627
2628                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2629                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2630                        "atc_status = %d\n", rtldm->atc_status);
2631
2632                if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2633                        rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2634                        crystal_cap = rtldm->crystal_cap & 0x3f;
2635                        crystal_cap = crystal_cap & 0x3f;
2636                        if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2637                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2638                                              0x7ff80000, (crystal_cap |
2639                                              (crystal_cap << 6)));
2640                        else
2641                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2642                                              0xfff000, (crystal_cap |
2643                                              (crystal_cap << 6)));
2644                }
2645                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2646                        rtldm->crystal_cap);
2647        } else{
2648                /*1. Calculate CFO for path-A & path-B*/
2649                cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2650                cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2651                packet_count = rtldm->packet_count;
2652
2653                /*2.No new packet*/
2654                if (packet_count == rtldm->packet_count_pre) {
2655                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2656                                "packet counter doesn't change\n");
2657                        return;
2658                }
2659
2660                rtldm->packet_count_pre = packet_count;
2661                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2662                        "packet counter = %d\n",
2663                        rtldm->packet_count);
2664
2665                /*3.Average CFO*/
2666                if (rtlpriv->phy.rf_type == RF_1T1R)
2667                        cfo_ave = cfo_khz_a;
2668                else
2669                        cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2670
2671                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2672                        "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2673                        cfo_khz_a, cfo_khz_b, cfo_ave);
2674
2675                /*4.Avoid abnormal large CFO*/
2676                cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2677                                                (rtldm->cfo_ave_pre - cfo_ave) :
2678                                                (cfo_ave - rtldm->cfo_ave_pre);
2679
2680                if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
2681                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2682                                "first large CFO hit\n");
2683                        rtldm->large_cfo_hit = true;
2684                        return;
2685                } else
2686                        rtldm->large_cfo_hit = false;
2687
2688                rtldm->cfo_ave_pre = cfo_ave;
2689
2690                /*CFO tracking by adjusting Xtal cap.*/
2691
2692                /*1.Dynamic Xtal threshold*/
2693                if (cfo_ave >= -rtldm->cfo_threshold &&
2694                        cfo_ave <= rtldm->cfo_threshold &&
2695                        rtldm->is_freeze == 0) {
2696                        if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2697                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2698                                rtldm->is_freeze = 1;
2699                        } else {
2700                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2701                        }
2702                }
2703                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2704                        "Dynamic threshold = %d\n",
2705                        rtldm->cfo_threshold);
2706
2707                /* 2.Calculate Xtal offset*/
2708                if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2709                        adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2710                else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2711                         rtlpriv->dm.crystal_cap > 0)
2712                        adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2713                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2714                        "Crystal cap = 0x%x, Crystal cap offset = %d\n",
2715                        rtldm->crystal_cap, adjust_xtal);
2716
2717                /*3.Adjudt Crystal Cap.*/
2718                if (adjust_xtal != 0) {
2719                        rtldm->is_freeze = 0;
2720                        rtldm->crystal_cap += adjust_xtal;
2721
2722                        if (rtldm->crystal_cap > 0x3f)
2723                                rtldm->crystal_cap = 0x3f;
2724                        else if (rtldm->crystal_cap < 0)
2725                                rtldm->crystal_cap = 0;
2726
2727                        crystal_cap = rtldm->crystal_cap & 0x3f;
2728                        crystal_cap = crystal_cap & 0x3f;
2729                        if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2730                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2731                                              0x7ff80000, (crystal_cap |
2732                                              (crystal_cap << 6)));
2733                        else
2734                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2735                                              0xfff000, (crystal_cap |
2736                                              (crystal_cap << 6)));
2737                        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2738                                "New crystal cap = 0x%x\n",
2739                                rtldm->crystal_cap);
2740                }
2741        }
2742}
2743
2744void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2745{
2746        struct rtl_priv *rtlpriv = rtl_priv(hw);
2747        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2748        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2749        bool fw_current_inpsmode = false;
2750        bool fw_ps_awake = true;
2751
2752        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2753                                      (u8 *)(&fw_current_inpsmode));
2754
2755        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2756                                      (u8 *)(&fw_ps_awake));
2757
2758        if (ppsc->p2p_ps_info.p2p_ps_mode)
2759                fw_ps_awake = false;
2760
2761        spin_lock(&rtlpriv->locks.rf_ps_lock);
2762        if ((ppsc->rfpwr_state == ERFON) &&
2763            ((!fw_current_inpsmode) && fw_ps_awake) &&
2764            (!ppsc->rfchange_inprogress)) {
2765                rtl8821ae_dm_common_info_self_update(hw);
2766                rtl8821ae_dm_false_alarm_counter_statistics(hw);
2767                rtl8821ae_dm_check_rssi_monitor(hw);
2768                rtl8821ae_dm_dig(hw);
2769                rtl8821ae_dm_cck_packet_detection_thresh(hw);
2770                rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2771                rtl8821ae_dm_refresh_basic_rate_mask(hw);
2772                rtl8821ae_dm_check_edca_turbo(hw);
2773                rtl8821ae_dm_dynamic_atc_switch(hw);
2774                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2775                        rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2776                else
2777                        rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2778                rtl8821ae_dm_iq_calibrate(hw);
2779        }
2780        spin_unlock(&rtlpriv->locks.rf_ps_lock);
2781
2782        rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2783        rtl_dbg(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2784}
2785
2786void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2787                                        u8 *pdesc, u32 mac_id)
2788{
2789        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2790        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2791        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2792        struct fast_ant_training *pfat_table = &rtldm->fat_table;
2793        __le32 *pdesc32 = (__le32 *)pdesc;
2794
2795        if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2796                return;
2797
2798        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2799                set_tx_desc_tx_ant(pdesc32, pfat_table->antsel_a[mac_id]);
2800}
2801