linux/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2013  Realtek Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 * The full GNU General Public License is included in this distribution in the
  19 * file called LICENSE.
  20 *
  21 * Contact Information:
  22 * wlanfae <wlanfae@realtek.com>
  23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  24 * Hsinchu 300, Taiwan.
  25 *
  26 * Larry Finger <Larry.Finger@lwfinger.net>
  27 *
  28 *****************************************************************************/
  29
  30#include "../wifi.h"
  31#include "../base.h"
  32#include "../pci.h"
  33#include "reg.h"
  34#include "def.h"
  35#include "phy.h"
  36#include "dm.h"
  37#include "fw.h"
  38#include "trx.h"
  39
  40static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
  41        0x7f8001fe,             /* 0, +6.0dB */
  42        0x788001e2,             /* 1, +5.5dB */
  43        0x71c001c7,             /* 2, +5.0dB */
  44        0x6b8001ae,             /* 3, +4.5dB */
  45        0x65400195,             /* 4, +4.0dB */
  46        0x5fc0017f,             /* 5, +3.5dB */
  47        0x5a400169,             /* 6, +3.0dB */
  48        0x55400155,             /* 7, +2.5dB */
  49        0x50800142,             /* 8, +2.0dB */
  50        0x4c000130,             /* 9, +1.5dB */
  51        0x47c0011f,             /* 10, +1.0dB */
  52        0x43c0010f,             /* 11, +0.5dB */
  53        0x40000100,             /* 12, +0dB */
  54        0x3c8000f2,             /* 13, -0.5dB */
  55        0x390000e4,             /* 14, -1.0dB */
  56        0x35c000d7,             /* 15, -1.5dB */
  57        0x32c000cb,             /* 16, -2.0dB */
  58        0x300000c0,             /* 17, -2.5dB */
  59        0x2d4000b5,             /* 18, -3.0dB */
  60        0x2ac000ab,             /* 19, -3.5dB */
  61        0x288000a2,             /* 20, -4.0dB */
  62        0x26000098,             /* 21, -4.5dB */
  63        0x24000090,             /* 22, -5.0dB */
  64        0x22000088,             /* 23, -5.5dB */
  65        0x20000080,             /* 24, -6.0dB */
  66        0x1e400079,             /* 25, -6.5dB */
  67        0x1c800072,             /* 26, -7.0dB */
  68        0x1b00006c,             /* 27. -7.5dB */
  69        0x19800066,             /* 28, -8.0dB */
  70        0x18000060,             /* 29, -8.5dB */
  71        0x16c0005b,             /* 30, -9.0dB */
  72        0x15800056,             /* 31, -9.5dB */
  73        0x14400051,             /* 32, -10.0dB */
  74        0x1300004c,             /* 33, -10.5dB */
  75        0x12000048,             /* 34, -11.0dB */
  76        0x11000044,             /* 35, -11.5dB */
  77        0x10000040,             /* 36, -12.0dB */
  78        0x0f00003c,             /* 37, -12.5dB */
  79        0x0e400039,             /* 38, -13.0dB */
  80        0x0d800036,             /* 39, -13.5dB */
  81        0x0cc00033,             /* 40, -14.0dB */
  82        0x0c000030,             /* 41, -14.5dB */
  83        0x0b40002d,             /* 42, -15.0dB */
  84};
  85
  86static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = {
  87        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},       /* 0, +0dB */
  88        {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},       /* 1, -0.5dB */
  89        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},       /* 2, -1.0dB */
  90        {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},       /* 3, -1.5dB */
  91        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},       /* 4, -2.0dB */
  92        {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},       /* 5, -2.5dB */
  93        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},       /* 6, -3.0dB */
  94        {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},       /* 7, -3.5dB */
  95        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},       /* 8, -4.0dB */
  96        {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},       /* 9, -4.5dB */
  97        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},       /* 10, -5.0dB */
  98        {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},       /* 11, -5.5dB */
  99        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},       /* 12, -6.0dB */
 100        {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},       /* 13, -6.5dB */
 101        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},       /* 14, -7.0dB */
 102        {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},       /* 15, -7.5dB */
 103        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},       /* 16, -8.0dB */
 104        {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},       /* 17, -8.5dB */
 105        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},       /* 18, -9.0dB */
 106        {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},       /* 19, -9.5dB */
 107        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},       /* 20, -10.0dB*/
 108        {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},       /* 21, -10.5dB*/
 109        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},       /* 22, -11.0dB*/
 110        {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},       /* 23, -11.5dB*/
 111        {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},       /* 24, -12.0dB*/
 112        {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},       /* 25, -12.5dB*/
 113        {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},       /* 26, -13.0dB*/
 114        {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},       /* 27, -13.5dB*/
 115        {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},       /* 28, -14.0dB*/
 116        {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},       /* 29, -14.5dB*/
 117        {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},       /* 30, -15.0dB*/
 118        {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},       /* 31, -15.5dB*/
 119        {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}        /* 32, -16.0dB*/
 120};
 121
 122static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = {
 123        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},       /* 0, +0dB */
 124        {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},       /* 1, -0.5dB */
 125        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},       /* 2, -1.0dB */
 126        {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},       /* 3, -1.5dB */
 127        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},       /* 4, -2.0dB */
 128        {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},       /* 5, -2.5dB */
 129        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},       /* 6, -3.0dB */
 130        {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},       /* 7, -3.5dB */
 131        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},       /* 8, -4.0dB */
 132        {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},       /* 9, -4.5dB */
 133        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},       /* 10, -5.0dB */
 134        {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},       /* 11, -5.5dB */
 135        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},       /* 12, -6.0dB */
 136        {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},       /* 13, -6.5dB */
 137        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},       /* 14, -7.0dB */
 138        {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},       /* 15, -7.5dB */
 139        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},       /* 16, -8.0dB */
 140        {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},       /* 17, -8.5dB */
 141        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},       /* 18, -9.0dB */
 142        {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},       /* 19, -9.5dB */
 143        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},       /* 20, -10.0dB*/
 144        {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},       /* 21, -10.5dB*/
 145        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},       /* 22, -11.0dB*/
 146        {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},       /* 23, -11.5dB*/
 147        {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},       /* 24, -12.0dB*/
 148        {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},       /* 25, -12.5dB*/
 149        {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},       /* 26, -13.0dB*/
 150        {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},       /* 27, -13.5dB*/
 151        {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},       /* 28, -14.0dB*/
 152        {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},       /* 29, -14.5dB*/
 153        {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},       /* 30, -15.0dB*/
 154        {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},       /* 31, -15.5dB*/
 155        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}        /* 32, -16.0dB*/
 156};
 157
 158#define CAL_SWING_OFF(_off, _dir, _size, _del)                          \
 159        do {                                                            \
 160                for (_off = 0; _off < _size; _off++) {                  \
 161                        if (_del < thermal_threshold[_dir][_off]) {     \
 162                                if (_off != 0)                          \
 163                                        _off--;                         \
 164                                break;                                  \
 165                        }                                               \
 166                }                                                       \
 167                if (_off >= _size)                                      \
 168                        _off = _size - 1;                               \
 169        } while (0)
 170
 171static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw,
 172                                  u8 ofdm_index, u8 rfpath,
 173                                  long iqk_result_x, long iqk_result_y)
 174{
 175        long ele_a = 0, ele_d, ele_c = 0, value32;
 176
 177        ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22;
 178
 179        if (iqk_result_x != 0) {
 180                if ((iqk_result_x & 0x00000200) != 0)
 181                        iqk_result_x = iqk_result_x | 0xFFFFFC00;
 182                ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF;
 183
 184                if ((iqk_result_y & 0x00000200) != 0)
 185                        iqk_result_y = iqk_result_y | 0xFFFFFC00;
 186                ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF;
 187
 188                switch (rfpath) {
 189                case RF90_PATH_A:
 190                        value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
 191                        rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
 192                                      value32);
 193                        value32 = (ele_c & 0x000003C0) >> 6;
 194                        rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
 195                        value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
 196                        rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), value32);
 197                        break;
 198                case RF90_PATH_B:
 199                        value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
 200                        rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL,
 201                                      MASKDWORD, value32);
 202                        value32 = (ele_c & 0x000003C0) >> 6;
 203                        rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32);
 204                        value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
 205                        rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), value32);
 206                        break;
 207                default:
 208                        break;
 209                }
 210        } else {
 211                switch (rfpath) {
 212                case RF90_PATH_A:
 213                        rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
 214                                      ofdmswing_table[ofdm_index]);
 215                        rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
 216                        rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), 0x00);
 217                        break;
 218                case RF90_PATH_B:
 219                        rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, MASKDWORD,
 220                                      ofdmswing_table[ofdm_index]);
 221                        rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00);
 222                        rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), 0x00);
 223                        break;
 224                default:
 225                        break;
 226                }
 227        }
 228}
 229
 230void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw,
 231        u8 type, u8 *pdirection, u32 *poutwrite_val)
 232{
 233        struct rtl_priv *rtlpriv = rtl_priv(hw);
 234        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 235        u8 pwr_val = 0;
 236        u8 cck_base = rtldm->swing_idx_cck_base;
 237        u8 cck_val = rtldm->swing_idx_cck;
 238        u8 ofdm_base = rtldm->swing_idx_ofdm_base;
 239        u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
 240
 241        if (type == 0) {
 242                if (ofdm_val <= ofdm_base) {
 243                        *pdirection = 1;
 244                        pwr_val = ofdm_base - ofdm_val;
 245                } else {
 246                        *pdirection = 2;
 247                        pwr_val = ofdm_val - ofdm_base;
 248                }
 249        } else if (type == 1) {
 250                if (cck_val <= cck_base) {
 251                        *pdirection = 1;
 252                        pwr_val = cck_base - cck_val;
 253                } else {
 254                        *pdirection = 2;
 255                        pwr_val = cck_val - 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) | (pwr_val << 16) |
 263                         (pwr_val << 24);
 264}
 265
 266
 267static void rtl88e_chk_tx_track(struct ieee80211_hw *hw,
 268                                enum pwr_track_control_method method,
 269                                u8 rfpath, u8 index)
 270{
 271        struct rtl_priv *rtlpriv = rtl_priv(hw);
 272        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 273        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 274        int jj = rtldm->swing_idx_cck;
 275        int i;
 276
 277        if (method == TXAGC) {
 278                if (rtldm->swing_flag_ofdm == true ||
 279                    rtldm->swing_flag_cck == true) {
 280                        u8 chan = rtlphy->current_channel;
 281                        rtl88e_phy_set_txpower_level(hw, chan);
 282                        rtldm->swing_flag_ofdm = false;
 283                        rtldm->swing_flag_cck = false;
 284                }
 285        } else if (method == BBSWING) {
 286                if (!rtldm->cck_inch14) {
 287                        for (i = 0; i < 8; i++)
 288                                rtl_write_byte(rtlpriv, 0xa22 + i,
 289                                               cck_tbl_ch1_13[jj][i]);
 290                } else {
 291                        for (i = 0; i < 8; i++)
 292                                rtl_write_byte(rtlpriv, 0xa22 + i,
 293                                               cck_tbl_ch14[jj][i]);
 294                }
 295
 296                if (rfpath == RF90_PATH_A) {
 297                        long x = rtlphy->iqk_matrix[index].value[0][0];
 298                        long y = rtlphy->iqk_matrix[index].value[0][1];
 299                        u8 indx = rtldm->swing_idx_ofdm[rfpath];
 300                        rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
 301                } else if (rfpath == RF90_PATH_B) {
 302                        u8 indx = rtldm->swing_idx_ofdm[rfpath];
 303                        long x = rtlphy->iqk_matrix[indx].value[0][4];
 304                        long y = rtlphy->iqk_matrix[indx].value[0][5];
 305                        rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
 306                }
 307        } else {
 308                return;
 309        }
 310}
 311
 312static void rtl88e_dm_diginit(struct ieee80211_hw *hw)
 313{
 314        struct rtl_priv *rtlpriv = rtl_priv(hw);
 315        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
 316
 317        dm_dig->dig_enable_flag = true;
 318        dm_dig->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 319        dm_dig->pre_igvalue = 0;
 320        dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
 321        dm_dig->presta_cstate = DIG_STA_DISCONNECT;
 322        dm_dig->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
 323        dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW;
 324        dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH;
 325        dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
 326        dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
 327        dm_dig->rx_gain_max = DM_DIG_MAX;
 328        dm_dig->rx_gain_min = DM_DIG_MIN;
 329        dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT;
 330        dm_dig->back_range_max = DM_DIG_BACKOFF_MAX;
 331        dm_dig->back_range_min = DM_DIG_BACKOFF_MIN;
 332        dm_dig->pre_cck_cca_thres = 0xff;
 333        dm_dig->cur_cck_cca_thres = 0x83;
 334        dm_dig->forbidden_igi = DM_DIG_MIN;
 335        dm_dig->large_fa_hit = 0;
 336        dm_dig->recover_cnt = 0;
 337        dm_dig->dig_min_0 = 0x25;
 338        dm_dig->dig_min_1 = 0x25;
 339        dm_dig->media_connect_0 = false;
 340        dm_dig->media_connect_1 = false;
 341        rtlpriv->dm.dm_initialgain_enable = true;
 342}
 343
 344static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 345{
 346        struct rtl_priv *rtlpriv = rtl_priv(hw);
 347        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
 348        long rssi_val_min = 0;
 349
 350        if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
 351            (dm_dig->cursta_cstate == DIG_STA_CONNECT)) {
 352                if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
 353                        rssi_val_min =
 354                            (rtlpriv->dm.entry_min_undec_sm_pwdb >
 355                            rtlpriv->dm.undec_sm_pwdb) ?
 356                            rtlpriv->dm.undec_sm_pwdb :
 357                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 358                else
 359                        rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 360        } else if (dm_dig->cursta_cstate == DIG_STA_CONNECT ||
 361                   dm_dig->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
 362                rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 363        } else if (dm_dig->curmultista_cstate ==
 364                DIG_MULTISTA_CONNECT) {
 365                rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
 366        }
 367        return (u8)rssi_val_min;
 368}
 369
 370static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 371{
 372        u32 ret_value;
 373        struct rtl_priv *rtlpriv = rtl_priv(hw);
 374        struct false_alarm_statistics *alm_cnt = &(rtlpriv->falsealm_cnt);
 375
 376        rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1);
 377        rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1);
 378
 379        ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
 380        alm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff);
 381        alm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16);
 382
 383        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
 384        alm_cnt->cnt_ofdm_cca = (ret_value&0xffff);
 385        alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
 386
 387        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
 388        alm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
 389        alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
 390
 391        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
 392        alm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
 393        alm_cnt->cnt_ofdm_fail = alm_cnt->cnt_parity_fail +
 394                                 alm_cnt->cnt_rate_illegal +
 395                                 alm_cnt->cnt_crc8_fail +
 396                                 alm_cnt->cnt_mcs_fail +
 397                                 alm_cnt->cnt_fast_fsync_fail +
 398                                 alm_cnt->cnt_sb_search_fail;
 399
 400        ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD);
 401        alm_cnt->cnt_bw_lsc = (ret_value & 0xffff);
 402        alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16);
 403
 404        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1);
 405        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
 406
 407        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
 408        alm_cnt->cnt_cck_fail = ret_value;
 409
 410        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
 411        alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 412
 413        ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD);
 414        alm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
 415                                ((ret_value&0xFF00)>>8);
 416
 417        alm_cnt->cnt_all = alm_cnt->cnt_fast_fsync_fail +
 418                           alm_cnt->cnt_sb_search_fail +
 419                           alm_cnt->cnt_parity_fail +
 420                           alm_cnt->cnt_rate_illegal +
 421                           alm_cnt->cnt_crc8_fail +
 422                           alm_cnt->cnt_mcs_fail +
 423                           alm_cnt->cnt_cck_fail;
 424        alm_cnt->cnt_cca_all = alm_cnt->cnt_ofdm_cca + alm_cnt->cnt_cck_cca;
 425
 426        rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1);
 427        rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0);
 428        rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1);
 429        rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0);
 430        rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
 431        rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
 432        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0);
 433        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2);
 434        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0);
 435        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2);
 436
 437        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 438                 "cnt_parity_fail = %d, cnt_rate_illegal = %d, "
 439                 "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 440                 alm_cnt->cnt_parity_fail,
 441                 alm_cnt->cnt_rate_illegal,
 442                 alm_cnt->cnt_crc8_fail, alm_cnt->cnt_mcs_fail);
 443
 444        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 445                 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 446                 alm_cnt->cnt_ofdm_fail,
 447                 alm_cnt->cnt_cck_fail, alm_cnt->cnt_all);
 448}
 449
 450static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 451{
 452        struct rtl_priv *rtlpriv = rtl_priv(hw);
 453        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
 454        u8 cur_cck_cca_thresh;
 455
 456        if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
 457                dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw);
 458                if (dm_dig->rssi_val_min > 25) {
 459                        cur_cck_cca_thresh = 0xcd;
 460                } else if ((dm_dig->rssi_val_min <= 25) &&
 461                           (dm_dig->rssi_val_min > 10)) {
 462                        cur_cck_cca_thresh = 0x83;
 463                } else {
 464                        if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
 465                                cur_cck_cca_thresh = 0x83;
 466                        else
 467                                cur_cck_cca_thresh = 0x40;
 468                }
 469
 470        } else {
 471                if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
 472                        cur_cck_cca_thresh = 0x83;
 473                else
 474                        cur_cck_cca_thresh = 0x40;
 475        }
 476
 477        if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh)
 478                rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
 479
 480        dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh;
 481        dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres;
 482        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 483                 "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres);
 484}
 485
 486static void rtl88e_dm_dig(struct ieee80211_hw *hw)
 487{
 488        struct rtl_priv *rtlpriv = rtl_priv(hw);
 489        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
 490        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 491        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 492        u8 dig_min, dig_maxofmin;
 493        bool bfirstconnect;
 494        u8 dm_dig_max, dm_dig_min;
 495        u8 current_igi = dm_dig->cur_igvalue;
 496
 497        if (rtlpriv->dm.dm_initialgain_enable == false)
 498                return;
 499        if (dm_dig->dig_enable_flag == false)
 500                return;
 501        if (mac->act_scanning == true)
 502                return;
 503
 504        if (mac->link_state >= MAC80211_LINKED)
 505                dm_dig->cursta_cstate = DIG_STA_CONNECT;
 506        else
 507                dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
 508        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
 509            rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
 510                dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
 511
 512        dm_dig_max = DM_DIG_MAX;
 513        dm_dig_min = DM_DIG_MIN;
 514        dig_maxofmin = DM_DIG_MAX_AP;
 515        dig_min = dm_dig->dig_min_0;
 516        bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) &&
 517                         (dm_dig->media_connect_0 == false);
 518
 519        dm_dig->rssi_val_min =
 520                rtl88e_dm_initial_gain_min_pwdb(hw);
 521
 522        if (mac->link_state >= MAC80211_LINKED) {
 523                if ((dm_dig->rssi_val_min + 20) > dm_dig_max)
 524                        dm_dig->rx_gain_max = dm_dig_max;
 525                else if ((dm_dig->rssi_val_min + 20) < dm_dig_min)
 526                        dm_dig->rx_gain_max = dm_dig_min;
 527                else
 528                        dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20;
 529
 530                if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
 531                        dig_min  = dm_dig->antdiv_rssi_max;
 532                } else {
 533                        if (dm_dig->rssi_val_min < dm_dig_min)
 534                                dig_min = dm_dig_min;
 535                        else if (dm_dig->rssi_val_min < dig_maxofmin)
 536                                dig_min = dig_maxofmin;
 537                        else
 538                                dig_min = dm_dig->rssi_val_min;
 539                }
 540        } else {
 541                dm_dig->rx_gain_max = dm_dig_max;
 542                dig_min = dm_dig_min;
 543                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
 544        }
 545
 546        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 547                dm_dig->large_fa_hit++;
 548                if (dm_dig->forbidden_igi < current_igi) {
 549                        dm_dig->forbidden_igi = current_igi;
 550                        dm_dig->large_fa_hit = 1;
 551                }
 552
 553                if (dm_dig->large_fa_hit >= 3) {
 554                        if ((dm_dig->forbidden_igi + 1) > dm_dig->rx_gain_max)
 555                                dm_dig->rx_gain_min = dm_dig->rx_gain_max;
 556                        else
 557                                dm_dig->rx_gain_min = dm_dig->forbidden_igi + 1;
 558                        dm_dig->recover_cnt = 3600;
 559                }
 560        } else {
 561                if (dm_dig->recover_cnt != 0) {
 562                        dm_dig->recover_cnt--;
 563                } else {
 564                        if (dm_dig->large_fa_hit == 0) {
 565                                if ((dm_dig->forbidden_igi - 1) < dig_min) {
 566                                        dm_dig->forbidden_igi = dig_min;
 567                                        dm_dig->rx_gain_min = dig_min;
 568                                } else {
 569                                        dm_dig->forbidden_igi--;
 570                                        dm_dig->rx_gain_min =
 571                                                 dm_dig->forbidden_igi + 1;
 572                                }
 573                        } else if (dm_dig->large_fa_hit == 3) {
 574                                dm_dig->large_fa_hit = 0;
 575                        }
 576                }
 577        }
 578
 579        if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
 580                if (bfirstconnect) {
 581                        current_igi = dm_dig->rssi_val_min;
 582                } else {
 583                        if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 584                                current_igi += 2;
 585                        else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 586                                current_igi++;
 587                        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 588                                current_igi--;
 589                }
 590        } else {
 591                if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 592                        current_igi += 2;
 593                else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
 594                        current_igi++;
 595                else if (rtlpriv->falsealm_cnt.cnt_all < 500)
 596                        current_igi--;
 597        }
 598
 599        if (current_igi > DM_DIG_FA_UPPER)
 600                current_igi = DM_DIG_FA_UPPER;
 601        else if (current_igi < DM_DIG_FA_LOWER)
 602                current_igi = DM_DIG_FA_LOWER;
 603
 604        if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 605                current_igi = DM_DIG_FA_UPPER;
 606
 607        dm_dig->cur_igvalue = current_igi;
 608        rtl88e_dm_write_dig(hw);
 609        dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ?
 610                                    true : false);
 611        dm_dig->dig_min_0 = dig_min;
 612
 613        rtl88e_dm_cck_packet_detection_thresh(hw);
 614}
 615
 616static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
 617{
 618        struct rtl_priv *rtlpriv = rtl_priv(hw);
 619
 620        rtlpriv->dm.dynamic_txpower_enable = false;
 621
 622        rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
 623        rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 624}
 625
 626static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
 627{
 628        struct rtl_priv *rtlpriv = rtl_priv(hw);
 629        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 630        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 631        long undec_sm_pwdb;
 632
 633        if (!rtlpriv->dm.dynamic_txpower_enable)
 634                return;
 635
 636        if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
 637                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 638                return;
 639        }
 640
 641        if ((mac->link_state < MAC80211_LINKED) &&
 642            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 643                RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 644                         "Not connected\n");
 645
 646                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 647
 648                rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
 649                return;
 650        }
 651
 652        if (mac->link_state >= MAC80211_LINKED) {
 653                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 654                        undec_sm_pwdb =
 655                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 656                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 657                                 "AP Client PWDB = 0x%lx\n",
 658                                  undec_sm_pwdb);
 659                } else {
 660                        undec_sm_pwdb =
 661                            rtlpriv->dm.undec_sm_pwdb;
 662                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 663                                 "STA Default Port PWDB = 0x%lx\n",
 664                                  undec_sm_pwdb);
 665                }
 666        } else {
 667                undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 668
 669                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 670                         "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb);
 671        }
 672
 673        if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 674                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 675                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 676                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n");
 677        } else if ((undec_sm_pwdb <
 678                    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
 679                   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 680                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 681                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 682                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n");
 683        } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 684                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 685                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 686                         "TXHIGHPWRLEVEL_NORMAL\n");
 687        }
 688
 689        if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
 690                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 691                         "PHY_SetTxPowerLevel8192S() Channel = %d\n",
 692                          rtlphy->current_channel);
 693                rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel);
 694        }
 695
 696        rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
 697}
 698
 699void rtl88e_dm_write_dig(struct ieee80211_hw *hw)
 700{
 701        struct rtl_priv *rtlpriv = rtl_priv(hw);
 702        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
 703
 704        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 705                 "cur_igvalue = 0x%x, "
 706                  "pre_igvalue = 0x%x, back_val = %d\n",
 707                  dm_dig->cur_igvalue, dm_dig->pre_igvalue,
 708                  dm_dig->back_val);
 709
 710        if (dm_dig->cur_igvalue > 0x3f)
 711                dm_dig->cur_igvalue = 0x3f;
 712        if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) {
 713                rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 714                              dm_dig->cur_igvalue);
 715
 716                dm_dig->pre_igvalue = dm_dig->cur_igvalue;
 717        }
 718}
 719
 720static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw)
 721{
 722        struct rtl_priv *rtlpriv = rtl_priv(hw);
 723        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 724        struct rtl_sta_info *drv_priv;
 725        static u64 last_txok;
 726        static u64 last_rx;
 727        long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 728
 729        if (rtlhal->oem_id == RT_CID_819x_HP) {
 730                u64 cur_txok_cnt = 0;
 731                u64 cur_rxok_cnt = 0;
 732                cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok;
 733                cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rx;
 734                last_txok = cur_txok_cnt;
 735                last_rx = cur_rxok_cnt;
 736
 737                if (cur_rxok_cnt > (cur_txok_cnt * 6))
 738                        rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015);
 739                else
 740                        rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015);
 741        }
 742
 743        /* AP & ADHOC & MESH */
 744        spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 745        list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 746                if (drv_priv->rssi_stat.undec_sm_pwdb < tmp_entry_min_pwdb)
 747                        tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
 748                if (drv_priv->rssi_stat.undec_sm_pwdb > tmp_entry_max_pwdb)
 749                        tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
 750        }
 751        spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 752
 753        /* If associated entry is found */
 754        if (tmp_entry_max_pwdb != 0) {
 755                rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb;
 756                RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n",
 757                        tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 758        } else {
 759                rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 760        }
 761        /* If associated entry is found */
 762        if (tmp_entry_min_pwdb != 0xff) {
 763                rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb;
 764                RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n",
 765                        tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 766        } else {
 767                rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 768        }
 769        /* Indicate Rx signal strength to FW. */
 770        if (!rtlpriv->dm.useramask)
 771                rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
 772}
 773
 774void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw)
 775{
 776        struct rtl_priv *rtlpriv = rtl_priv(hw);
 777
 778        rtlpriv->dm.current_turbo_edca = false;
 779        rtlpriv->dm.is_any_nonbepkts = false;
 780        rtlpriv->dm.is_cur_rdlstate = false;
 781}
 782
 783static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw)
 784{
 785        struct rtl_priv *rtlpriv = rtl_priv(hw);
 786        struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
 787        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 788        static u64 last_txok_cnt;
 789        static u64 last_rxok_cnt;
 790        static u32 last_bt_edca_ul;
 791        static u32 last_bt_edca_dl;
 792        u64 cur_txok_cnt = 0;
 793        u64 cur_rxok_cnt = 0;
 794        u32 edca_be_ul = 0x5ea42b;
 795        u32 edca_be_dl = 0x5ea42b;
 796        bool change_edca = false;
 797
 798        if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
 799            (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
 800                rtlpriv->dm.current_turbo_edca = false;
 801                last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
 802                last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
 803        }
 804
 805        if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
 806                edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
 807                change_edca = true;
 808        }
 809
 810        if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
 811                edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
 812                change_edca = true;
 813        }
 814
 815        if (mac->link_state != MAC80211_LINKED) {
 816                rtlpriv->dm.current_turbo_edca = false;
 817                return;
 818        }
 819
 820        if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
 821                if (!(edca_be_ul & 0xffff0000))
 822                        edca_be_ul |= 0x005e0000;
 823
 824                if (!(edca_be_dl & 0xffff0000))
 825                        edca_be_dl |= 0x005e0000;
 826        }
 827
 828        if ((change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
 829                              (!rtlpriv->dm.disable_framebursting))) {
 830                cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
 831                cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
 832
 833                if (cur_rxok_cnt > 4 * cur_txok_cnt) {
 834                        if (!rtlpriv->dm.is_cur_rdlstate ||
 835                            !rtlpriv->dm.current_turbo_edca) {
 836                                rtl_write_dword(rtlpriv,
 837                                                REG_EDCA_BE_PARAM,
 838                                                edca_be_dl);
 839                                rtlpriv->dm.is_cur_rdlstate = true;
 840                        }
 841                } else {
 842                        if (rtlpriv->dm.is_cur_rdlstate ||
 843                            !rtlpriv->dm.current_turbo_edca) {
 844                                rtl_write_dword(rtlpriv,
 845                                                REG_EDCA_BE_PARAM,
 846                                                edca_be_ul);
 847                                rtlpriv->dm.is_cur_rdlstate = false;
 848                        }
 849                }
 850                rtlpriv->dm.current_turbo_edca = true;
 851        } else {
 852                if (rtlpriv->dm.current_turbo_edca) {
 853                        u8 tmp = AC0_BE;
 854                        rtlpriv->cfg->ops->set_hw_reg(hw,
 855                                                      HW_VAR_AC_PARAM,
 856                                                      (u8 *)(&tmp));
 857                        rtlpriv->dm.current_turbo_edca = false;
 858                }
 859        }
 860
 861        rtlpriv->dm.is_any_nonbepkts = false;
 862        last_txok_cnt = rtlpriv->stats.txbytesunicast;
 863        last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
 864}
 865
 866static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
 867                                                             *hw)
 868{
 869        struct rtl_priv *rtlpriv = rtl_priv(hw);
 870        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 871        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
 872        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 873        u8 thermalvalue = 0, delta, delta_lck, delta_iqk, off;
 874        u8 th_avg_cnt = 0;
 875        u32 thermalvalue_avg = 0;
 876        long  ele_d, temp_cck;
 877        char ofdm_index[2], cck_index = 0, ofdm_old[2] = {0, 0}, cck_old = 0;
 878        int i = 0;
 879        bool is2t = false;
 880
 881        u8 ofdm_min_index = 6, rf = (is2t) ? 2 : 1;
 882        u8 index_for_channel;
 883        enum _dec_inc {dec, power_inc};
 884
 885        /* 0.1 the following TWO tables decide the final index of
 886         * OFDM/CCK swing table
 887         */
 888        char del_tbl_idx[2][15] = {
 889                {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
 890                {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10}
 891        };
 892        u8 thermal_threshold[2][15] = {
 893                {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
 894                {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25}
 895        };
 896
 897        /*Initilization (7 steps in total) */
 898        rtlpriv->dm.txpower_trackinginit = true;
 899        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 900                 "rtl88e_dm_txpower_tracking_callback_thermalmeter\n");
 901
 902        thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00);
 903        if (!thermalvalue)
 904                return;
 905        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 906                 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
 907                 thermalvalue, rtlpriv->dm.thermalvalue,
 908                 rtlefuse->eeprom_thermalmeter);
 909
 910        /*1. Query OFDM Default Setting: Path A*/
 911        ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD) & MASKOFDM_D;
 912        for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
 913                if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
 914                        ofdm_old[0] = (u8) i;
 915                        rtldm->swing_idx_ofdm_base = (u8)i;
 916                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 917                                 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
 918                                 ROFDM0_XATXIQIMBAL,
 919                                 ele_d, ofdm_old[0]);
 920                        break;
 921                }
 922        }
 923
 924        if (is2t) {
 925                ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBAL,
 926                                      MASKDWORD) & MASKOFDM_D;
 927                for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
 928                        if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
 929                                ofdm_old[1] = (u8)i;
 930
 931                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
 932                                         DBG_LOUD,
 933                                         "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
 934                                         ROFDM0_XBTXIQIMBAL, ele_d,
 935                                         ofdm_old[1]);
 936                                break;
 937                        }
 938                }
 939        }
 940        /*2.Query CCK default setting From 0xa24*/
 941        temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
 942        for (i = 0; i < CCK_TABLE_LENGTH; i++) {
 943                if (rtlpriv->dm.cck_inch14) {
 944                        if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) {
 945                                cck_old = (u8)i;
 946                                rtldm->swing_idx_cck_base = (u8)i;
 947                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 948                                         "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n",
 949                                         RCCK0_TXFILTER2, temp_cck, cck_old,
 950                                         rtlpriv->dm.cck_inch14);
 951                                break;
 952                        }
 953                } else {
 954                        if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) {
 955                                cck_old = (u8)i;
 956                                rtldm->swing_idx_cck_base = (u8)i;
 957                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 958                                         "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n",
 959                                         RCCK0_TXFILTER2, temp_cck, cck_old,
 960                                         rtlpriv->dm.cck_inch14);
 961                                break;
 962                        }
 963                }
 964        }
 965
 966        /*3 Initialize ThermalValues of RFCalibrateInfo*/
 967        if (!rtldm->thermalvalue) {
 968                rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter;
 969                rtlpriv->dm.thermalvalue_lck = thermalvalue;
 970                rtlpriv->dm.thermalvalue_iqk = thermalvalue;
 971                for (i = 0; i < rf; i++)
 972                        rtlpriv->dm.ofdm_index[i] = ofdm_old[i];
 973                rtlpriv->dm.cck_index = cck_old;
 974        }
 975
 976        /*4 Calculate average thermal meter*/
 977        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
 978        rtldm->thermalvalue_avg_index++;
 979        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E)
 980                rtldm->thermalvalue_avg_index = 0;
 981
 982        for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
 983                if (rtldm->thermalvalue_avg[i]) {
 984                        thermalvalue_avg += rtldm->thermalvalue_avg[i];
 985                        th_avg_cnt++;
 986                }
 987        }
 988
 989        if (th_avg_cnt)
 990                thermalvalue = (u8)(thermalvalue_avg / th_avg_cnt);
 991
 992        /* 5 Calculate delta, delta_LCK, delta_IQK.*/
 993        if (rtlhal->reloadtxpowerindex) {
 994                delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
 995                    (thermalvalue - rtlefuse->eeprom_thermalmeter) :
 996                    (rtlefuse->eeprom_thermalmeter - thermalvalue);
 997                rtlhal->reloadtxpowerindex = false;
 998                rtlpriv->dm.done_txpower = false;
 999        } else if (rtlpriv->dm.done_txpower) {
1000                delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
1001                        (thermalvalue - rtlpriv->dm.thermalvalue) :
1002                        (rtlpriv->dm.thermalvalue - thermalvalue);
1003        } else {
1004                delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
1005                        (thermalvalue - rtlefuse->eeprom_thermalmeter) :
1006                        (rtlefuse->eeprom_thermalmeter - thermalvalue);
1007        }
1008        delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
1009                    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
1010                    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
1011        delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
1012                    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
1013                    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
1014
1015        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1016                 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
1017                 "eeprom_thermalmeter 0x%x delta 0x%x "
1018                 "delta_lck 0x%x delta_iqk 0x%x\n",
1019                 thermalvalue, rtlpriv->dm.thermalvalue,
1020                 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
1021                 delta_iqk);
1022        /* 6 If necessary, do LCK.*/
1023        if (delta_lck >= 8) {
1024                rtlpriv->dm.thermalvalue_lck = thermalvalue;
1025                rtl88e_phy_lc_calibrate(hw);
1026        }
1027
1028        /* 7 If necessary, move the index of swing table to adjust Tx power. */
1029        if (delta > 0 && rtlpriv->dm.txpower_track_control) {
1030                delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
1031                        (thermalvalue - rtlefuse->eeprom_thermalmeter) :
1032                        (rtlefuse->eeprom_thermalmeter - thermalvalue);
1033
1034                /* 7.1 Get the final CCK_index and OFDM_index for each
1035                 * swing table.
1036                 */
1037                if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
1038                        CAL_SWING_OFF(off, power_inc, IDX_MAP, delta);
1039                        for (i = 0; i < rf; i++)
1040                                ofdm_index[i] = rtldm->ofdm_index[i] +
1041                                                del_tbl_idx[power_inc][off];
1042                        cck_index = rtldm->cck_index +
1043                                    del_tbl_idx[power_inc][off];
1044                } else {
1045                        CAL_SWING_OFF(off, dec, IDX_MAP, delta);
1046                        for (i = 0; i < rf; i++)
1047                                ofdm_index[i] = rtldm->ofdm_index[i] +
1048                                                del_tbl_idx[dec][off];
1049                        cck_index = rtldm->cck_index + del_tbl_idx[dec][off];
1050                }
1051
1052                /* 7.2 Handle boundary conditions of index.*/
1053                for (i = 0; i < rf; i++) {
1054                        if (ofdm_index[i] > OFDM_TABLE_SIZE-1)
1055                                ofdm_index[i] = OFDM_TABLE_SIZE-1;
1056                        else if (rtldm->ofdm_index[i] < ofdm_min_index)
1057                                ofdm_index[i] = ofdm_min_index;
1058                }
1059
1060                if (cck_index > CCK_TABLE_SIZE - 1)
1061                        cck_index = CCK_TABLE_SIZE - 1;
1062                else if (cck_index < 0)
1063                        cck_index = 0;
1064
1065                /*7.3Configure the Swing Table to adjust Tx Power.*/
1066                if (rtlpriv->dm.txpower_track_control) {
1067                        rtldm->done_txpower = true;
1068                        rtldm->swing_idx_ofdm[RF90_PATH_A] =
1069                                 (u8)ofdm_index[RF90_PATH_A];
1070                        if (is2t)
1071                                rtldm->swing_idx_ofdm[RF90_PATH_B] =
1072                                         (u8)ofdm_index[RF90_PATH_B];
1073                        rtldm->swing_idx_cck = cck_index;
1074                        if (rtldm->swing_idx_ofdm_cur !=
1075                            rtldm->swing_idx_ofdm[0]) {
1076                                rtldm->swing_idx_ofdm_cur =
1077                                         rtldm->swing_idx_ofdm[0];
1078                                rtldm->swing_flag_ofdm = true;
1079                        }
1080
1081                        if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) {
1082                                rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck;
1083                                rtldm->swing_flag_cck = true;
1084                        }
1085
1086                        rtl88e_chk_tx_track(hw, TXAGC, 0, 0);
1087
1088                        if (is2t)
1089                                rtl88e_chk_tx_track(hw, BBSWING,
1090                                                    RF90_PATH_B,
1091                                                    index_for_channel);
1092                }
1093        }
1094
1095        if (delta_iqk >= 8) {
1096                rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1097                rtl88e_phy_iq_calibrate(hw, false);
1098        }
1099
1100        if (rtldm->txpower_track_control)
1101                rtldm->thermalvalue = thermalvalue;
1102        rtldm->txpowercount = 0;
1103        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
1104}
1105
1106static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw)
1107{
1108        struct rtl_priv *rtlpriv = rtl_priv(hw);
1109
1110        rtlpriv->dm.txpower_tracking = true;
1111        rtlpriv->dm.txpower_trackinginit = false;
1112        rtlpriv->dm.txpowercount = 0;
1113        rtlpriv->dm.txpower_track_control = true;
1114
1115        rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12;
1116        rtlpriv->dm.swing_idx_ofdm_cur = 12;
1117        rtlpriv->dm.swing_flag_ofdm = false;
1118        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1119                 "  rtlpriv->dm.txpower_tracking = %d\n",
1120                 rtlpriv->dm.txpower_tracking);
1121}
1122
1123void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1124{
1125        struct rtl_priv *rtlpriv = rtl_priv(hw);
1126        static u8 tm_trigger;
1127
1128        if (!rtlpriv->dm.txpower_tracking)
1129                return;
1130
1131        if (!tm_trigger) {
1132                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16),
1133                              0x03);
1134                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1135                         "Trigger 88E Thermal Meter!!\n");
1136                tm_trigger = 1;
1137                return;
1138        } else {
1139                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1140                         "Schedule TxPowerTracking !!\n");
1141                rtl88e_dm_txpower_tracking_callback_thermalmeter(hw);
1142                tm_trigger = 0;
1143        }
1144}
1145
1146void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1147{
1148        struct rtl_priv *rtlpriv = rtl_priv(hw);
1149        struct rate_adaptive *p_ra = &(rtlpriv->ra);
1150
1151        p_ra->ratr_state = DM_RATR_STA_INIT;
1152        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1153
1154        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1155                rtlpriv->dm.useramask = true;
1156        else
1157                rtlpriv->dm.useramask = false;
1158}
1159
1160static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
1161{
1162        struct rtl_priv *rtlpriv = rtl_priv(hw);
1163        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1164        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1165        struct rate_adaptive *p_ra = &(rtlpriv->ra);
1166        struct ieee80211_sta *sta = NULL;
1167        u32 low_rssi, hi_rssi;
1168
1169        if (is_hal_stop(rtlhal)) {
1170                RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1171                         "driver is going to unload\n");
1172                return;
1173        }
1174
1175        if (!rtlpriv->dm.useramask) {
1176                RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1177                         "driver does not control rate adaptive mask\n");
1178                return;
1179        }
1180
1181        if (mac->link_state == MAC80211_LINKED &&
1182            mac->opmode == NL80211_IFTYPE_STATION) {
1183                switch (p_ra->pre_ratr_state) {
1184                case DM_RATR_STA_HIGH:
1185                        hi_rssi = 50;
1186                        low_rssi = 20;
1187                        break;
1188                case DM_RATR_STA_MIDDLE:
1189                        hi_rssi = 55;
1190                        low_rssi = 20;
1191                        break;
1192                case DM_RATR_STA_LOW:
1193                        hi_rssi = 50;
1194                        low_rssi = 25;
1195                        break;
1196                default:
1197                        hi_rssi = 50;
1198                        low_rssi = 20;
1199                        break;
1200                }
1201
1202                if (rtlpriv->dm.undec_sm_pwdb > (long)hi_rssi)
1203                        p_ra->ratr_state = DM_RATR_STA_HIGH;
1204                else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi)
1205                        p_ra->ratr_state = DM_RATR_STA_MIDDLE;
1206                else
1207                        p_ra->ratr_state = DM_RATR_STA_LOW;
1208
1209                if (p_ra->pre_ratr_state != p_ra->ratr_state) {
1210                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1211                                 "RSSI = %ld\n",
1212                                 rtlpriv->dm.undec_sm_pwdb);
1213                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1214                                 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
1215                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1216                                 "PreState = %d, CurState = %d\n",
1217                                  p_ra->pre_ratr_state, p_ra->ratr_state);
1218
1219                        rcu_read_lock();
1220                        sta = rtl_find_sta(hw, mac->bssid);
1221                        if (sta)
1222                                rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
1223                                                   p_ra->ratr_state);
1224                        rcu_read_unlock();
1225
1226                        p_ra->pre_ratr_state = p_ra->ratr_state;
1227                }
1228        }
1229}
1230
1231static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1232{
1233        struct rtl_priv *rtlpriv = rtl_priv(hw);
1234        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1235
1236        dm_pstable->pre_ccastate = CCA_MAX;
1237        dm_pstable->cur_ccasate = CCA_MAX;
1238        dm_pstable->pre_rfstate = RF_MAX;
1239        dm_pstable->cur_rfstate = RF_MAX;
1240        dm_pstable->rssi_val_min = 0;
1241}
1242
1243static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, u8 ant)
1244{
1245        struct rtl_priv *rtlpriv = rtl_priv(hw);
1246        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1247        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1248        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1249        u32 def_ant, opt_ant;
1250
1251        if (fat_tbl->rx_idle_ant != ant) {
1252                RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1253                         "need to update rx idle ant\n");
1254                if (ant == MAIN_ANT) {
1255                        def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
1256                                   MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
1257                        opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
1258                                   AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
1259                } else {
1260                        def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
1261                                   AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
1262                        opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
1263                                   MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
1264                }
1265
1266                if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
1267                        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
1268                                      BIT(4) | BIT(3), def_ant);
1269                        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
1270                                      BIT(7) | BIT(6), opt_ant);
1271                        rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, BIT(14) |
1272                                      BIT(13) | BIT(12), def_ant);
1273                        rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, BIT(6) | BIT(7),
1274                                      def_ant);
1275                } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
1276                        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
1277                                      BIT(4) | BIT(3), def_ant);
1278                        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
1279                                      BIT(7) | BIT(6), opt_ant);
1280                }
1281        }
1282        fat_tbl->rx_idle_ant = ant;
1283        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n",
1284                 ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
1285}
1286
1287static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw,
1288        u8 ant, u32 mac_id)
1289{
1290        struct rtl_priv *rtlpriv = rtl_priv(hw);
1291        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1292        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1293        u8 target_ant;
1294
1295        if (ant == MAIN_ANT)
1296                target_ant = MAIN_ANT_CG_TRX;
1297        else
1298                target_ant = AUX_ANT_CG_TRX;
1299
1300        fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
1301        fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
1302        fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
1303        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n",
1304                 ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
1305        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n",
1306                 fat_tbl->antsel_c[mac_id],
1307                 fat_tbl->antsel_b[mac_id], fat_tbl->antsel_a[mac_id]);
1308}
1309
1310static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw)
1311{
1312        u32  value32;
1313        /*MAC Setting*/
1314        value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
1315        rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
1316                     (BIT(23) | BIT(25)));
1317        /*Pin Setting*/
1318        rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
1319        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
1320        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1);
1321        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
1322        /*OFDM Setting*/
1323        rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
1324        /*CCK Setting*/
1325        rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
1326        rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
1327        rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
1328        rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
1329}
1330
1331static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw)
1332{
1333        u32  value32;
1334
1335        /*MAC Setting*/
1336        value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
1337        rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
1338                     (BIT(23) | BIT(25)));
1339        /*Pin Setting*/
1340        rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
1341        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
1342        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
1343        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
1344        /*OFDM Setting*/
1345        rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
1346        /*CCK Setting*/
1347        rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
1348        rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
1349        /*TX Setting*/
1350        rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
1351        rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
1352        rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
1353}
1354
1355static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw)
1356{
1357        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1358        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1359        u32 ant_combo = 2;
1360        u32 value32, i;
1361
1362        for (i = 0; i < 6; i++) {
1363                fat_tbl->bssid[i] = 0;
1364                fat_tbl->ant_sum[i] = 0;
1365                fat_tbl->ant_cnt[i] = 0;
1366                fat_tbl->ant_ave[i] = 0;
1367        }
1368        fat_tbl->train_idx = 0;
1369        fat_tbl->fat_state = FAT_NORMAL_STATE;
1370
1371        /*MAC Setting*/
1372        value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
1373        rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) |
1374                      BIT(25)));
1375        value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD);
1376        rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD, value32 | (BIT(16) |
1377                      BIT(17)));
1378        rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKLWORD, 0);
1379        rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, MASKDWORD, 0);
1380
1381        /*Pin Setting*/
1382        rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
1383        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
1384        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
1385        rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
1386
1387        /*OFDM Setting*/
1388        rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
1389        /*antenna mapping table*/
1390        if (ant_combo == 2) {
1391                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
1392                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
1393        } else if (ant_combo == 7) {
1394                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
1395                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
1396                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE2, 2);
1397                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE3, 3);
1398                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE0, 4);
1399                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE1, 5);
1400                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE2, 6);
1401                rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE3, 7);
1402        }
1403
1404        /*TX Setting*/
1405        rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
1406        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0);
1407        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), 1);
1408        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(2) | BIT(1) | BIT(0),
1409                      (ant_combo - 1));
1410
1411        rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
1412}
1413
1414static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw)
1415{
1416        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1417
1418        if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
1419                rtl88e_dm_rx_hw_antena_div_init(hw);
1420        else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
1421                rtl88e_dm_trx_hw_antenna_div_init(hw);
1422        else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
1423                rtl88e_dm_fast_training_init(hw);
1424}
1425
1426void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
1427                                     u8 *pdesc, u32 mac_id)
1428{
1429        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1430        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1431        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1432
1433        if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
1434            (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) {
1435                SET_TX_DESC_ANTSEL_A(pdesc, fat_tbl->antsel_a[mac_id]);
1436                SET_TX_DESC_ANTSEL_B(pdesc, fat_tbl->antsel_b[mac_id]);
1437                SET_TX_DESC_ANTSEL_C(pdesc, fat_tbl->antsel_c[mac_id]);
1438        }
1439}
1440
1441void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw,
1442                                  u8 antsel_tr_mux, u32 mac_id, u32 rx_pwdb_all)
1443{
1444        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1445        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1446        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1447
1448        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
1449                if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
1450                        fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
1451                        fat_tbl->main_ant_cnt[mac_id]++;
1452                } else {
1453                        fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
1454                        fat_tbl->aux_ant_cnt[mac_id]++;
1455                }
1456        } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
1457                if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
1458                        fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
1459                        fat_tbl->main_ant_cnt[mac_id]++;
1460                } else {
1461                        fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
1462                        fat_tbl->aux_ant_cnt[mac_id]++;
1463                }
1464        }
1465}
1466
1467static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw)
1468{
1469        struct rtl_priv *rtlpriv = rtl_priv(hw);
1470        struct dig_t *dm_dig = &rtlpriv->dm_digtable;
1471        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1472        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1473        struct rtl_sta_info *drv_priv;
1474        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1475        u32 i, min_rssi = 0xff, ant_div_max_rssi = 0, max_rssi = 0;
1476        u32 local_min_rssi, local_max_rssi;
1477        u32 main_rssi, aux_rssi;
1478        u8 rx_idle_ant = 0, target_ant = 7;
1479
1480        i = 0;
1481        main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
1482                    (fat_tbl->main_ant_sum[i] /
1483                     fat_tbl->main_ant_cnt[i]) : 0;
1484        aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
1485                (fat_tbl->aux_ant_sum[i] / fat_tbl->aux_ant_cnt[i]) : 0;
1486        target_ant = (main_rssi == aux_rssi) ?
1487                     fat_tbl->rx_idle_ant : ((main_rssi >= aux_rssi) ?
1488                     MAIN_ANT : AUX_ANT);
1489        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1490                 "main_ant_sum %d main_ant_cnt %d\n",
1491                 fat_tbl->main_ant_sum[i], fat_tbl->main_ant_cnt[i]);
1492        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1493                 "aux_ant_sum %d aux_ant_cnt %d\n",
1494                 fat_tbl->aux_ant_sum[i],
1495                 fat_tbl->aux_ant_cnt[i]);
1496        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1497                 "main_rssi %d aux_rssi%d\n", main_rssi, aux_rssi);
1498        local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi;
1499        if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40))
1500                ant_div_max_rssi = local_max_rssi;
1501        if (local_max_rssi > max_rssi)
1502                max_rssi = local_max_rssi;
1503
1504        if ((fat_tbl->rx_idle_ant == MAIN_ANT) && (main_rssi == 0))
1505                main_rssi = aux_rssi;
1506        else if ((fat_tbl->rx_idle_ant == AUX_ANT) && (aux_rssi == 0))
1507                aux_rssi = main_rssi;
1508
1509        local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi;
1510        if (local_min_rssi < min_rssi) {
1511                min_rssi = local_min_rssi;
1512                rx_idle_ant = target_ant;
1513        }
1514        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
1515                rtl88e_dm_update_tx_ant(hw, target_ant, i);
1516
1517        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1518            rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) {
1519                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1520                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1521                        i++;
1522                        main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
1523                                (fat_tbl->main_ant_sum[i] /
1524                                 fat_tbl->main_ant_cnt[i]) : 0;
1525                        aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
1526                                   (fat_tbl->aux_ant_sum[i] /
1527                                    fat_tbl->aux_ant_cnt[i]) : 0;
1528                        target_ant = (main_rssi == aux_rssi) ?
1529                                      fat_tbl->rx_idle_ant : ((main_rssi >=
1530                                      aux_rssi) ? MAIN_ANT : AUX_ANT);
1531
1532
1533                        local_max_rssi = max_t(u32, main_rssi, aux_rssi);
1534                        if ((local_max_rssi > ant_div_max_rssi) &&
1535                            (local_max_rssi < 40))
1536                                ant_div_max_rssi = local_max_rssi;
1537                        if (local_max_rssi > max_rssi)
1538                                max_rssi = local_max_rssi;
1539
1540                        if ((fat_tbl->rx_idle_ant == MAIN_ANT) && !main_rssi)
1541                                main_rssi = aux_rssi;
1542                        else if ((fat_tbl->rx_idle_ant == AUX_ANT) &&
1543                                 (aux_rssi == 0))
1544                                aux_rssi = main_rssi;
1545
1546                        local_min_rssi = (main_rssi > aux_rssi) ?
1547                                          aux_rssi : main_rssi;
1548                        if (local_min_rssi < min_rssi) {
1549                                min_rssi = local_min_rssi;
1550                                rx_idle_ant = target_ant;
1551                        }
1552                        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
1553                                rtl88e_dm_update_tx_ant(hw, target_ant, i);
1554                }
1555                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1556        }
1557
1558        for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
1559                fat_tbl->main_ant_sum[i] = 0;
1560                fat_tbl->aux_ant_sum[i] = 0;
1561                fat_tbl->main_ant_cnt[i] = 0;
1562                fat_tbl->aux_ant_cnt[i] = 0;
1563        }
1564
1565        rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant);
1566
1567        dm_dig->antdiv_rssi_max = ant_div_max_rssi;
1568        dm_dig->rssi_max = max_rssi;
1569}
1570
1571static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw)
1572{
1573        struct rtl_priv *rtlpriv = rtl_priv(hw);
1574        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1575        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1576        struct rtl_sta_info *drv_priv;
1577        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1578        u32 value32, i, j = 0;
1579
1580        if (mac->link_state >= MAC80211_LINKED) {
1581                for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
1582                        if ((fat_tbl->train_idx + 1) == ASSOCIATE_ENTRY_NUM)
1583                                fat_tbl->train_idx = 0;
1584                        else
1585                                fat_tbl->train_idx++;
1586
1587                        if (fat_tbl->train_idx == 0) {
1588                                value32 = (mac->mac_addr[5] << 8) |
1589                                           mac->mac_addr[4];
1590                                rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
1591                                              MASKLWORD, value32);
1592
1593                                value32 = (mac->mac_addr[3] << 24) |
1594                                          (mac->mac_addr[2] << 16) |
1595                                          (mac->mac_addr[1] << 8) |
1596                                           mac->mac_addr[0];
1597                                rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
1598                                              MASKDWORD, value32);
1599                                break;
1600                        }
1601
1602                        if (rtlpriv->mac80211.opmode !=
1603                            NL80211_IFTYPE_STATION) {
1604                                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1605                                list_for_each_entry(drv_priv,
1606                                                    &rtlpriv->entry_list,
1607                                                    list) {
1608                                        j++;
1609                                        if (j != fat_tbl->train_idx)
1610                                                continue;
1611
1612                                        value32 = (drv_priv->mac_addr[5] << 8) |
1613                                                   drv_priv->mac_addr[4];
1614                                        rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
1615                                                      MASKLWORD, value32);
1616
1617                                        value32 = (drv_priv->mac_addr[3]<<24) |
1618                                                  (drv_priv->mac_addr[2]<<16) |
1619                                                  (drv_priv->mac_addr[1]<<8) |
1620                                                   drv_priv->mac_addr[0];
1621                                        rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
1622                                                      MASKDWORD, value32);
1623                                        break;
1624                                }
1625                                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1626                                /*find entry, break*/
1627                                if (j == fat_tbl->train_idx)
1628                                        break;
1629                        }
1630                }
1631        }
1632}
1633
1634static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw)
1635{
1636        struct rtl_priv *rtlpriv = rtl_priv(hw);
1637        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1638        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1639        u32 i, max_rssi = 0;
1640        u8 target_ant = 2;
1641        bool bpkt_filter_match = false;
1642
1643        if (fat_tbl->fat_state == FAT_TRAINING_STATE) {
1644                for (i = 0; i < 7; i++) {
1645                        if (fat_tbl->ant_cnt[i] == 0) {
1646                                fat_tbl->ant_ave[i] = 0;
1647                        } else {
1648                                fat_tbl->ant_ave[i] = fat_tbl->ant_sum[i] /
1649                                        fat_tbl->ant_cnt[i];
1650                                bpkt_filter_match = true;
1651                        }
1652
1653                        if (fat_tbl->ant_ave[i] > max_rssi) {
1654                                max_rssi = fat_tbl->ant_ave[i];
1655                                target_ant = (u8) i;
1656                        }
1657                }
1658
1659                if (bpkt_filter_match == false) {
1660                        rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
1661                                      BIT(16), 0);
1662                        rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
1663                } else {
1664                        rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
1665                                      BIT(16), 0);
1666                        rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
1667                                      BIT(7) | BIT(6), target_ant);
1668                        rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
1669
1670                        fat_tbl->antsel_a[fat_tbl->train_idx] =
1671                                  target_ant & BIT(0);
1672                        fat_tbl->antsel_b[fat_tbl->train_idx] =
1673                                 (target_ant & BIT(1)) >> 1;
1674                        fat_tbl->antsel_c[fat_tbl->train_idx] =
1675                                 (target_ant & BIT(2)) >> 2;
1676
1677                        if (target_ant == 0)
1678                                rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
1679                }
1680
1681                for (i = 0; i < 7; i++) {
1682                        fat_tbl->ant_sum[i] = 0;
1683                        fat_tbl->ant_cnt[i] = 0;
1684                }
1685
1686                fat_tbl->fat_state = FAT_NORMAL_STATE;
1687                return;
1688        }
1689
1690        if (fat_tbl->fat_state == FAT_NORMAL_STATE) {
1691                rtl88e_set_next_mac_address_target(hw);
1692
1693                fat_tbl->fat_state = FAT_TRAINING_STATE;
1694                rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1);
1695                rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
1696
1697                mod_timer(&rtlpriv->works.fast_antenna_training_timer,
1698                          jiffies + MSECS(RTL_WATCH_DOG_TIME));
1699        }
1700}
1701
1702void rtl88e_dm_fast_antenna_training_callback(unsigned long data)
1703{
1704        struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
1705
1706        rtl88e_dm_fast_ant_training(hw);
1707}
1708
1709static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw)
1710{
1711        struct rtl_priv *rtlpriv = rtl_priv(hw);
1712        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1713        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1714        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1715        struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
1716
1717        if (mac->link_state < MAC80211_LINKED) {
1718                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
1719                if (fat_tbl->becomelinked == true) {
1720                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
1721                                 "need to turn off HW AntDiv\n");
1722                        rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
1723                        rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
1724                                      BIT(15), 0);
1725                        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
1726                                rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
1727                                              BIT(21), 0);
1728                        fat_tbl->becomelinked =
1729                          (mac->link_state == MAC80211_LINKED) ? true : false;
1730                }
1731                return;
1732        } else {
1733                if (fat_tbl->becomelinked == false) {
1734                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
1735                                 "Need to turn on HW AntDiv\n");
1736                        rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
1737                        rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
1738                                      BIT(15), 1);
1739                        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
1740                                rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
1741                                              BIT(21), 1);
1742                        fat_tbl->becomelinked =
1743                           (mac->link_state >= MAC80211_LINKED) ? true : false;
1744                }
1745        }
1746
1747        if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
1748            (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV))
1749                rtl88e_dm_hw_ant_div(hw);
1750        else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
1751                rtl88e_dm_fast_ant_training(hw);
1752}
1753
1754void rtl88e_dm_init(struct ieee80211_hw *hw)
1755{
1756        struct rtl_priv *rtlpriv = rtl_priv(hw);
1757
1758        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1759        rtl88e_dm_diginit(hw);
1760        rtl88e_dm_init_dynamic_txpower(hw);
1761        rtl88e_dm_init_edca_turbo(hw);
1762        rtl88e_dm_init_rate_adaptive_mask(hw);
1763        rtl88e_dm_init_txpower_tracking(hw);
1764        rtl92c_dm_init_dynamic_bb_powersaving(hw);
1765        rtl88e_dm_antenna_div_init(hw);
1766}
1767
1768void rtl88e_dm_watchdog(struct ieee80211_hw *hw)
1769{
1770        struct rtl_priv *rtlpriv = rtl_priv(hw);
1771        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1772        bool fw_current_inpsmode = false;
1773        bool fw_ps_awake = true;
1774
1775        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1776                                      (u8 *)(&fw_current_inpsmode));
1777        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1778                                      (u8 *)(&fw_ps_awake));
1779        if (ppsc->p2p_ps_info.p2p_ps_mode)
1780                fw_ps_awake = false;
1781
1782        if ((ppsc->rfpwr_state == ERFON) &&
1783            ((!fw_current_inpsmode) && fw_ps_awake) &&
1784            (!ppsc->rfchange_inprogress)) {
1785                rtl88e_dm_pwdb_monitor(hw);
1786                rtl88e_dm_dig(hw);
1787                rtl88e_dm_false_alarm_counter_statistics(hw);
1788                rtl92c_dm_dynamic_txpower(hw);
1789                rtl88e_dm_check_txpower_tracking(hw);
1790                rtl88e_dm_refresh_rate_adaptive_mask(hw);
1791                rtl88e_dm_check_edca_turbo(hw);
1792                rtl88e_dm_antenna_diversity(hw);
1793        }
1794}
1795