linux/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2014  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 "../rtl8723com/dm_common.h"
  13#include "fw.h"
  14#include "trx.h"
  15#include "../btcoexist/rtl_btc.h"
  16
  17static const u32 ofdmswing_table[] = {
  18        0x0b40002d, /* 0,  -15.0dB */
  19        0x0c000030, /* 1,  -14.5dB */
  20        0x0cc00033, /* 2,  -14.0dB */
  21        0x0d800036, /* 3,  -13.5dB */
  22        0x0e400039, /* 4,  -13.0dB */
  23        0x0f00003c, /* 5,  -12.5dB */
  24        0x10000040, /* 6,  -12.0dB */
  25        0x11000044, /* 7,  -11.5dB */
  26        0x12000048, /* 8,  -11.0dB */
  27        0x1300004c, /* 9,  -10.5dB */
  28        0x14400051, /* 10, -10.0dB */
  29        0x15800056, /* 11, -9.5dB */
  30        0x16c0005b, /* 12, -9.0dB */
  31        0x18000060, /* 13, -8.5dB */
  32        0x19800066, /* 14, -8.0dB */
  33        0x1b00006c, /* 15, -7.5dB */
  34        0x1c800072, /* 16, -7.0dB */
  35        0x1e400079, /* 17, -6.5dB */
  36        0x20000080, /* 18, -6.0dB */
  37        0x22000088, /* 19, -5.5dB */
  38        0x24000090, /* 20, -5.0dB */
  39        0x26000098, /* 21, -4.5dB */
  40        0x288000a2, /* 22, -4.0dB */
  41        0x2ac000ab, /* 23, -3.5dB */
  42        0x2d4000b5, /* 24, -3.0dB */
  43        0x300000c0, /* 25, -2.5dB */
  44        0x32c000cb, /* 26, -2.0dB */
  45        0x35c000d7, /* 27, -1.5dB */
  46        0x390000e4, /* 28, -1.0dB */
  47        0x3c8000f2, /* 29, -0.5dB */
  48        0x40000100, /* 30, +0dB */
  49        0x43c0010f, /* 31, +0.5dB */
  50        0x47c0011f, /* 32, +1.0dB */
  51        0x4c000130, /* 33, +1.5dB */
  52        0x50800142, /* 34, +2.0dB */
  53        0x55400155, /* 35, +2.5dB */
  54        0x5a400169, /* 36, +3.0dB */
  55        0x5fc0017f, /* 37, +3.5dB */
  56        0x65400195, /* 38, +4.0dB */
  57        0x6b8001ae, /* 39, +4.5dB */
  58        0x71c001c7, /* 40, +5.0dB */
  59        0x788001e2, /* 41, +5.5dB */
  60        0x7f8001fe  /* 42, +6.0dB */
  61};
  62
  63static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
  64        {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /*  0, -16.0dB */
  65        {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /*  1, -15.5dB */
  66        {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  2, -15.0dB */
  67        {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  3, -14.5dB */
  68        {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  4, -14.0dB */
  69        {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  5, -13.5dB */
  70        {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /*  6, -13.0dB */
  71        {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /*  7, -12.5dB */
  72        {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /*  8, -12.0dB */
  73        {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /*  9, -11.5dB */
  74        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
  75        {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
  76        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
  77        {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
  78        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
  79        {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
  80        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
  81        {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
  82        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
  83        {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
  84        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
  85        {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
  86        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
  87        {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
  88        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
  89        {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
  90        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
  91        {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
  92        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
  93        {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
  94        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
  95        {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
  96        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}  /* 32, +0dB */
  97};
  98
  99static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 100        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /*  0, -16.0dB */
 101        {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  1, -15.5dB */
 102        {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  2, -15.0dB */
 103        {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  3, -14.5dB */
 104        {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  4, -14.0dB */
 105        {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  5, -13.5dB */
 106        {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  6, -13.0dB */
 107        {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  7, -12.5dB */
 108        {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  8, -12.0dB */
 109        {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  9, -11.5dB */
 110        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
 111        {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
 112        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
 113        {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
 114        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
 115        {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
 116        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
 117        {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
 118        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
 119        {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
 120        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
 121        {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
 122        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
 123        {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
 124        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
 125        {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
 126        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
 127        {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
 128        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
 129        {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
 130        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
 131        {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
 132        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}  /* 32, +0dB */
 133};
 134
 135static const u32 edca_setting_dl[PEER_MAX] = {
 136        0xa44f,         /* 0 UNKNOWN */
 137        0x5ea44f,       /* 1 REALTEK_90 */
 138        0x5e4322,       /* 2 REALTEK_92SE */
 139        0x5ea42b,       /* 3 BROAD */
 140        0xa44f,         /* 4 RAL */
 141        0xa630,         /* 5 ATH */
 142        0x5ea630,       /* 6 CISCO */
 143        0x5ea42b,       /* 7 MARVELL */
 144};
 145
 146static const u32 edca_setting_ul[PEER_MAX] = {
 147        0x5e4322,       /* 0 UNKNOWN */
 148        0xa44f,         /* 1 REALTEK_90 */
 149        0x5ea44f,       /* 2 REALTEK_92SE */
 150        0x5ea32b,       /* 3 BROAD */
 151        0x5ea422,       /* 4 RAL */
 152        0x5ea322,       /* 5 ATH */
 153        0x3ea430,       /* 6 CISCO */
 154        0x5ea44f,       /* 7 MARV */
 155};
 156
 157void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
 158                                       u8 *pdirection, u32 *poutwrite_val)
 159{
 160        struct rtl_priv *rtlpriv = rtl_priv(hw);
 161        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 162        u8 pwr_val = 0;
 163        u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
 164        u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
 165        u8 cck_base = rtldm->swing_idx_cck_base;
 166        u8 cck_val = rtldm->swing_idx_cck;
 167
 168        if (type == 0) {
 169                if (ofdm_val <= ofdm_base) {
 170                        *pdirection = 1;
 171                        pwr_val = ofdm_base - ofdm_val;
 172                } else {
 173                        *pdirection = 2;
 174                        pwr_val = ofdm_val - ofdm_base;
 175                }
 176        } else if (type == 1) {
 177                if (cck_val <= cck_base) {
 178                        *pdirection = 1;
 179                        pwr_val = cck_base - cck_val;
 180                } else {
 181                        *pdirection = 2;
 182                        pwr_val = cck_val - cck_base;
 183                }
 184        }
 185
 186        if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 187                pwr_val = TXPWRTRACK_MAX_IDX;
 188
 189        *poutwrite_val = pwr_val | (pwr_val << 8) |
 190                (pwr_val << 16) | (pwr_val << 24);
 191}
 192
 193void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 194{
 195        struct rtl_priv *rtlpriv = rtl_priv(hw);
 196        struct rate_adaptive *p_ra = &rtlpriv->ra;
 197
 198        p_ra->ratr_state = DM_RATR_STA_INIT;
 199        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 200
 201        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 202                rtlpriv->dm.useramask = true;
 203        else
 204                rtlpriv->dm.useramask = false;
 205
 206        p_ra->high_rssi_thresh_for_ra = 50;
 207        p_ra->low_rssi_thresh_for_ra40m = 20;
 208}
 209
 210static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
 211{
 212        struct rtl_priv *rtlpriv = rtl_priv(hw);
 213
 214        rtlpriv->dm.txpower_tracking = true;
 215        rtlpriv->dm.txpower_track_control = true;
 216        rtlpriv->dm.thermalvalue = 0;
 217
 218        rtlpriv->dm.ofdm_index[0] = 30;
 219        rtlpriv->dm.cck_index = 20;
 220
 221        rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
 222
 223        rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
 224        rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
 225        rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
 226        rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
 227
 228        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 229                "rtlpriv->dm.txpower_tracking = %d\n",
 230                rtlpriv->dm.txpower_tracking);
 231}
 232
 233static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 234{
 235        struct rtl_priv *rtlpriv = rtl_priv(hw);
 236
 237        rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 238
 239        rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
 240        rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 241}
 242
 243void rtl8723be_dm_init(struct ieee80211_hw *hw)
 244{
 245        struct rtl_priv *rtlpriv = rtl_priv(hw);
 246        u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 247
 248        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 249        rtl_dm_diginit(hw, cur_igvalue);
 250        rtl8723be_dm_init_rate_adaptive_mask(hw);
 251        rtl8723_dm_init_edca_turbo(hw);
 252        rtl8723_dm_init_dynamic_bb_powersaving(hw);
 253        rtl8723_dm_init_dynamic_txpower(hw);
 254        rtl8723be_dm_init_txpower_tracking(hw);
 255        rtl8723be_dm_init_dynamic_atc_switch(hw);
 256}
 257
 258static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 259{
 260        struct rtl_priv *rtlpriv = rtl_priv(hw);
 261        struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 262        struct rtl_mac *mac = rtl_mac(rtlpriv);
 263
 264        /* Determine the minimum RSSI  */
 265        if ((mac->link_state < MAC80211_LINKED) &&
 266            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 267                rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 268                rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 269                        "Not connected to any\n");
 270        }
 271        if (mac->link_state >= MAC80211_LINKED) {
 272                if (mac->opmode == NL80211_IFTYPE_AP ||
 273                    mac->opmode == NL80211_IFTYPE_ADHOC) {
 274                        rtl_dm_dig->min_undec_pwdb_for_dm =
 275                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 276                        rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 277                                "AP Client PWDB = 0x%lx\n",
 278                                rtlpriv->dm.entry_min_undec_sm_pwdb);
 279                } else {
 280                        rtl_dm_dig->min_undec_pwdb_for_dm =
 281                            rtlpriv->dm.undec_sm_pwdb;
 282                        rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 283                                "STA Default Port PWDB = 0x%x\n",
 284                                rtl_dm_dig->min_undec_pwdb_for_dm);
 285                }
 286        } else {
 287                rtl_dm_dig->min_undec_pwdb_for_dm =
 288                                rtlpriv->dm.entry_min_undec_sm_pwdb;
 289                rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 290                        "AP Ext Port or disconnect PWDB = 0x%x\n",
 291                        rtl_dm_dig->min_undec_pwdb_for_dm);
 292        }
 293        rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
 294                rtl_dm_dig->min_undec_pwdb_for_dm);
 295}
 296
 297static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 298{
 299        struct rtl_priv *rtlpriv = rtl_priv(hw);
 300        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 301        struct rtl_sta_info *drv_priv;
 302        u8 h2c_parameter[3] = { 0 };
 303        long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 304
 305        /* AP & ADHOC & MESH */
 306        spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 307        list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 308                if (drv_priv->rssi_stat.undec_sm_pwdb <
 309                                                tmp_entry_min_pwdb)
 310                        tmp_entry_min_pwdb =
 311                                drv_priv->rssi_stat.undec_sm_pwdb;
 312                if (drv_priv->rssi_stat.undec_sm_pwdb >
 313                                                tmp_entry_max_pwdb)
 314                        tmp_entry_max_pwdb =
 315                                drv_priv->rssi_stat.undec_sm_pwdb;
 316        }
 317        spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 318
 319        /* If associated entry is found */
 320        if (tmp_entry_max_pwdb != 0) {
 321                rtlpriv->dm.entry_max_undec_sm_pwdb =
 322                                                        tmp_entry_max_pwdb;
 323                RTPRINT(rtlpriv, FDM, DM_PWDB,
 324                        "EntryMaxPWDB = 0x%lx(%ld)\n",
 325                         tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 326        } else {
 327                rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 328        }
 329        /* If associated entry is found */
 330        if (tmp_entry_min_pwdb != 0xff) {
 331                rtlpriv->dm.entry_min_undec_sm_pwdb =
 332                                                        tmp_entry_min_pwdb;
 333                RTPRINT(rtlpriv, FDM, DM_PWDB,
 334                        "EntryMinPWDB = 0x%lx(%ld)\n",
 335                         tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 336        } else {
 337                rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 338        }
 339        /* Indicate Rx signal strength to FW. */
 340        if (rtlpriv->dm.useramask) {
 341                h2c_parameter[2] =
 342                        (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 343                h2c_parameter[1] = 0x20;
 344                h2c_parameter[0] = 0;
 345                rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
 346        } else {
 347                rtl_write_byte(rtlpriv, 0x4fe,
 348                               rtlpriv->dm.undec_sm_pwdb);
 349        }
 350        rtl8723be_dm_find_minimum_rssi(hw);
 351        dm_digtable->rssi_val_min =
 352                        rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 353}
 354
 355void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 356{
 357        struct rtl_priv *rtlpriv = rtl_priv(hw);
 358        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 359
 360        if (dm_digtable->stop_dig)
 361                return;
 362
 363        if (dm_digtable->cur_igvalue != current_igi) {
 364                rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
 365                if (rtlpriv->phy.rf_type != RF_1T1R)
 366                        rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
 367                                      0x7f, current_igi);
 368        }
 369        dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
 370        dm_digtable->cur_igvalue = current_igi;
 371}
 372
 373static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
 374{
 375        struct rtl_priv *rtlpriv = rtl_priv(hw);
 376        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 377        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 378        u8 dig_min_0, dig_maxofmin;
 379        bool bfirstconnect, bfirstdisconnect;
 380        u8 dm_dig_max, dm_dig_min;
 381        u8 current_igi = dm_digtable->cur_igvalue;
 382        u8 offset;
 383
 384        /* AP,BT */
 385        if (mac->act_scanning)
 386                return;
 387
 388        dig_min_0 = dm_digtable->dig_min_0;
 389        bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
 390                        !dm_digtable->media_connect_0;
 391        bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
 392                        (dm_digtable->media_connect_0);
 393
 394        dm_dig_max = 0x5a;
 395        dm_dig_min = DM_DIG_MIN;
 396        dig_maxofmin = DM_DIG_MAX_AP;
 397
 398        if (mac->link_state >= MAC80211_LINKED) {
 399                if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
 400                        dm_digtable->rx_gain_max = dm_dig_max;
 401                else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
 402                        dm_digtable->rx_gain_max = dm_dig_min;
 403                else
 404                        dm_digtable->rx_gain_max =
 405                                dm_digtable->rssi_val_min + 10;
 406
 407                if (rtlpriv->dm.one_entry_only) {
 408                        offset = 12;
 409                        if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 410                                dig_min_0 = dm_dig_min;
 411                        else if (dm_digtable->rssi_val_min - offset >
 412                                                        dig_maxofmin)
 413                                dig_min_0 = dig_maxofmin;
 414                        else
 415                                dig_min_0 =
 416                                        dm_digtable->rssi_val_min - offset;
 417                } else {
 418                        dig_min_0 = dm_dig_min;
 419                }
 420
 421        } else {
 422                dm_digtable->rx_gain_max = dm_dig_max;
 423                dig_min_0 = dm_dig_min;
 424                rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
 425        }
 426
 427        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 428                if (dm_digtable->large_fa_hit != 3)
 429                        dm_digtable->large_fa_hit++;
 430                if (dm_digtable->forbidden_igi < current_igi) {
 431                        dm_digtable->forbidden_igi = current_igi;
 432                        dm_digtable->large_fa_hit = 1;
 433                }
 434
 435                if (dm_digtable->large_fa_hit >= 3) {
 436                        if ((dm_digtable->forbidden_igi + 1) >
 437                             dm_digtable->rx_gain_max)
 438                                dm_digtable->rx_gain_min =
 439                                                dm_digtable->rx_gain_max;
 440                        else
 441                                dm_digtable->rx_gain_min =
 442                                                dm_digtable->forbidden_igi + 1;
 443                        dm_digtable->recover_cnt = 3600;
 444                }
 445        } else {
 446                if (dm_digtable->recover_cnt != 0) {
 447                        dm_digtable->recover_cnt--;
 448                } else {
 449                        if (dm_digtable->large_fa_hit < 3) {
 450                                if ((dm_digtable->forbidden_igi - 1) <
 451                                     dig_min_0) {
 452                                        dm_digtable->forbidden_igi =
 453                                                        dig_min_0;
 454                                        dm_digtable->rx_gain_min =
 455                                                        dig_min_0;
 456                                } else {
 457                                        dm_digtable->forbidden_igi--;
 458                                        dm_digtable->rx_gain_min =
 459                                                dm_digtable->forbidden_igi + 1;
 460                                }
 461                        } else {
 462                                dm_digtable->large_fa_hit = 0;
 463                        }
 464                }
 465        }
 466        if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 467                dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 468
 469        if (mac->link_state >= MAC80211_LINKED) {
 470                if (bfirstconnect) {
 471                        if (dm_digtable->rssi_val_min <= dig_maxofmin)
 472                                current_igi = dm_digtable->rssi_val_min;
 473                        else
 474                                current_igi = dig_maxofmin;
 475
 476                        dm_digtable->large_fa_hit = 0;
 477                } else {
 478                        if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 479                                current_igi += 4;
 480                        else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 481                                current_igi += 2;
 482                        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 483                                current_igi -= 2;
 484                }
 485        } else {
 486                if (bfirstdisconnect) {
 487                        current_igi = dm_digtable->rx_gain_min;
 488                } else {
 489                        if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 490                                current_igi += 4;
 491                        else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
 492                                current_igi += 2;
 493                        else if (rtlpriv->falsealm_cnt.cnt_all < 500)
 494                                current_igi -= 2;
 495                }
 496        }
 497
 498        if (current_igi > dm_digtable->rx_gain_max)
 499                current_igi = dm_digtable->rx_gain_max;
 500        else if (current_igi < dm_digtable->rx_gain_min)
 501                current_igi = dm_digtable->rx_gain_min;
 502
 503        rtl8723be_dm_write_dig(hw, current_igi);
 504        dm_digtable->media_connect_0 =
 505                ((mac->link_state >= MAC80211_LINKED) ? true : false);
 506        dm_digtable->dig_min_0 = dig_min_0;
 507}
 508
 509static void rtl8723be_dm_false_alarm_counter_statistics(
 510                                        struct ieee80211_hw *hw)
 511{
 512        u32 ret_value;
 513        struct rtl_priv *rtlpriv = rtl_priv(hw);
 514        struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 515
 516        rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
 517        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
 518
 519        ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
 520        falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
 521        falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
 522
 523        ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
 524        falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
 525        falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
 526
 527        ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
 528        falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
 529        falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
 530
 531        ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
 532        falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
 533
 534        falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
 535                                      falsealm_cnt->cnt_rate_illegal +
 536                                      falsealm_cnt->cnt_crc8_fail +
 537                                      falsealm_cnt->cnt_mcs_fail +
 538                                      falsealm_cnt->cnt_fast_fsync_fail +
 539                                      falsealm_cnt->cnt_sb_search_fail;
 540
 541        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
 542        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
 543
 544        ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
 545        falsealm_cnt->cnt_cck_fail = ret_value;
 546
 547        ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
 548        falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 549
 550        ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
 551        falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
 552                                    ((ret_value & 0xff00) >> 8);
 553
 554        falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
 555                                falsealm_cnt->cnt_sb_search_fail +
 556                                falsealm_cnt->cnt_parity_fail +
 557                                falsealm_cnt->cnt_rate_illegal +
 558                                falsealm_cnt->cnt_crc8_fail +
 559                                falsealm_cnt->cnt_mcs_fail +
 560                                falsealm_cnt->cnt_cck_fail;
 561
 562        falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
 563                                    falsealm_cnt->cnt_cck_cca;
 564
 565        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
 566        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
 567        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
 568        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
 569
 570        rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
 571        rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
 572
 573        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
 574        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
 575
 576        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
 577        rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
 578
 579        rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
 580                "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 581                falsealm_cnt->cnt_parity_fail,
 582                falsealm_cnt->cnt_rate_illegal,
 583                falsealm_cnt->cnt_crc8_fail,
 584                falsealm_cnt->cnt_mcs_fail);
 585
 586        rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
 587                "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 588                falsealm_cnt->cnt_ofdm_fail,
 589                falsealm_cnt->cnt_cck_fail,
 590                falsealm_cnt->cnt_all);
 591}
 592
 593static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
 594{
 595        /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
 596        return;
 597}
 598
 599static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
 600                                     u8 rfpath, long iqk_result_x,
 601                                     long iqk_result_y)
 602{
 603        long ele_a = 0, ele_d, ele_c = 0, value32;
 604
 605        if (ofdm_index >= 43)
 606                ofdm_index = 43 - 1;
 607
 608        ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
 609
 610        if (iqk_result_x != 0) {
 611                if ((iqk_result_x & 0x00000200) != 0)
 612                        iqk_result_x = iqk_result_x | 0xFFFFFC00;
 613                ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
 614
 615                if ((iqk_result_y & 0x00000200) != 0)
 616                        iqk_result_y = iqk_result_y | 0xFFFFFC00;
 617                ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
 618
 619                switch (rfpath) {
 620                case RF90_PATH_A:
 621                        value32 = (ele_d << 22) |
 622                                ((ele_c & 0x3F) << 16) | ele_a;
 623                        rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 624                                      value32);
 625                        value32 = (ele_c & 0x000003C0) >> 6;
 626                        rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
 627                        value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
 628                        rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
 629                                      value32);
 630                        break;
 631                default:
 632                        break;
 633                }
 634        } else {
 635                switch (rfpath) {
 636                case RF90_PATH_A:
 637                        rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 638                                      ofdmswing_table[ofdm_index]);
 639                        rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
 640                        rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
 641                        break;
 642                default:
 643                        break;
 644                }
 645        }
 646}
 647
 648static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
 649                                        enum pwr_track_control_method method,
 650                                        u8 rfpath, u8 idx)
 651{
 652        struct rtl_priv *rtlpriv = rtl_priv(hw);
 653        struct rtl_phy *rtlphy = &rtlpriv->phy;
 654        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 655        u8 swing_idx_ofdm_limit = 36;
 656
 657        if (method == TXAGC) {
 658                rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
 659        } else if (method == BBSWING) {
 660                if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
 661                        rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
 662
 663                if (!rtldm->cck_inch14) {
 664                        rtl_write_byte(rtlpriv, 0xa22,
 665                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
 666                        rtl_write_byte(rtlpriv, 0xa23,
 667                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
 668                        rtl_write_byte(rtlpriv, 0xa24,
 669                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
 670                        rtl_write_byte(rtlpriv, 0xa25,
 671                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
 672                        rtl_write_byte(rtlpriv, 0xa26,
 673                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
 674                        rtl_write_byte(rtlpriv, 0xa27,
 675                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
 676                        rtl_write_byte(rtlpriv, 0xa28,
 677                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
 678                        rtl_write_byte(rtlpriv, 0xa29,
 679                            cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
 680                } else {
 681                        rtl_write_byte(rtlpriv, 0xa22,
 682                            cckswing_table_ch14[rtldm->swing_idx_cck][0]);
 683                        rtl_write_byte(rtlpriv, 0xa23,
 684                            cckswing_table_ch14[rtldm->swing_idx_cck][1]);
 685                        rtl_write_byte(rtlpriv, 0xa24,
 686                            cckswing_table_ch14[rtldm->swing_idx_cck][2]);
 687                        rtl_write_byte(rtlpriv, 0xa25,
 688                            cckswing_table_ch14[rtldm->swing_idx_cck][3]);
 689                        rtl_write_byte(rtlpriv, 0xa26,
 690                            cckswing_table_ch14[rtldm->swing_idx_cck][4]);
 691                        rtl_write_byte(rtlpriv, 0xa27,
 692                            cckswing_table_ch14[rtldm->swing_idx_cck][5]);
 693                        rtl_write_byte(rtlpriv, 0xa28,
 694                            cckswing_table_ch14[rtldm->swing_idx_cck][6]);
 695                        rtl_write_byte(rtlpriv, 0xa29,
 696                            cckswing_table_ch14[rtldm->swing_idx_cck][7]);
 697                }
 698
 699                if (rfpath == RF90_PATH_A) {
 700                        if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
 701                            swing_idx_ofdm_limit)
 702                                swing_idx_ofdm_limit =
 703                                        rtldm->swing_idx_ofdm[RF90_PATH_A];
 704
 705                        rtl8723be_set_iqk_matrix(hw,
 706                                rtldm->swing_idx_ofdm[rfpath], rfpath,
 707                                rtlphy->iqk_matrix[idx].value[0][0],
 708                                rtlphy->iqk_matrix[idx].value[0][1]);
 709                } else if (rfpath == RF90_PATH_B) {
 710                        if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
 711                            swing_idx_ofdm_limit)
 712                                swing_idx_ofdm_limit =
 713                                        rtldm->swing_idx_ofdm[RF90_PATH_B];
 714
 715                        rtl8723be_set_iqk_matrix(hw,
 716                                rtldm->swing_idx_ofdm[rfpath], rfpath,
 717                                rtlphy->iqk_matrix[idx].value[0][4],
 718                                rtlphy->iqk_matrix[idx].value[0][5]);
 719                }
 720        } else {
 721                return;
 722        }
 723}
 724
 725static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
 726                                                        struct ieee80211_hw *hw)
 727{
 728        struct rtl_priv *rtlpriv = rtl_priv(hw);
 729        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 730        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
 731        u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
 732        u8 thermalvalue_avg_count = 0;
 733        u32 thermalvalue_avg = 0;
 734        int i = 0;
 735
 736        u8 ofdm_min_index = 6;
 737        u8 index_for_channel = 0;
 738
 739        static const s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
 740                0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 741                5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
 742                10, 11, 11, 12, 12, 13, 14, 15};
 743        static const s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
 744                0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 745                5, 6, 6, 6, 6, 7, 7, 7, 8, 8,  9,
 746                9, 10, 10, 11, 12, 13, 14, 15};
 747
 748        /*Initilization ( 7 steps in total )*/
 749        rtlpriv->dm.txpower_trackinginit = true;
 750        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 751                "%s\n", __func__);
 752
 753        thermalvalue = (u8)rtl_get_rfreg(hw,
 754                RF90_PATH_A, RF_T_METER, 0xfc00);
 755        if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
 756            rtlefuse->eeprom_thermalmeter == 0xFF)
 757                return;
 758        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 759                "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
 760                thermalvalue, rtldm->thermalvalue,
 761                rtlefuse->eeprom_thermalmeter);
 762        /*3 Initialize ThermalValues of RFCalibrateInfo*/
 763        if (!rtldm->thermalvalue) {
 764                rtlpriv->dm.thermalvalue_lck = thermalvalue;
 765                rtlpriv->dm.thermalvalue_iqk = thermalvalue;
 766        }
 767
 768        /*4 Calculate average thermal meter*/
 769        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
 770        rtldm->thermalvalue_avg_index++;
 771        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
 772                rtldm->thermalvalue_avg_index = 0;
 773
 774        for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
 775                if (rtldm->thermalvalue_avg[i]) {
 776                        thermalvalue_avg += rtldm->thermalvalue_avg[i];
 777                        thermalvalue_avg_count++;
 778                }
 779        }
 780
 781        if (thermalvalue_avg_count)
 782                thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
 783
 784        /* 5 Calculate delta, delta_LCK, delta_IQK.*/
 785        delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
 786                (thermalvalue - rtlpriv->dm.thermalvalue) :
 787                (rtlpriv->dm.thermalvalue - thermalvalue);
 788        delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
 789                    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
 790                    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
 791        delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
 792                    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
 793                    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
 794
 795        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 796                "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n",
 797                thermalvalue, rtlpriv->dm.thermalvalue,
 798                rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
 799        /* 6 If necessary, do LCK.*/
 800        if (delta_lck >= IQK_THRESHOLD) {
 801                rtlpriv->dm.thermalvalue_lck = thermalvalue;
 802                rtl8723be_phy_lc_calibrate(hw);
 803        }
 804
 805        /* 7 If necessary, move the index of
 806         * swing table to adjust Tx power.
 807         */
 808        if (delta > 0 && rtlpriv->dm.txpower_track_control) {
 809                delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
 810                        (thermalvalue - rtlefuse->eeprom_thermalmeter) :
 811                        (rtlefuse->eeprom_thermalmeter - thermalvalue);
 812
 813                if (delta >= TXSCALE_TABLE_SIZE)
 814                        delta = TXSCALE_TABLE_SIZE - 1;
 815                /* 7.1 Get the final CCK_index and
 816                 * OFDM_index for each swing table.
 817                 */
 818                if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
 819                        rtldm->delta_power_index_last[RF90_PATH_A] =
 820                                        rtldm->delta_power_index[RF90_PATH_A];
 821                        rtldm->delta_power_index[RF90_PATH_A] =
 822                                        delta_swing_table_idx_tup_a[delta];
 823                } else {
 824                        rtldm->delta_power_index_last[RF90_PATH_A] =
 825                                        rtldm->delta_power_index[RF90_PATH_A];
 826                        rtldm->delta_power_index[RF90_PATH_A] =
 827                                -1 * delta_swing_table_idx_tdown_a[delta];
 828                }
 829
 830                /* 7.2 Handle boundary conditions of index.*/
 831                if (rtldm->delta_power_index[RF90_PATH_A] ==
 832                    rtldm->delta_power_index_last[RF90_PATH_A])
 833                        rtldm->power_index_offset[RF90_PATH_A] = 0;
 834                else
 835                        rtldm->power_index_offset[RF90_PATH_A] =
 836                                rtldm->delta_power_index[RF90_PATH_A] -
 837                                rtldm->delta_power_index_last[RF90_PATH_A];
 838
 839                rtldm->ofdm_index[0] =
 840                        rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
 841                        rtldm->power_index_offset[RF90_PATH_A];
 842                rtldm->cck_index = rtldm->swing_idx_cck_base +
 843                                   rtldm->power_index_offset[RF90_PATH_A];
 844
 845                rtldm->swing_idx_cck = rtldm->cck_index;
 846                rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
 847
 848                if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
 849                        rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
 850                else if (rtldm->ofdm_index[0] < ofdm_min_index)
 851                        rtldm->ofdm_index[0] = ofdm_min_index;
 852
 853                if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
 854                        rtldm->cck_index = CCK_TABLE_SIZE - 1;
 855                else if (rtldm->cck_index < 0)
 856                        rtldm->cck_index = 0;
 857        } else {
 858                rtldm->power_index_offset[RF90_PATH_A] = 0;
 859        }
 860
 861        if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
 862            (rtldm->txpower_track_control)) {
 863                rtldm->done_txpower = true;
 864                rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
 865                                                      index_for_channel);
 866
 867                rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
 868                rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
 869                                                rtldm->swing_idx_ofdm[0];
 870                rtldm->thermalvalue = thermalvalue;
 871        }
 872
 873        if (delta_iqk >= IQK_THRESHOLD) {
 874                rtldm->thermalvalue_iqk = thermalvalue;
 875                rtl8723be_phy_iq_calibrate(hw, false);
 876        }
 877
 878        rtldm->txpowercount = 0;
 879        rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
 880
 881}
 882
 883void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 884{
 885        struct rtl_priv *rtlpriv = rtl_priv(hw);
 886
 887        if (!rtlpriv->dm.txpower_tracking)
 888                return;
 889
 890        if (!rtlpriv->dm.tm_trigger) {
 891                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
 892                              0x03);
 893                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 894                        "Trigger 8723be Thermal Meter!!\n");
 895                rtlpriv->dm.tm_trigger = 1;
 896                return;
 897        } else {
 898                rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 899                        "Schedule TxPowerTracking !!\n");
 900                rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
 901                rtlpriv->dm.tm_trigger = 0;
 902        }
 903}
 904
 905static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 906{
 907        struct rtl_priv *rtlpriv = rtl_priv(hw);
 908        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 909        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 910        struct rate_adaptive *p_ra = &rtlpriv->ra;
 911        u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
 912        u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
 913        u8 go_up_gap = 5;
 914        struct ieee80211_sta *sta = NULL;
 915
 916        if (is_hal_stop(rtlhal)) {
 917                rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 918                        "driver is going to unload\n");
 919                return;
 920        }
 921
 922        if (!rtlpriv->dm.useramask) {
 923                rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 924                        "driver does not control rate adaptive mask\n");
 925                return;
 926        }
 927
 928        if (mac->link_state == MAC80211_LINKED &&
 929                mac->opmode == NL80211_IFTYPE_STATION) {
 930                switch (p_ra->pre_ratr_state) {
 931                case DM_RATR_STA_MIDDLE:
 932                        high_rssithresh_for_ra += go_up_gap;
 933                        break;
 934                case DM_RATR_STA_LOW:
 935                        high_rssithresh_for_ra += go_up_gap;
 936                        low_rssithresh_for_ra += go_up_gap;
 937                        break;
 938                default:
 939                        break;
 940                }
 941
 942                if (rtlpriv->dm.undec_sm_pwdb >
 943                    (long)high_rssithresh_for_ra)
 944                        p_ra->ratr_state = DM_RATR_STA_HIGH;
 945                else if (rtlpriv->dm.undec_sm_pwdb >
 946                         (long)low_rssithresh_for_ra)
 947                        p_ra->ratr_state = DM_RATR_STA_MIDDLE;
 948                else
 949                        p_ra->ratr_state = DM_RATR_STA_LOW;
 950
 951                if (p_ra->pre_ratr_state != p_ra->ratr_state) {
 952                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 953                                "RSSI = %ld\n",
 954                                 rtlpriv->dm.undec_sm_pwdb);
 955                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 956                                "RSSI_LEVEL = %d\n", p_ra->ratr_state);
 957                        rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 958                                "PreState = %d, CurState = %d\n",
 959                                p_ra->pre_ratr_state, p_ra->ratr_state);
 960
 961                        rcu_read_lock();
 962                        sta = rtl_find_sta(hw, mac->bssid);
 963                        if (sta)
 964                                rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 965                                                           p_ra->ratr_state,
 966                                                           true);
 967                        rcu_read_unlock();
 968
 969                        p_ra->pre_ratr_state = p_ra->ratr_state;
 970                }
 971        }
 972}
 973
 974static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
 975{
 976        struct rtl_priv *rtlpriv = rtl_priv(hw);
 977
 978        if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
 979                return true;
 980
 981        return false;
 982}
 983
 984static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
 985{
 986        struct rtl_priv *rtlpriv = rtl_priv(hw);
 987        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 988
 989        static u64 last_txok_cnt;
 990        static u64 last_rxok_cnt;
 991        u64 cur_txok_cnt = 0;
 992        u64 cur_rxok_cnt = 0;
 993        u32 edca_be_ul = 0x6ea42b;
 994        u32 edca_be_dl = 0x6ea42b;/*not sure*/
 995        u32 edca_be = 0x5ea42b;
 996        u32 iot_peer = 0;
 997        bool b_is_cur_rdlstate;
 998        bool b_bias_on_rx = false;
 999        bool b_edca_turbo_on = false;
1000
1001        cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1002        cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1003
1004        iot_peer = rtlpriv->mac80211.vendor;
1005        b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1006                       true : false;
1007        b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1008                           (!rtlpriv->dm.disable_framebursting)) ?
1009                           true : false;
1010
1011        if ((iot_peer == PEER_CISCO) &&
1012            (mac->mode == WIRELESS_MODE_N_24G)) {
1013                edca_be_dl = edca_setting_dl[iot_peer];
1014                edca_be_ul = edca_setting_ul[iot_peer];
1015        }
1016        if (rtl8723be_dm_is_edca_turbo_disable(hw))
1017                goto exit;
1018
1019        if (b_edca_turbo_on) {
1020                if (b_bias_on_rx)
1021                        b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1022                                            false : true;
1023                else
1024                        b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1025                                            true : false;
1026
1027                edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1028                rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1029                rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1030                rtlpriv->dm.current_turbo_edca = true;
1031        } else {
1032                if (rtlpriv->dm.current_turbo_edca) {
1033                        u8 tmp = AC0_BE;
1034                        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1035                                                      (u8 *)(&tmp));
1036                }
1037                rtlpriv->dm.current_turbo_edca = false;
1038        }
1039
1040exit:
1041        rtlpriv->dm.is_any_nonbepkts = false;
1042        last_txok_cnt = rtlpriv->stats.txbytesunicast;
1043        last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1044}
1045
1046static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1047{
1048        struct rtl_priv *rtlpriv = rtl_priv(hw);
1049        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1050        u8 cur_cck_cca_thresh;
1051
1052        if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1053                if (dm_digtable->rssi_val_min > 25) {
1054                        cur_cck_cca_thresh = 0xcd;
1055                } else if ((dm_digtable->rssi_val_min <= 25) &&
1056                           (dm_digtable->rssi_val_min > 10)) {
1057                        cur_cck_cca_thresh = 0x83;
1058                } else {
1059                        if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1060                                cur_cck_cca_thresh = 0x83;
1061                        else
1062                                cur_cck_cca_thresh = 0x40;
1063                }
1064        } else {
1065                if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1066                        cur_cck_cca_thresh = 0x83;
1067                else
1068                        cur_cck_cca_thresh = 0x40;
1069        }
1070
1071        if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1072                rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1073
1074        dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1075        dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1076        rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
1077                "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1078}
1079
1080static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1081{
1082        struct rtl_priv *rtlpriv = rtl_priv(hw);
1083        u8 reg_c50, reg_c58;
1084        bool fw_current_in_ps_mode = false;
1085
1086        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1087                                      (u8 *)(&fw_current_in_ps_mode));
1088        if (fw_current_in_ps_mode)
1089                return;
1090
1091        reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1092        reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1093
1094        if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1095                if (!rtlpriv->rtlhal.pre_edcca_enable) {
1096                        rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1097                        rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1098                }
1099        } else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1100                if (rtlpriv->rtlhal.pre_edcca_enable) {
1101                        rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1102                        rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1103                }
1104        }
1105}
1106
1107static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1108{
1109        struct rtl_priv *rtlpriv = rtl_priv(hw);
1110        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1111        u8 crystal_cap;
1112        u32 packet_count;
1113        int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1114        int cfo_ave_diff;
1115
1116        if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1117                if (rtldm->atc_status == ATC_STATUS_OFF) {
1118                        rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1119                                      ATC_STATUS_ON);
1120                        rtldm->atc_status = ATC_STATUS_ON;
1121                }
1122                if (rtlpriv->cfg->ops->get_btc_status()) {
1123                        if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1124                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1125                                        "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1126                                return;
1127                        }
1128                }
1129
1130                if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1131                        rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1132                        crystal_cap = rtldm->crystal_cap & 0x3f;
1133                        rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1134                                      (crystal_cap | (crystal_cap << 6)));
1135                }
1136        } else {
1137                cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1138                cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1139                packet_count = rtldm->packet_count;
1140
1141                if (packet_count == rtldm->packet_count_pre)
1142                        return;
1143
1144                rtldm->packet_count_pre = packet_count;
1145
1146                if (rtlpriv->phy.rf_type == RF_1T1R)
1147                        cfo_ave = cfo_khz_a;
1148                else
1149                        cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1150
1151                cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1152                               (rtldm->cfo_ave_pre - cfo_ave) :
1153                               (cfo_ave - rtldm->cfo_ave_pre);
1154
1155                if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
1156                        rtldm->large_cfo_hit = true;
1157                        return;
1158                } else
1159                        rtldm->large_cfo_hit = false;
1160
1161                rtldm->cfo_ave_pre = cfo_ave;
1162
1163                if (cfo_ave >= -rtldm->cfo_threshold &&
1164                    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1165                        if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1166                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1167                                rtldm->is_freeze = 1;
1168                        } else {
1169                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1170                        }
1171                }
1172
1173                if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1174                        adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1175                else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1176                                        rtlpriv->dm.crystal_cap > 0)
1177                        adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1178
1179                if (adjust_xtal != 0) {
1180                        rtldm->is_freeze = 0;
1181                        rtldm->crystal_cap += adjust_xtal;
1182
1183                        if (rtldm->crystal_cap > 0x3f)
1184                                rtldm->crystal_cap = 0x3f;
1185                        else if (rtldm->crystal_cap < 0)
1186                                rtldm->crystal_cap = 0;
1187
1188                        crystal_cap = rtldm->crystal_cap & 0x3f;
1189                        rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1190                                      (crystal_cap | (crystal_cap << 6)));
1191                }
1192
1193                if (cfo_ave < CFO_THRESHOLD_ATC &&
1194                    cfo_ave > -CFO_THRESHOLD_ATC) {
1195                        if (rtldm->atc_status == ATC_STATUS_ON) {
1196                                rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1197                                              ATC_STATUS_OFF);
1198                                rtldm->atc_status = ATC_STATUS_OFF;
1199                        }
1200                } else {
1201                        if (rtldm->atc_status == ATC_STATUS_OFF) {
1202                                rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1203                                              ATC_STATUS_ON);
1204                                rtldm->atc_status = ATC_STATUS_ON;
1205                        }
1206                }
1207        }
1208}
1209
1210static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1211{
1212        struct rtl_priv *rtlpriv = rtl_priv(hw);
1213        u8 cnt = 0;
1214        struct rtl_sta_info *drv_priv;
1215
1216        rtlpriv->dm.one_entry_only = false;
1217
1218        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1219                rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1220                rtlpriv->dm.one_entry_only = true;
1221                return;
1222        }
1223
1224        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1225                rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1226                rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1227                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1228                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1229                        cnt++;
1230                }
1231                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1232
1233                if (cnt == 1)
1234                        rtlpriv->dm.one_entry_only = true;
1235        }
1236}
1237
1238void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1239{
1240        struct rtl_priv *rtlpriv = rtl_priv(hw);
1241        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1242        bool fw_current_inpsmode = false;
1243        bool fw_ps_awake = true;
1244
1245        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1246                                      (u8 *)(&fw_current_inpsmode));
1247
1248        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1249                                      (u8 *)(&fw_ps_awake));
1250
1251        if (ppsc->p2p_ps_info.p2p_ps_mode)
1252                fw_ps_awake = false;
1253
1254        spin_lock(&rtlpriv->locks.rf_ps_lock);
1255        if ((ppsc->rfpwr_state == ERFON) &&
1256                ((!fw_current_inpsmode) && fw_ps_awake) &&
1257                (!ppsc->rfchange_inprogress)) {
1258                rtl8723be_dm_common_info_self_update(hw);
1259                rtl8723be_dm_false_alarm_counter_statistics(hw);
1260                rtl8723be_dm_check_rssi_monitor(hw);
1261                rtl8723be_dm_dig(hw);
1262                rtl8723be_dm_dynamic_edcca(hw);
1263                rtl8723be_dm_cck_packet_detection_thresh(hw);
1264                rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1265                rtl8723be_dm_check_edca_turbo(hw);
1266                rtl8723be_dm_dynamic_atc_switch(hw);
1267                rtl8723be_dm_check_txpower_tracking(hw);
1268                rtl8723be_dm_dynamic_txpower(hw);
1269        }
1270        spin_unlock(&rtlpriv->locks.rf_ps_lock);
1271        rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1272}
1273