Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include <linux/export.h>
0005 #include "dm_common.h"
0006 #include "phy_common.h"
0007 #include "../pci.h"
0008 #include "../base.h"
0009 #include "../core.h"
0010 
0011 #define BT_RSSI_STATE_NORMAL_POWER  BIT(0)
0012 #define BT_RSSI_STATE_AMDPU_OFF     BIT(1)
0013 #define BT_RSSI_STATE_SPECIAL_LOW   BIT(2)
0014 #define BT_RSSI_STATE_BG_EDCA_LOW   BIT(3)
0015 #define BT_RSSI_STATE_TXPOWER_LOW   BIT(4)
0016 #define BT_MASK             0x00ffffff
0017 
0018 #define RTLPRIV         (struct rtl_priv *)
0019 #define GET_UNDECORATED_AVERAGE_RSSI(_priv) \
0020     ((RTLPRIV(_priv))->mac80211.opmode == \
0021                  NL80211_IFTYPE_ADHOC) ?    \
0022     ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
0023     ((RTLPRIV(_priv))->dm.undec_sm_pwdb)
0024 
0025 static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
0026     0x7f8001fe,
0027     0x788001e2,
0028     0x71c001c7,
0029     0x6b8001ae,
0030     0x65400195,
0031     0x5fc0017f,
0032     0x5a400169,
0033     0x55400155,
0034     0x50800142,
0035     0x4c000130,
0036     0x47c0011f,
0037     0x43c0010f,
0038     0x40000100,
0039     0x3c8000f2,
0040     0x390000e4,
0041     0x35c000d7,
0042     0x32c000cb,
0043     0x300000c0,
0044     0x2d4000b5,
0045     0x2ac000ab,
0046     0x288000a2,
0047     0x26000098,
0048     0x24000090,
0049     0x22000088,
0050     0x20000080,
0051     0x1e400079,
0052     0x1c800072,
0053     0x1b00006c,
0054     0x19800066,
0055     0x18000060,
0056     0x16c0005b,
0057     0x15800056,
0058     0x14400051,
0059     0x1300004c,
0060     0x12000048,
0061     0x11000044,
0062     0x10000040,
0063 };
0064 
0065 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
0066     {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
0067     {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
0068     {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
0069     {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
0070     {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
0071     {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
0072     {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
0073     {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
0074     {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
0075     {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
0076     {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
0077     {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
0078     {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
0079     {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
0080     {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
0081     {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
0082     {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
0083     {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
0084     {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
0085     {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
0086     {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
0087     {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
0088     {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
0089     {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
0090     {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
0091     {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
0092     {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
0093     {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
0094     {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
0095     {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
0096     {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
0097     {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
0098     {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
0099 };
0100 
0101 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
0102     {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
0103     {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
0104     {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
0105     {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
0106     {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
0107     {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
0108     {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
0109     {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
0110     {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
0111     {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
0112     {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
0113     {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
0114     {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
0115     {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
0116     {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
0117     {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
0118     {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
0119     {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
0120     {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
0121     {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
0122     {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
0123     {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
0124     {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
0125     {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
0126     {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
0127     {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
0128     {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
0129     {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
0130     {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
0131     {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
0132     {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
0133     {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
0134     {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
0135 };
0136 
0137 static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
0138 
0139 void dm_restorepowerindex(struct ieee80211_hw *hw)
0140 {
0141     struct rtl_priv *rtlpriv = rtl_priv(hw);
0142     u8  index;
0143 
0144     for (index = 0; index < 6; index++)
0145         rtl_write_byte(rtlpriv, power_index_reg[index],
0146                    rtlpriv->dm.powerindex_backup[index]);
0147 }
0148 EXPORT_SYMBOL_GPL(dm_restorepowerindex);
0149 
0150 void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)
0151 {
0152     struct rtl_priv *rtlpriv = rtl_priv(hw);
0153     u8 index;
0154 
0155     for (index = 0; index < 6; index++)
0156         rtl_write_byte(rtlpriv, power_index_reg[index], value);
0157 }
0158 EXPORT_SYMBOL_GPL(dm_writepowerindex);
0159 
0160 void dm_savepowerindex(struct ieee80211_hw *hw)
0161 {
0162     struct rtl_priv *rtlpriv = rtl_priv(hw);
0163     u8 index;
0164     u8 tmp;
0165 
0166     for (index = 0; index < 6; index++) {
0167         tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);
0168         rtlpriv->dm.powerindex_backup[index] = tmp;
0169     }
0170 }
0171 EXPORT_SYMBOL_GPL(dm_savepowerindex);
0172 
0173 static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
0174 {
0175     struct rtl_priv *rtlpriv = rtl_priv(hw);
0176     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0177     long rssi_val_min = 0;
0178 
0179     if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
0180         (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
0181         if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
0182             rssi_val_min =
0183                 (rtlpriv->dm.entry_min_undec_sm_pwdb >
0184                  rtlpriv->dm.undec_sm_pwdb) ?
0185                 rtlpriv->dm.undec_sm_pwdb :
0186                 rtlpriv->dm.entry_min_undec_sm_pwdb;
0187         else
0188             rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
0189     } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
0190            dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
0191         rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
0192     } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
0193         rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
0194     }
0195 
0196     if (rssi_val_min > 100)
0197         rssi_val_min = 100;
0198     return (u8)rssi_val_min;
0199 }
0200 
0201 static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
0202 {
0203     u32 ret_value;
0204     struct rtl_priv *rtlpriv = rtl_priv(hw);
0205     struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
0206 
0207     ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
0208     falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
0209 
0210     ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
0211     falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
0212     falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
0213 
0214     ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
0215     falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
0216 
0217     ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
0218     falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
0219     falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
0220 
0221     falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
0222                       falsealm_cnt->cnt_rate_illegal +
0223                       falsealm_cnt->cnt_crc8_fail +
0224                       falsealm_cnt->cnt_mcs_fail +
0225                       falsealm_cnt->cnt_fast_fsync_fail +
0226                       falsealm_cnt->cnt_sb_search_fail;
0227 
0228     rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
0229     ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
0230     falsealm_cnt->cnt_cck_fail = ret_value;
0231 
0232     ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
0233     falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
0234     falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
0235                  falsealm_cnt->cnt_rate_illegal +
0236                  falsealm_cnt->cnt_crc8_fail +
0237                  falsealm_cnt->cnt_mcs_fail +
0238                  falsealm_cnt->cnt_cck_fail);
0239 
0240     rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
0241     rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
0242     rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
0243     rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
0244 
0245     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0246         "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
0247         falsealm_cnt->cnt_parity_fail,
0248         falsealm_cnt->cnt_rate_illegal,
0249         falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
0250 
0251     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0252         "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
0253         falsealm_cnt->cnt_ofdm_fail,
0254         falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
0255 }
0256 
0257 static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
0258 {
0259     struct rtl_priv *rtlpriv = rtl_priv(hw);
0260     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0261     u8 value_igi = dm_digtable->cur_igvalue;
0262 
0263     if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
0264         value_igi--;
0265     else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
0266         value_igi += 0;
0267     else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
0268         value_igi++;
0269     else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
0270         value_igi += 2;
0271 
0272     if (value_igi > DM_DIG_FA_UPPER)
0273         value_igi = DM_DIG_FA_UPPER;
0274     else if (value_igi < DM_DIG_FA_LOWER)
0275         value_igi = DM_DIG_FA_LOWER;
0276 
0277     if (rtlpriv->falsealm_cnt.cnt_all > 10000)
0278         value_igi = DM_DIG_FA_UPPER;
0279 
0280     dm_digtable->cur_igvalue = value_igi;
0281     rtl92c_dm_write_dig(hw);
0282 }
0283 
0284 static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
0285 {
0286     struct rtl_priv *rtlpriv = rtl_priv(hw);
0287     struct dig_t *digtable = &rtlpriv->dm_digtable;
0288     u32 isbt;
0289 
0290     /* modify DIG lower bound, deal with abnormally large false alarm */
0291     if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
0292         digtable->large_fa_hit++;
0293         if (digtable->forbidden_igi < digtable->cur_igvalue) {
0294             digtable->forbidden_igi = digtable->cur_igvalue;
0295             digtable->large_fa_hit = 1;
0296         }
0297 
0298         if (digtable->large_fa_hit >= 3) {
0299             if ((digtable->forbidden_igi + 1) >
0300                 digtable->rx_gain_max)
0301                 digtable->rx_gain_min = digtable->rx_gain_max;
0302             else
0303                 digtable->rx_gain_min = (digtable->forbidden_igi + 1);
0304             digtable->recover_cnt = 3600; /* 3600=2hr */
0305         }
0306     } else {
0307         /* Recovery mechanism for IGI lower bound */
0308         if (digtable->recover_cnt != 0) {
0309             digtable->recover_cnt--;
0310         } else {
0311             if (digtable->large_fa_hit == 0) {
0312                 if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
0313                     digtable->forbidden_igi = DM_DIG_MIN;
0314                     digtable->rx_gain_min = DM_DIG_MIN;
0315                 } else {
0316                     digtable->forbidden_igi--;
0317                     digtable->rx_gain_min = digtable->forbidden_igi + 1;
0318                 }
0319             } else if (digtable->large_fa_hit == 3) {
0320                 digtable->large_fa_hit = 0;
0321             }
0322         }
0323     }
0324     if (rtlpriv->falsealm_cnt.cnt_all < 250) {
0325         isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;
0326 
0327         if (!isbt) {
0328             if (rtlpriv->falsealm_cnt.cnt_all >
0329                 digtable->fa_lowthresh) {
0330                 if ((digtable->back_val - 2) <
0331                    digtable->back_range_min)
0332                     digtable->back_val = digtable->back_range_min;
0333                 else
0334                     digtable->back_val -= 2;
0335             } else if (rtlpriv->falsealm_cnt.cnt_all <
0336                    digtable->fa_lowthresh) {
0337                 if ((digtable->back_val + 2) >
0338                     digtable->back_range_max)
0339                     digtable->back_val = digtable->back_range_max;
0340                 else
0341                     digtable->back_val += 2;
0342             }
0343         } else {
0344             digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
0345         }
0346     } else {
0347         /* Adjust initial gain by false alarm */
0348         if (rtlpriv->falsealm_cnt.cnt_all > 1000)
0349             digtable->cur_igvalue = digtable->pre_igvalue + 2;
0350         else if (rtlpriv->falsealm_cnt.cnt_all > 750)
0351             digtable->cur_igvalue = digtable->pre_igvalue + 1;
0352         else if (rtlpriv->falsealm_cnt.cnt_all < 500)
0353             digtable->cur_igvalue = digtable->pre_igvalue - 1;
0354     }
0355 
0356     /* Check initial gain by upper/lower bound */
0357     if (digtable->cur_igvalue > digtable->rx_gain_max)
0358         digtable->cur_igvalue = digtable->rx_gain_max;
0359 
0360     if (digtable->cur_igvalue < digtable->rx_gain_min)
0361         digtable->cur_igvalue = digtable->rx_gain_min;
0362 
0363     rtl92c_dm_write_dig(hw);
0364 }
0365 
0366 static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
0367 {
0368     static u8 initialized; /* initialized to false */
0369     struct rtl_priv *rtlpriv = rtl_priv(hw);
0370     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0371     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0372     long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
0373     bool multi_sta = false;
0374 
0375     if (mac->opmode == NL80211_IFTYPE_ADHOC)
0376         multi_sta = true;
0377 
0378     if (!multi_sta ||
0379         dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {
0380         initialized = false;
0381         dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
0382         return;
0383     } else if (!initialized) {
0384         initialized = true;
0385         dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
0386         dm_digtable->cur_igvalue = 0x20;
0387         rtl92c_dm_write_dig(hw);
0388     }
0389 
0390     if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
0391         if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
0392             (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
0393 
0394             if (dm_digtable->dig_ext_port_stage ==
0395                 DIG_EXT_PORT_STAGE_2) {
0396                 dm_digtable->cur_igvalue = 0x20;
0397                 rtl92c_dm_write_dig(hw);
0398             }
0399 
0400             dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
0401         } else if (rssi_strength > dm_digtable->rssi_highthresh) {
0402             dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
0403             rtl92c_dm_ctrl_initgain_by_fa(hw);
0404         }
0405     } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
0406         dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
0407         dm_digtable->cur_igvalue = 0x20;
0408         rtl92c_dm_write_dig(hw);
0409     }
0410 
0411     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0412         "curmultista_cstate = %x dig_ext_port_stage %x\n",
0413         dm_digtable->curmultista_cstate,
0414         dm_digtable->dig_ext_port_stage);
0415 }
0416 
0417 static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
0418 {
0419     struct rtl_priv *rtlpriv = rtl_priv(hw);
0420     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0421 
0422     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0423         "presta_cstate = %x, cursta_cstate = %x\n",
0424         dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
0425     if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
0426         dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
0427         dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
0428         if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
0429             dm_digtable->rssi_val_min =
0430                 rtl92c_dm_initial_gain_min_pwdb(hw);
0431             if (dm_digtable->rssi_val_min > 100)
0432                 dm_digtable->rssi_val_min = 100;
0433             rtl92c_dm_ctrl_initgain_by_rssi(hw);
0434         }
0435     } else {
0436         dm_digtable->rssi_val_min = 0;
0437         dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
0438         dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
0439         dm_digtable->cur_igvalue = 0x20;
0440         dm_digtable->pre_igvalue = 0;
0441         rtl92c_dm_write_dig(hw);
0442     }
0443 }
0444 
0445 static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
0446 {
0447     struct rtl_priv *rtlpriv = rtl_priv(hw);
0448     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0449 
0450     if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
0451         dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
0452         if (dm_digtable->rssi_val_min > 100)
0453             dm_digtable->rssi_val_min = 100;
0454 
0455         if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
0456             if (dm_digtable->rssi_val_min <= 25)
0457                 dm_digtable->cur_cck_pd_state =
0458                     CCK_PD_STAGE_LOWRSSI;
0459             else
0460                 dm_digtable->cur_cck_pd_state =
0461                     CCK_PD_STAGE_HIGHRSSI;
0462         } else {
0463             if (dm_digtable->rssi_val_min <= 20)
0464                 dm_digtable->cur_cck_pd_state =
0465                     CCK_PD_STAGE_LOWRSSI;
0466             else
0467                 dm_digtable->cur_cck_pd_state =
0468                     CCK_PD_STAGE_HIGHRSSI;
0469         }
0470     } else {
0471         dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
0472     }
0473 
0474     if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
0475         if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) ||
0476             (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))
0477             rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
0478         else
0479             rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
0480 
0481         dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
0482     }
0483 }
0484 
0485 static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
0486 {
0487     struct rtl_priv *rtlpriv = rtl_priv(hw);
0488     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0489     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0490 
0491     if (mac->act_scanning)
0492         return;
0493 
0494     if (mac->link_state >= MAC80211_LINKED)
0495         dm_digtable->cursta_cstate = DIG_STA_CONNECT;
0496     else
0497         dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
0498 
0499     dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
0500 
0501     rtl92c_dm_initial_gain_sta(hw);
0502     rtl92c_dm_initial_gain_multi_sta(hw);
0503     rtl92c_dm_cck_packet_detection_thresh(hw);
0504 
0505     dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
0506 }
0507 
0508 static void rtl92c_dm_dig(struct ieee80211_hw *hw)
0509 {
0510     struct rtl_priv *rtlpriv = rtl_priv(hw);
0511 
0512     if (!rtlpriv->dm.dm_initialgain_enable)
0513         return;
0514     if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
0515         return;
0516 
0517     rtl92c_dm_ctrl_initgain_by_twoport(hw);
0518 }
0519 
0520 static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
0521 {
0522     struct rtl_priv *rtlpriv = rtl_priv(hw);
0523 
0524     if (rtlpriv->rtlhal.interface == INTF_USB &&
0525         rtlpriv->rtlhal.board_type & 0x1) {
0526         dm_savepowerindex(hw);
0527         rtlpriv->dm.dynamic_txpower_enable = true;
0528     } else {
0529         rtlpriv->dm.dynamic_txpower_enable = false;
0530     }
0531     rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
0532     rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
0533 }
0534 
0535 void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
0536 {
0537     struct rtl_priv *rtlpriv = rtl_priv(hw);
0538     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0539 
0540     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0541         "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
0542         dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
0543         dm_digtable->back_val);
0544 
0545     if (rtlpriv->rtlhal.interface == INTF_USB &&
0546         !dm_digtable->dig_enable_flag) {
0547         dm_digtable->pre_igvalue = 0x17;
0548         return;
0549     }
0550     dm_digtable->cur_igvalue -= 1;
0551     if (dm_digtable->cur_igvalue < DM_DIG_MIN)
0552         dm_digtable->cur_igvalue = DM_DIG_MIN;
0553 
0554     if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
0555         rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
0556                   dm_digtable->cur_igvalue);
0557         rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
0558                   dm_digtable->cur_igvalue);
0559 
0560         dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
0561     }
0562     rtl_dbg(rtlpriv, COMP_DIG, DBG_WARNING,
0563         "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
0564         dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
0565         dm_digtable->rssi_val_min, dm_digtable->back_val,
0566         dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,
0567         dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);
0568 }
0569 EXPORT_SYMBOL(rtl92c_dm_write_dig);
0570 
0571 static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
0572 {
0573     struct rtl_priv *rtlpriv = rtl_priv(hw);
0574     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0575     long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
0576 
0577     if (mac->link_state != MAC80211_LINKED)
0578         return;
0579 
0580     if (mac->opmode == NL80211_IFTYPE_ADHOC ||
0581         mac->opmode == NL80211_IFTYPE_AP) {
0582         /* TODO: Handle ADHOC and AP Mode */
0583     }
0584 
0585     if (tmpentry_max_pwdb != 0)
0586         rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
0587     else
0588         rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
0589 
0590     if (tmpentry_min_pwdb != 0xff)
0591         rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
0592     else
0593         rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
0594 
0595 /* TODO:
0596  *  if (mac->opmode == NL80211_IFTYPE_STATION) {
0597  *      if (rtlpriv->rtlhal.fw_ready) {
0598  *          u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);
0599  *          rtl8192c_set_rssi_cmd(hw, param);
0600  *      }
0601  *  }
0602  */
0603 }
0604 
0605 void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
0606 {
0607     struct rtl_priv *rtlpriv = rtl_priv(hw);
0608 
0609     rtlpriv->dm.current_turbo_edca = false;
0610     rtlpriv->dm.is_any_nonbepkts = false;
0611     rtlpriv->dm.is_cur_rdlstate = false;
0612 }
0613 EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
0614 
0615 static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
0616 {
0617     struct rtl_priv *rtlpriv = rtl_priv(hw);
0618     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0619 
0620     static u64 last_txok_cnt;
0621     static u64 last_rxok_cnt;
0622     static u32 last_bt_edca_ul;
0623     static u32 last_bt_edca_dl;
0624     u64 cur_txok_cnt = 0;
0625     u64 cur_rxok_cnt = 0;
0626     u32 edca_be_ul = 0x5ea42b;
0627     u32 edca_be_dl = 0x5ea42b;
0628     bool bt_change_edca = false;
0629 
0630     if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||
0631         (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {
0632         rtlpriv->dm.current_turbo_edca = false;
0633         last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;
0634         last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;
0635     }
0636 
0637     if (rtlpriv->btcoexist.bt_edca_ul != 0) {
0638         edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;
0639         bt_change_edca = true;
0640     }
0641 
0642     if (rtlpriv->btcoexist.bt_edca_dl != 0) {
0643         edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
0644         bt_change_edca = true;
0645     }
0646 
0647     if (mac->link_state != MAC80211_LINKED) {
0648         rtlpriv->dm.current_turbo_edca = false;
0649         return;
0650     }
0651 
0652     if ((!mac->ht_enable) && (!rtlpriv->btcoexist.bt_coexistence)) {
0653         if (!(edca_be_ul & 0xffff0000))
0654             edca_be_ul |= 0x005e0000;
0655 
0656         if (!(edca_be_dl & 0xffff0000))
0657             edca_be_dl |= 0x005e0000;
0658     }
0659 
0660     if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
0661          (!rtlpriv->dm.disable_framebursting))) {
0662         cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
0663         cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
0664 
0665         if (cur_rxok_cnt > 4 * cur_txok_cnt) {
0666             if (!rtlpriv->dm.is_cur_rdlstate ||
0667                 !rtlpriv->dm.current_turbo_edca) {
0668                 rtl_write_dword(rtlpriv,
0669                         REG_EDCA_BE_PARAM,
0670                         edca_be_dl);
0671                 rtlpriv->dm.is_cur_rdlstate = true;
0672             }
0673         } else {
0674             if (rtlpriv->dm.is_cur_rdlstate ||
0675                 !rtlpriv->dm.current_turbo_edca) {
0676                 rtl_write_dword(rtlpriv,
0677                         REG_EDCA_BE_PARAM,
0678                         edca_be_ul);
0679                 rtlpriv->dm.is_cur_rdlstate = false;
0680             }
0681         }
0682         rtlpriv->dm.current_turbo_edca = true;
0683     } else {
0684         if (rtlpriv->dm.current_turbo_edca) {
0685             u8 tmp = AC0_BE;
0686 
0687             rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
0688                               &tmp);
0689             rtlpriv->dm.current_turbo_edca = false;
0690         }
0691     }
0692 
0693     rtlpriv->dm.is_any_nonbepkts = false;
0694     last_txok_cnt = rtlpriv->stats.txbytesunicast;
0695     last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
0696 }
0697 
0698 static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
0699                                  *hw)
0700 {
0701     struct rtl_priv *rtlpriv = rtl_priv(hw);
0702     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0703     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0704     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0705     u8 thermalvalue, delta, delta_lck, delta_iqk;
0706     long ele_a, ele_d, temp_cck, val_x, value32;
0707     long val_y, ele_c = 0;
0708     u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
0709     s8 cck_index = 0;
0710     int i;
0711     bool is2t = IS_92C_SERIAL(rtlhal->version);
0712     s8 txpwr_level[3] = {0, 0, 0};
0713     u8 ofdm_min_index = 6, rf;
0714 
0715     rtlpriv->dm.txpower_trackinginit = true;
0716     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0717         "%s\n", __func__);
0718 
0719     thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
0720 
0721     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0722         "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
0723         thermalvalue, rtlpriv->dm.thermalvalue,
0724         rtlefuse->eeprom_thermalmeter);
0725 
0726     rtl92c_phy_ap_calibrate(hw, (thermalvalue -
0727                      rtlefuse->eeprom_thermalmeter));
0728     if (is2t)
0729         rf = 2;
0730     else
0731         rf = 1;
0732 
0733     if (thermalvalue) {
0734         ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
0735                       MASKDWORD) & MASKOFDM_D;
0736 
0737         for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
0738             if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
0739                 ofdm_index_old[0] = (u8) i;
0740 
0741                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0742                     "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
0743                     ROFDM0_XATXIQIMBALANCE,
0744                     ele_d, ofdm_index_old[0]);
0745                 break;
0746             }
0747         }
0748 
0749         if (is2t) {
0750             ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
0751                           MASKDWORD) & MASKOFDM_D;
0752 
0753             for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
0754                 if (ele_d == (ofdmswing_table[i] &
0755                     MASKOFDM_D)) {
0756                     ofdm_index_old[1] = (u8) i;
0757                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
0758                         DBG_LOUD,
0759                         "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
0760                         ROFDM0_XBTXIQIMBALANCE, ele_d,
0761                         ofdm_index_old[1]);
0762                     break;
0763                 }
0764             }
0765         }
0766 
0767         temp_cck =
0768             rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
0769 
0770         for (i = 0; i < CCK_TABLE_LENGTH; i++) {
0771             if (rtlpriv->dm.cck_inch14) {
0772                 if (memcmp((void *)&temp_cck,
0773                        (void *)&cckswing_table_ch14[i][2],
0774                        4) == 0) {
0775                     cck_index_old = (u8) i;
0776 
0777                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
0778                         DBG_LOUD,
0779                         "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",
0780                         RCCK0_TXFILTER2, temp_cck,
0781                         cck_index_old,
0782                         rtlpriv->dm.cck_inch14);
0783                     break;
0784                 }
0785             } else {
0786                 if (memcmp((void *)&temp_cck,
0787                        (void *)
0788                        &cckswing_table_ch1ch13[i][2],
0789                        4) == 0) {
0790                     cck_index_old = (u8) i;
0791 
0792                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
0793                         DBG_LOUD,
0794                         "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",
0795                         RCCK0_TXFILTER2, temp_cck,
0796                         cck_index_old,
0797                         rtlpriv->dm.cck_inch14);
0798                     break;
0799                 }
0800             }
0801         }
0802 
0803         if (!rtlpriv->dm.thermalvalue) {
0804             rtlpriv->dm.thermalvalue =
0805                 rtlefuse->eeprom_thermalmeter;
0806             rtlpriv->dm.thermalvalue_lck = thermalvalue;
0807             rtlpriv->dm.thermalvalue_iqk = thermalvalue;
0808             for (i = 0; i < rf; i++)
0809                 rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
0810             rtlpriv->dm.cck_index = cck_index_old;
0811         }
0812         /* Handle USB High PA boards */
0813 
0814         delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
0815             (thermalvalue - rtlpriv->dm.thermalvalue) :
0816             (rtlpriv->dm.thermalvalue - thermalvalue);
0817 
0818         delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
0819             (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
0820             (rtlpriv->dm.thermalvalue_lck - thermalvalue);
0821 
0822         delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
0823             (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
0824             (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
0825 
0826         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0827             "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",
0828             thermalvalue, rtlpriv->dm.thermalvalue,
0829             rtlefuse->eeprom_thermalmeter, delta, delta_lck,
0830             delta_iqk);
0831 
0832         if (delta_lck > 1) {
0833             rtlpriv->dm.thermalvalue_lck = thermalvalue;
0834             rtl92c_phy_lc_calibrate(hw);
0835         }
0836 
0837         if (delta > 0 && rtlpriv->dm.txpower_track_control) {
0838             if (thermalvalue > rtlpriv->dm.thermalvalue) {
0839                 for (i = 0; i < rf; i++)
0840                     rtlpriv->dm.ofdm_index[i] -= delta;
0841                 rtlpriv->dm.cck_index -= delta;
0842             } else {
0843                 for (i = 0; i < rf; i++)
0844                     rtlpriv->dm.ofdm_index[i] += delta;
0845                 rtlpriv->dm.cck_index += delta;
0846             }
0847 
0848             if (is2t) {
0849                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0850                     "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
0851                     rtlpriv->dm.ofdm_index[0],
0852                     rtlpriv->dm.ofdm_index[1],
0853                     rtlpriv->dm.cck_index);
0854             } else {
0855                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0856                     "temp OFDM_A_index=0x%x, cck_index=0x%x\n",
0857                     rtlpriv->dm.ofdm_index[0],
0858                     rtlpriv->dm.cck_index);
0859             }
0860 
0861             if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
0862                 for (i = 0; i < rf; i++)
0863                     ofdm_index[i] =
0864                         rtlpriv->dm.ofdm_index[i]
0865                         + 1;
0866                 cck_index = rtlpriv->dm.cck_index + 1;
0867             } else {
0868                 for (i = 0; i < rf; i++)
0869                     ofdm_index[i] =
0870                         rtlpriv->dm.ofdm_index[i];
0871                 cck_index = rtlpriv->dm.cck_index;
0872             }
0873 
0874             for (i = 0; i < rf; i++) {
0875                 if (txpwr_level[i] >= 0 &&
0876                     txpwr_level[i] <= 26) {
0877                     if (thermalvalue >
0878                         rtlefuse->eeprom_thermalmeter) {
0879                         if (delta < 5)
0880                             ofdm_index[i] -= 1;
0881 
0882                         else
0883                             ofdm_index[i] -= 2;
0884                     } else if (delta > 5 && thermalvalue <
0885                            rtlefuse->
0886                            eeprom_thermalmeter) {
0887                         ofdm_index[i] += 1;
0888                     }
0889                 } else if (txpwr_level[i] >= 27 &&
0890                        txpwr_level[i] <= 32
0891                        && thermalvalue >
0892                        rtlefuse->eeprom_thermalmeter) {
0893                     if (delta < 5)
0894                         ofdm_index[i] -= 1;
0895 
0896                     else
0897                         ofdm_index[i] -= 2;
0898                 } else if (txpwr_level[i] >= 32 &&
0899                        txpwr_level[i] <= 38 &&
0900                        thermalvalue >
0901                        rtlefuse->eeprom_thermalmeter
0902                        && delta > 5) {
0903                     ofdm_index[i] -= 1;
0904                 }
0905             }
0906 
0907             if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
0908                 if (thermalvalue >
0909                     rtlefuse->eeprom_thermalmeter) {
0910                     if (delta < 5)
0911                         cck_index -= 1;
0912 
0913                     else
0914                         cck_index -= 2;
0915                 } else if (delta > 5 && thermalvalue <
0916                        rtlefuse->eeprom_thermalmeter) {
0917                     cck_index += 1;
0918                 }
0919             } else if (txpwr_level[i] >= 27 &&
0920                    txpwr_level[i] <= 32 &&
0921                    thermalvalue >
0922                    rtlefuse->eeprom_thermalmeter) {
0923                 if (delta < 5)
0924                     cck_index -= 1;
0925 
0926                 else
0927                     cck_index -= 2;
0928             } else if (txpwr_level[i] >= 32 &&
0929                    txpwr_level[i] <= 38 &&
0930                    thermalvalue > rtlefuse->eeprom_thermalmeter
0931                    && delta > 5) {
0932                 cck_index -= 1;
0933             }
0934 
0935             for (i = 0; i < rf; i++) {
0936                 if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
0937                     ofdm_index[i] = OFDM_TABLE_SIZE - 1;
0938 
0939                 else if (ofdm_index[i] < ofdm_min_index)
0940                     ofdm_index[i] = ofdm_min_index;
0941             }
0942 
0943             if (cck_index > CCK_TABLE_SIZE - 1)
0944                 cck_index = CCK_TABLE_SIZE - 1;
0945             else if (cck_index < 0)
0946                 cck_index = 0;
0947 
0948             if (is2t) {
0949                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0950                     "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
0951                     ofdm_index[0], ofdm_index[1],
0952                     cck_index);
0953             } else {
0954                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0955                     "new OFDM_A_index=0x%x, cck_index=0x%x\n",
0956                     ofdm_index[0], cck_index);
0957             }
0958         }
0959 
0960         if (rtlpriv->dm.txpower_track_control && delta != 0) {
0961             ele_d =
0962                 (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
0963             val_x = rtlphy->reg_e94;
0964             val_y = rtlphy->reg_e9c;
0965 
0966             if (val_x != 0) {
0967                 if ((val_x & 0x00000200) != 0)
0968                     val_x = val_x | 0xFFFFFC00;
0969                 ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
0970 
0971                 if ((val_y & 0x00000200) != 0)
0972                     val_y = val_y | 0xFFFFFC00;
0973                 ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
0974 
0975                 value32 = (ele_d << 22) |
0976                     ((ele_c & 0x3F) << 16) | ele_a;
0977 
0978                 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
0979                           MASKDWORD, value32);
0980 
0981                 value32 = (ele_c & 0x000003C0) >> 6;
0982                 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
0983                           value32);
0984 
0985                 value32 = ((val_x * ele_d) >> 7) & 0x01;
0986                 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
0987                           BIT(31), value32);
0988 
0989                 value32 = ((val_y * ele_d) >> 7) & 0x01;
0990                 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
0991                           BIT(29), value32);
0992             } else {
0993                 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
0994                           MASKDWORD,
0995                           ofdmswing_table[ofdm_index[0]]);
0996 
0997                 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
0998                           0x00);
0999                 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1000                           BIT(31) | BIT(29), 0x00);
1001             }
1002 
1003             if (!rtlpriv->dm.cck_inch14) {
1004                 rtl_write_byte(rtlpriv, 0xa22,
1005                            cckswing_table_ch1ch13[cck_index]
1006                            [0]);
1007                 rtl_write_byte(rtlpriv, 0xa23,
1008                            cckswing_table_ch1ch13[cck_index]
1009                            [1]);
1010                 rtl_write_byte(rtlpriv, 0xa24,
1011                            cckswing_table_ch1ch13[cck_index]
1012                            [2]);
1013                 rtl_write_byte(rtlpriv, 0xa25,
1014                            cckswing_table_ch1ch13[cck_index]
1015                            [3]);
1016                 rtl_write_byte(rtlpriv, 0xa26,
1017                            cckswing_table_ch1ch13[cck_index]
1018                            [4]);
1019                 rtl_write_byte(rtlpriv, 0xa27,
1020                            cckswing_table_ch1ch13[cck_index]
1021                            [5]);
1022                 rtl_write_byte(rtlpriv, 0xa28,
1023                            cckswing_table_ch1ch13[cck_index]
1024                            [6]);
1025                 rtl_write_byte(rtlpriv, 0xa29,
1026                            cckswing_table_ch1ch13[cck_index]
1027                            [7]);
1028             } else {
1029                 rtl_write_byte(rtlpriv, 0xa22,
1030                            cckswing_table_ch14[cck_index]
1031                            [0]);
1032                 rtl_write_byte(rtlpriv, 0xa23,
1033                            cckswing_table_ch14[cck_index]
1034                            [1]);
1035                 rtl_write_byte(rtlpriv, 0xa24,
1036                            cckswing_table_ch14[cck_index]
1037                            [2]);
1038                 rtl_write_byte(rtlpriv, 0xa25,
1039                            cckswing_table_ch14[cck_index]
1040                            [3]);
1041                 rtl_write_byte(rtlpriv, 0xa26,
1042                            cckswing_table_ch14[cck_index]
1043                            [4]);
1044                 rtl_write_byte(rtlpriv, 0xa27,
1045                            cckswing_table_ch14[cck_index]
1046                            [5]);
1047                 rtl_write_byte(rtlpriv, 0xa28,
1048                            cckswing_table_ch14[cck_index]
1049                            [6]);
1050                 rtl_write_byte(rtlpriv, 0xa29,
1051                            cckswing_table_ch14[cck_index]
1052                            [7]);
1053             }
1054 
1055             if (is2t) {
1056                 ele_d = (ofdmswing_table[ofdm_index[1]] &
1057                      0xFFC00000) >> 22;
1058 
1059                 val_x = rtlphy->reg_eb4;
1060                 val_y = rtlphy->reg_ebc;
1061 
1062                 if (val_x != 0) {
1063                     if ((val_x & 0x00000200) != 0)
1064                         val_x = val_x | 0xFFFFFC00;
1065                     ele_a = ((val_x * ele_d) >> 8) &
1066                         0x000003FF;
1067 
1068                     if ((val_y & 0x00000200) != 0)
1069                         val_y = val_y | 0xFFFFFC00;
1070                     ele_c = ((val_y * ele_d) >> 8) &
1071                         0x00003FF;
1072 
1073                     value32 = (ele_d << 22) |
1074                         ((ele_c & 0x3F) << 16) | ele_a;
1075                     rtl_set_bbreg(hw,
1076                               ROFDM0_XBTXIQIMBALANCE,
1077                               MASKDWORD, value32);
1078 
1079                     value32 = (ele_c & 0x000003C0) >> 6;
1080                     rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1081                               MASKH4BITS, value32);
1082 
1083                     value32 = ((val_x * ele_d) >> 7) & 0x01;
1084                     rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1085                               BIT(27), value32);
1086 
1087                     value32 = ((val_y * ele_d) >> 7) & 0x01;
1088                     rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1089                               BIT(25), value32);
1090                 } else {
1091                     rtl_set_bbreg(hw,
1092                               ROFDM0_XBTXIQIMBALANCE,
1093                               MASKDWORD,
1094                               ofdmswing_table[ofdm_index
1095                                       [1]]);
1096                     rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1097                               MASKH4BITS, 0x00);
1098                     rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1099                               BIT(27) | BIT(25), 0x00);
1100                 }
1101 
1102             }
1103         }
1104 
1105         if (delta_iqk > 3) {
1106             rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1107             rtl92c_phy_iq_calibrate(hw, false);
1108         }
1109 
1110         if (rtlpriv->dm.txpower_track_control)
1111             rtlpriv->dm.thermalvalue = thermalvalue;
1112     }
1113 
1114     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
1115 
1116 }
1117 
1118 static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
1119                         struct ieee80211_hw *hw)
1120 {
1121     struct rtl_priv *rtlpriv = rtl_priv(hw);
1122 
1123     rtlpriv->dm.txpower_tracking = true;
1124     rtlpriv->dm.txpower_trackinginit = false;
1125 
1126     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1127         "pMgntInfo->txpower_tracking = %d\n",
1128         rtlpriv->dm.txpower_tracking);
1129 }
1130 
1131 static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
1132 {
1133     rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
1134 }
1135 
1136 static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
1137 {
1138     rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
1139 }
1140 
1141 static void rtl92c_dm_check_txpower_tracking_thermal_meter(
1142                         struct ieee80211_hw *hw)
1143 {
1144     struct rtl_priv *rtlpriv = rtl_priv(hw);
1145 
1146     if (!rtlpriv->dm.txpower_tracking)
1147         return;
1148 
1149     if (!rtlpriv->dm.tm_trigger) {
1150         rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
1151                   0x60);
1152         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1153             "Trigger 92S Thermal Meter!!\n");
1154         rtlpriv->dm.tm_trigger = 1;
1155         return;
1156     } else {
1157         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1158             "Schedule TxPowerTracking direct call!!\n");
1159         rtl92c_dm_txpower_tracking_directcall(hw);
1160         rtlpriv->dm.tm_trigger = 0;
1161     }
1162 }
1163 
1164 void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1165 {
1166     rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
1167 }
1168 EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
1169 
1170 void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1171 {
1172     struct rtl_priv *rtlpriv = rtl_priv(hw);
1173     struct rate_adaptive *p_ra = &(rtlpriv->ra);
1174 
1175     p_ra->ratr_state = DM_RATR_STA_INIT;
1176     p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1177 
1178     if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1179         rtlpriv->dm.useramask = true;
1180     else
1181         rtlpriv->dm.useramask = false;
1182 
1183 }
1184 EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
1185 
1186 static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1187 {
1188     struct rtl_priv *rtlpriv = rtl_priv(hw);
1189     struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1190 
1191     dm_pstable->pre_ccastate = CCA_MAX;
1192     dm_pstable->cur_ccasate = CCA_MAX;
1193     dm_pstable->pre_rfstate = RF_MAX;
1194     dm_pstable->cur_rfstate = RF_MAX;
1195     dm_pstable->rssi_val_min = 0;
1196 }
1197 
1198 void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
1199 {
1200     struct rtl_priv *rtlpriv = rtl_priv(hw);
1201     struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1202 
1203     if (!rtlpriv->reg_init) {
1204         rtlpriv->reg_874 = (rtl_get_bbreg(hw,
1205                           RFPGA0_XCD_RFINTERFACESW,
1206                           MASKDWORD) & 0x1CC000) >> 14;
1207 
1208         rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
1209                     MASKDWORD) & BIT(3)) >> 3;
1210 
1211         rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1212                     MASKDWORD) & 0xFF000000) >> 24;
1213 
1214         rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
1215                     0xF000) >> 12;
1216 
1217         rtlpriv->reg_init = true;
1218     }
1219 
1220     if (!bforce_in_normal) {
1221         if (dm_pstable->rssi_val_min != 0) {
1222             if (dm_pstable->pre_rfstate == RF_NORMAL) {
1223                 if (dm_pstable->rssi_val_min >= 30)
1224                     dm_pstable->cur_rfstate = RF_SAVE;
1225                 else
1226                     dm_pstable->cur_rfstate = RF_NORMAL;
1227             } else {
1228                 if (dm_pstable->rssi_val_min <= 25)
1229                     dm_pstable->cur_rfstate = RF_NORMAL;
1230                 else
1231                     dm_pstable->cur_rfstate = RF_SAVE;
1232             }
1233         } else {
1234             dm_pstable->cur_rfstate = RF_MAX;
1235         }
1236     } else {
1237         dm_pstable->cur_rfstate = RF_NORMAL;
1238     }
1239 
1240     if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
1241         if (dm_pstable->cur_rfstate == RF_SAVE) {
1242             rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1243                       0x1C0000, 0x2);
1244             rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
1245             rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1246                       0xFF000000, 0x63);
1247             rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1248                       0xC000, 0x2);
1249             rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
1250             rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1251             rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
1252         } else {
1253             rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1254                       0x1CC000, rtlpriv->reg_874);
1255             rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
1256                       rtlpriv->reg_c70);
1257             rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
1258                       rtlpriv->reg_85c);
1259             rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
1260             rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1261         }
1262 
1263         dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
1264     }
1265 }
1266 EXPORT_SYMBOL(rtl92c_dm_rf_saving);
1267 
1268 static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1269 {
1270     struct rtl_priv *rtlpriv = rtl_priv(hw);
1271     struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1272     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1273     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1274 
1275     /* Determine the minimum RSSI */
1276     if (((mac->link_state == MAC80211_NOLINK)) &&
1277         (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1278         dm_pstable->rssi_val_min = 0;
1279         rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
1280     }
1281 
1282     if (mac->link_state == MAC80211_LINKED) {
1283         if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1284             dm_pstable->rssi_val_min =
1285                 rtlpriv->dm.entry_min_undec_sm_pwdb;
1286             rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,
1287                 "AP Client PWDB = 0x%lx\n",
1288                 dm_pstable->rssi_val_min);
1289         } else {
1290             dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
1291             rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,
1292                 "STA Default Port PWDB = 0x%lx\n",
1293                 dm_pstable->rssi_val_min);
1294         }
1295     } else {
1296         dm_pstable->rssi_val_min =
1297             rtlpriv->dm.entry_min_undec_sm_pwdb;
1298 
1299         rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,
1300             "AP Ext Port PWDB = 0x%lx\n",
1301             dm_pstable->rssi_val_min);
1302     }
1303 
1304     /* Power Saving for 92C */
1305     if (IS_92C_SERIAL(rtlhal->version))
1306         ;/* rtl92c_dm_1r_cca(hw); */
1307     else
1308         rtl92c_dm_rf_saving(hw, false);
1309 }
1310 
1311 void rtl92c_dm_init(struct ieee80211_hw *hw)
1312 {
1313     struct rtl_priv *rtlpriv = rtl_priv(hw);
1314 
1315     rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1316     rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;
1317     rtlpriv->dm.undec_sm_pwdb = -1;
1318     rtlpriv->dm.undec_sm_cck = -1;
1319     rtlpriv->dm.dm_initialgain_enable = true;
1320     rtl_dm_diginit(hw, 0x20);
1321 
1322     rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;
1323     rtl92c_dm_init_dynamic_txpower(hw);
1324 
1325     rtl92c_dm_init_edca_turbo(hw);
1326     rtl92c_dm_init_rate_adaptive_mask(hw);
1327     rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;
1328     rtl92c_dm_initialize_txpower_tracking(hw);
1329     rtl92c_dm_init_dynamic_bb_powersaving(hw);
1330 
1331     rtlpriv->dm.ofdm_pkt_cnt = 0;
1332     rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;
1333 }
1334 EXPORT_SYMBOL(rtl92c_dm_init);
1335 
1336 void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
1337 {
1338     struct rtl_priv *rtlpriv = rtl_priv(hw);
1339     struct rtl_phy *rtlphy = &(rtlpriv->phy);
1340     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1341     long undec_sm_pwdb;
1342 
1343     if (!rtlpriv->dm.dynamic_txpower_enable)
1344         return;
1345 
1346     if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
1347         rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1348         return;
1349     }
1350 
1351     if ((mac->link_state < MAC80211_LINKED) &&
1352         (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1353         rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
1354             "Not connected to any\n");
1355 
1356         rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1357 
1358         rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
1359         return;
1360     }
1361 
1362     if (mac->link_state >= MAC80211_LINKED) {
1363         if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1364             undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1365             rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1366                 "AP Client PWDB = 0x%lx\n",
1367                 undec_sm_pwdb);
1368         } else {
1369             undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
1370             rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1371                 "STA Default Port PWDB = 0x%lx\n",
1372                 undec_sm_pwdb);
1373         }
1374     } else {
1375         undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1376 
1377         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1378             "AP Ext Port PWDB = 0x%lx\n",
1379             undec_sm_pwdb);
1380     }
1381 
1382     if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
1383         rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;
1384         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1385             "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
1386     } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
1387            (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
1388 
1389         rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1390         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1391             "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
1392     } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
1393         rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1394         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1395             "TXHIGHPWRLEVEL_NORMAL\n");
1396     }
1397 
1398     if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
1399         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1400             "PHY_SetTxPowerLevel8192S() Channel = %d\n",
1401              rtlphy->current_channel);
1402         rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
1403         if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1404             TXHIGHPWRLEVEL_NORMAL)
1405             dm_restorepowerindex(hw);
1406         else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1407              TXHIGHPWRLEVEL_LEVEL1)
1408             dm_writepowerindex(hw, 0x14);
1409         else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1410              TXHIGHPWRLEVEL_LEVEL2)
1411             dm_writepowerindex(hw, 0x10);
1412     }
1413     rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
1414 }
1415 
1416 void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
1417 {
1418     struct rtl_priv *rtlpriv = rtl_priv(hw);
1419     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1420     bool fw_current_inpsmode = false;
1421     bool fw_ps_awake = true;
1422 
1423     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1424                       (u8 *) (&fw_current_inpsmode));
1425     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1426                       (u8 *) (&fw_ps_awake));
1427 
1428     if (ppsc->p2p_ps_info.p2p_ps_mode)
1429         fw_ps_awake = false;
1430 
1431     if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
1432                          fw_ps_awake)
1433         && (!ppsc->rfchange_inprogress)) {
1434         rtl92c_dm_pwdb_monitor(hw);
1435         rtl92c_dm_dig(hw);
1436         rtl92c_dm_false_alarm_counter_statistics(hw);
1437         rtl92c_dm_dynamic_bb_powersaving(hw);
1438         rtl92c_dm_dynamic_txpower(hw);
1439         rtl92c_dm_check_txpower_tracking(hw);
1440         /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
1441         rtl92c_dm_bt_coexist(hw);
1442         rtl92c_dm_check_edca_turbo(hw);
1443     }
1444 }
1445 EXPORT_SYMBOL(rtl92c_dm_watchdog);
1446 
1447 u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
1448 {
1449     struct rtl_priv *rtlpriv = rtl_priv(hw);
1450     long undec_sm_pwdb;
1451     u8 curr_bt_rssi_state = 0x00;
1452 
1453     if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1454         undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
1455     } else {
1456         if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
1457             undec_sm_pwdb = 100;
1458         else
1459             undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1460     }
1461 
1462     /* Check RSSI to determine HighPower/NormalPower state for
1463      * BT coexistence. */
1464     if (undec_sm_pwdb >= 67)
1465         curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
1466     else if (undec_sm_pwdb < 62)
1467         curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
1468 
1469     /* Check RSSI to determine AMPDU setting for BT coexistence. */
1470     if (undec_sm_pwdb >= 40)
1471         curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
1472     else if (undec_sm_pwdb <= 32)
1473         curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
1474 
1475     /* Marked RSSI state. It will be used to determine BT coexistence
1476      * setting later. */
1477     if (undec_sm_pwdb < 35)
1478         curr_bt_rssi_state |=  BT_RSSI_STATE_SPECIAL_LOW;
1479     else
1480         curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
1481 
1482     /* Check BT state related to BT_Idle in B/G mode. */
1483     if (undec_sm_pwdb < 15)
1484         curr_bt_rssi_state |=  BT_RSSI_STATE_BG_EDCA_LOW;
1485     else
1486         curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
1487 
1488     if (curr_bt_rssi_state != rtlpriv->btcoexist.bt_rssi_state) {
1489         rtlpriv->btcoexist.bt_rssi_state = curr_bt_rssi_state;
1490         return true;
1491     } else {
1492         return false;
1493     }
1494 }
1495 EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
1496 
1497 static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
1498 {
1499     struct rtl_priv *rtlpriv = rtl_priv(hw);
1500 
1501     u32 polling, ratio_tx, ratio_pri;
1502     u32 bt_tx, bt_pri;
1503     u8 bt_state;
1504     u8 cur_service_type;
1505 
1506     if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
1507         return false;
1508 
1509     bt_state = rtl_read_byte(rtlpriv, 0x4fd);
1510     bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK;
1511     bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK;
1512     polling = rtl_read_dword(rtlpriv, 0x490);
1513 
1514     if (bt_tx == BT_MASK && bt_pri == BT_MASK &&
1515         polling == 0xffffffff && bt_state == 0xff)
1516         return false;
1517 
1518     bt_state &= BIT(0);
1519     if (bt_state != rtlpriv->btcoexist.bt_cur_state) {
1520         rtlpriv->btcoexist.bt_cur_state = bt_state;
1521 
1522         if (rtlpriv->btcoexist.reg_bt_sco == 3) {
1523             rtlpriv->btcoexist.bt_service = BT_IDLE;
1524 
1525             bt_state = bt_state |
1526               ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
1527               0 : BIT(1)) | BIT(2);
1528             rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1529         }
1530         return true;
1531     }
1532 
1533     ratio_tx = bt_tx * 1000 / polling;
1534     ratio_pri = bt_pri * 1000 / polling;
1535     rtlpriv->btcoexist.ratio_tx = ratio_tx;
1536     rtlpriv->btcoexist.ratio_pri = ratio_pri;
1537 
1538     if (bt_state && rtlpriv->btcoexist.reg_bt_sco == 3) {
1539 
1540         if ((ratio_tx < 30)  && (ratio_pri < 30))
1541             cur_service_type = BT_IDLE;
1542         else if ((ratio_pri > 110) && (ratio_pri < 250))
1543             cur_service_type = BT_SCO;
1544         else if ((ratio_tx >= 200) && (ratio_pri >= 200))
1545             cur_service_type = BT_BUSY;
1546         else if ((ratio_tx >= 350) && (ratio_tx < 500))
1547             cur_service_type = BT_OTHERBUSY;
1548         else if (ratio_tx >= 500)
1549             cur_service_type = BT_PAN;
1550         else
1551             cur_service_type = BT_OTHER_ACTION;
1552 
1553         if (cur_service_type != rtlpriv->btcoexist.bt_service) {
1554             rtlpriv->btcoexist.bt_service = cur_service_type;
1555             bt_state = bt_state |
1556                ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
1557                0 : BIT(1)) |
1558                ((rtlpriv->btcoexist.bt_service != BT_IDLE) ?
1559                0 : BIT(2));
1560 
1561             /* Add interrupt migration when bt is not ini
1562              * idle state (no traffic). */
1563             if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1564                 rtl_write_word(rtlpriv, 0x504, 0x0ccc);
1565                 rtl_write_byte(rtlpriv, 0x506, 0x54);
1566                 rtl_write_byte(rtlpriv, 0x507, 0x54);
1567             } else {
1568                 rtl_write_byte(rtlpriv, 0x506, 0x00);
1569                 rtl_write_byte(rtlpriv, 0x507, 0x00);
1570             }
1571 
1572             rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1573             return true;
1574         }
1575     }
1576 
1577     return false;
1578 
1579 }
1580 
1581 static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
1582 {
1583     struct rtl_priv *rtlpriv = rtl_priv(hw);
1584     static bool media_connect;
1585 
1586     if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1587         media_connect = false;
1588     } else {
1589         if (!media_connect) {
1590             media_connect = true;
1591             return true;
1592         }
1593         media_connect = true;
1594     }
1595 
1596     return false;
1597 }
1598 
1599 static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
1600 {
1601     struct rtl_priv *rtlpriv = rtl_priv(hw);
1602 
1603     if (rtlpriv->btcoexist.bt_service == BT_OTHERBUSY) {
1604         rtlpriv->btcoexist.bt_edca_ul = 0x5ea72b;
1605         rtlpriv->btcoexist.bt_edca_dl = 0x5ea72b;
1606     } else if (rtlpriv->btcoexist.bt_service == BT_BUSY) {
1607         rtlpriv->btcoexist.bt_edca_ul = 0x5eb82f;
1608         rtlpriv->btcoexist.bt_edca_dl = 0x5eb82f;
1609     } else if (rtlpriv->btcoexist.bt_service == BT_SCO) {
1610         if (rtlpriv->btcoexist.ratio_tx > 160) {
1611             rtlpriv->btcoexist.bt_edca_ul = 0x5ea72f;
1612             rtlpriv->btcoexist.bt_edca_dl = 0x5ea72f;
1613         } else {
1614             rtlpriv->btcoexist.bt_edca_ul = 0x5ea32b;
1615             rtlpriv->btcoexist.bt_edca_dl = 0x5ea42b;
1616         }
1617     } else {
1618         rtlpriv->btcoexist.bt_edca_ul = 0;
1619         rtlpriv->btcoexist.bt_edca_dl = 0;
1620     }
1621 
1622     if ((rtlpriv->btcoexist.bt_service != BT_IDLE) &&
1623         (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
1624          (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
1625         (rtlpriv->btcoexist.bt_rssi_state &
1626          BT_RSSI_STATE_BG_EDCA_LOW)) {
1627         rtlpriv->btcoexist.bt_edca_ul = 0x5eb82b;
1628         rtlpriv->btcoexist.bt_edca_dl = 0x5eb82b;
1629     }
1630 }
1631 
1632 static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
1633 {
1634     struct rtl_priv *rtlpriv = rtl_priv(hw);
1635 
1636     /* Only enable HW BT coexist when BT in "Busy" state. */
1637     if (rtlpriv->mac80211.vendor == PEER_CISCO &&
1638         rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {
1639         rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1640     } else {
1641         if ((rtlpriv->btcoexist.bt_service == BT_BUSY) &&
1642             (rtlpriv->btcoexist.bt_rssi_state &
1643              BT_RSSI_STATE_NORMAL_POWER)) {
1644             rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1645         } else if ((rtlpriv->btcoexist.bt_service ==
1646                 BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
1647                 WIRELESS_MODE_N_24G) &&
1648                 (rtlpriv->btcoexist.bt_rssi_state &
1649                 BT_RSSI_STATE_SPECIAL_LOW)) {
1650             rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1651         } else {
1652             rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1653         }
1654     }
1655 
1656     if (rtlpriv->btcoexist.bt_service == BT_PAN)
1657         rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
1658     else
1659         rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
1660 
1661     if (rtlpriv->btcoexist.bt_rssi_state &
1662         BT_RSSI_STATE_NORMAL_POWER) {
1663         rtl92c_bt_set_normal(hw);
1664     } else {
1665         rtlpriv->btcoexist.bt_edca_ul = 0;
1666         rtlpriv->btcoexist.bt_edca_dl = 0;
1667     }
1668 
1669     if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1670         rtlpriv->cfg->ops->set_rfreg(hw,
1671                  RF90_PATH_A,
1672                  0x1e,
1673                  0xf0, 0xf);
1674     } else {
1675         rtlpriv->cfg->ops->set_rfreg(hw,
1676              RF90_PATH_A, 0x1e, 0xf0,
1677              rtlpriv->btcoexist.bt_rfreg_origin_1e);
1678     }
1679 
1680     if (!rtlpriv->dm.dynamic_txpower_enable) {
1681         if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1682             if (rtlpriv->btcoexist.bt_rssi_state &
1683                 BT_RSSI_STATE_TXPOWER_LOW) {
1684                 rtlpriv->dm.dynamic_txhighpower_lvl =
1685                             TXHIGHPWRLEVEL_BT2;
1686             } else {
1687                 rtlpriv->dm.dynamic_txhighpower_lvl =
1688                     TXHIGHPWRLEVEL_BT1;
1689             }
1690         } else {
1691             rtlpriv->dm.dynamic_txhighpower_lvl =
1692                 TXHIGHPWRLEVEL_NORMAL;
1693         }
1694         rtl92c_phy_set_txpower_level(hw,
1695             rtlpriv->phy.current_channel);
1696     }
1697 }
1698 
1699 static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
1700 {
1701     struct rtl_priv *rtlpriv = rtl_priv(hw);
1702     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1703     u8 tmp1byte = 0;
1704 
1705     if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&
1706         rtlpriv->btcoexist.bt_coexistence)
1707         tmp1byte |= BIT(5);
1708     if (rtlpriv->btcoexist.bt_cur_state) {
1709         if (rtlpriv->btcoexist.bt_ant_isolation)
1710             rtl92c_bt_ant_isolation(hw, tmp1byte);
1711     } else {
1712         rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1713         rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
1714                 rtlpriv->btcoexist.bt_rfreg_origin_1e);
1715 
1716         rtlpriv->btcoexist.bt_edca_ul = 0;
1717         rtlpriv->btcoexist.bt_edca_dl = 0;
1718     }
1719 }
1720 
1721 void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
1722 {
1723     struct rtl_priv *rtlpriv = rtl_priv(hw);
1724     bool wifi_connect_change;
1725     bool bt_state_change;
1726     bool rssi_state_change;
1727 
1728     if ((rtlpriv->btcoexist.bt_coexistence) &&
1729         (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) {
1730         wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
1731         bt_state_change = rtl92c_bt_state_change(hw);
1732         rssi_state_change = rtl92c_bt_rssi_state_change(hw);
1733 
1734         if (wifi_connect_change || bt_state_change || rssi_state_change)
1735             rtl92c_check_bt_change(hw);
1736     }
1737 }
1738 EXPORT_SYMBOL(rtl92c_dm_bt_coexist);