linux/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  Realtek Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * The full GNU General Public License is included in this distribution in the
  15 * file called LICENSE.
  16 *
  17 * Contact Information:
  18 * wlanfae <wlanfae@realtek.com>
  19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20 * Hsinchu 300, Taiwan.
  21 *
  22 * Larry Finger <Larry.Finger@lwfinger.net>
  23 *
  24 *****************************************************************************/
  25
  26#include <linux/export.h>
  27#include "dm_common.h"
  28#include "phy_common.h"
  29#include "../pci.h"
  30#include "../base.h"
  31#include "../core.h"
  32
  33#define BT_RSSI_STATE_NORMAL_POWER      BIT_OFFSET_LEN_MASK_32(0, 1)
  34#define BT_RSSI_STATE_AMDPU_OFF         BIT_OFFSET_LEN_MASK_32(1, 1)
  35#define BT_RSSI_STATE_SPECIAL_LOW       BIT_OFFSET_LEN_MASK_32(2, 1)
  36#define BT_RSSI_STATE_BG_EDCA_LOW       BIT_OFFSET_LEN_MASK_32(3, 1)
  37#define BT_RSSI_STATE_TXPOWER_LOW       BIT_OFFSET_LEN_MASK_32(4, 1)
  38#define BT_MASK                         0x00ffffff
  39
  40#define RTLPRIV                 (struct rtl_priv *)
  41#define GET_UNDECORATED_AVERAGE_RSSI(_priv)     \
  42        ((RTLPRIV(_priv))->mac80211.opmode == \
  43                             NL80211_IFTYPE_ADHOC) ?    \
  44        ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
  45        ((RTLPRIV(_priv))->dm.undec_sm_pwdb)
  46
  47static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
  48        0x7f8001fe,
  49        0x788001e2,
  50        0x71c001c7,
  51        0x6b8001ae,
  52        0x65400195,
  53        0x5fc0017f,
  54        0x5a400169,
  55        0x55400155,
  56        0x50800142,
  57        0x4c000130,
  58        0x47c0011f,
  59        0x43c0010f,
  60        0x40000100,
  61        0x3c8000f2,
  62        0x390000e4,
  63        0x35c000d7,
  64        0x32c000cb,
  65        0x300000c0,
  66        0x2d4000b5,
  67        0x2ac000ab,
  68        0x288000a2,
  69        0x26000098,
  70        0x24000090,
  71        0x22000088,
  72        0x20000080,
  73        0x1e400079,
  74        0x1c800072,
  75        0x1b00006c,
  76        0x19800066,
  77        0x18000060,
  78        0x16c0005b,
  79        0x15800056,
  80        0x14400051,
  81        0x1300004c,
  82        0x12000048,
  83        0x11000044,
  84        0x10000040,
  85};
  86
  87static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
  88        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
  89        {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
  90        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
  91        {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
  92        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
  93        {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
  94        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
  95        {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
  96        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
  97        {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
  98        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
  99        {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
 100        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
 101        {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
 102        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
 103        {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
 104        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
 105        {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
 106        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
 107        {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
 108        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
 109        {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
 110        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
 111        {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
 112        {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
 113        {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
 114        {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
 115        {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
 116        {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
 117        {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
 118        {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
 119        {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
 120        {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
 121};
 122
 123static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 124        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
 125        {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
 126        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
 127        {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
 128        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
 129        {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
 130        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
 131        {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
 132        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
 133        {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
 134        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
 135        {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
 136        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
 137        {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
 138        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
 139        {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
 140        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
 141        {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
 142        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
 143        {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
 144        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
 145        {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
 146        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
 147        {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
 148        {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
 149        {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
 150        {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
 151        {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
 152        {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
 153        {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
 154        {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
 155        {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
 156        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
 157};
 158
 159static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
 160
 161void dm_restorepowerindex(struct ieee80211_hw *hw)
 162{
 163        struct rtl_priv *rtlpriv = rtl_priv(hw);
 164        u8      index;
 165
 166        for (index = 0; index < 6; index++)
 167                rtl_write_byte(rtlpriv, power_index_reg[index],
 168                               rtlpriv->dm.powerindex_backup[index]);
 169}
 170EXPORT_SYMBOL_GPL(dm_restorepowerindex);
 171
 172void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)
 173{
 174        struct rtl_priv *rtlpriv = rtl_priv(hw);
 175        u8 index;
 176
 177        for (index = 0; index < 6; index++)
 178                rtl_write_byte(rtlpriv, power_index_reg[index], value);
 179}
 180EXPORT_SYMBOL_GPL(dm_writepowerindex);
 181
 182void dm_savepowerindex(struct ieee80211_hw *hw)
 183{
 184        struct rtl_priv *rtlpriv = rtl_priv(hw);
 185        u8 index;
 186        u8 tmp;
 187
 188        for (index = 0; index < 6; index++) {
 189                tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);
 190                rtlpriv->dm.powerindex_backup[index] = tmp;
 191        }
 192}
 193EXPORT_SYMBOL_GPL(dm_savepowerindex);
 194
 195static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 196{
 197        struct rtl_priv *rtlpriv = rtl_priv(hw);
 198        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 199        long rssi_val_min = 0;
 200
 201        if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
 202            (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
 203                if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
 204                        rssi_val_min =
 205                            (rtlpriv->dm.entry_min_undec_sm_pwdb >
 206                             rtlpriv->dm.undec_sm_pwdb) ?
 207                            rtlpriv->dm.undec_sm_pwdb :
 208                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 209                else
 210                        rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 211        } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
 212                   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
 213                rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 214        } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
 215                rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
 216        }
 217
 218        if (rssi_val_min > 100)
 219                rssi_val_min = 100;
 220        return (u8)rssi_val_min;
 221}
 222
 223static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 224{
 225        u32 ret_value;
 226        struct rtl_priv *rtlpriv = rtl_priv(hw);
 227        struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
 228
 229        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
 230        falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
 231
 232        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
 233        falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
 234        falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
 235
 236        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
 237        falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
 238
 239        ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
 240        falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
 241        falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
 242
 243        falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
 244                                      falsealm_cnt->cnt_rate_illegal +
 245                                      falsealm_cnt->cnt_crc8_fail +
 246                                      falsealm_cnt->cnt_mcs_fail +
 247                                      falsealm_cnt->cnt_fast_fsync_fail +
 248                                      falsealm_cnt->cnt_sb_search_fail;
 249
 250        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
 251        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
 252        falsealm_cnt->cnt_cck_fail = ret_value;
 253
 254        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
 255        falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 256        falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
 257                                 falsealm_cnt->cnt_rate_illegal +
 258                                 falsealm_cnt->cnt_crc8_fail +
 259                                 falsealm_cnt->cnt_mcs_fail +
 260                                 falsealm_cnt->cnt_cck_fail);
 261
 262        rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
 263        rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
 264        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
 265        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
 266
 267        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 268                 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 269                 falsealm_cnt->cnt_parity_fail,
 270                 falsealm_cnt->cnt_rate_illegal,
 271                 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
 272
 273        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 274                 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 275                 falsealm_cnt->cnt_ofdm_fail,
 276                 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
 277}
 278
 279static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
 280{
 281        struct rtl_priv *rtlpriv = rtl_priv(hw);
 282        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 283        u8 value_igi = dm_digtable->cur_igvalue;
 284
 285        if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 286                value_igi--;
 287        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
 288                value_igi += 0;
 289        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
 290                value_igi++;
 291        else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
 292                value_igi += 2;
 293
 294        if (value_igi > DM_DIG_FA_UPPER)
 295                value_igi = DM_DIG_FA_UPPER;
 296        else if (value_igi < DM_DIG_FA_LOWER)
 297                value_igi = DM_DIG_FA_LOWER;
 298
 299        if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 300                value_igi = DM_DIG_FA_UPPER;
 301
 302        dm_digtable->cur_igvalue = value_igi;
 303        rtl92c_dm_write_dig(hw);
 304}
 305
 306static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 307{
 308        struct rtl_priv *rtlpriv = rtl_priv(hw);
 309        struct dig_t *digtable = &rtlpriv->dm_digtable;
 310        u32 isbt;
 311
 312        /* modify DIG lower bound, deal with abnormally large false alarm */
 313        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 314                digtable->large_fa_hit++;
 315                if (digtable->forbidden_igi < digtable->cur_igvalue) {
 316                        digtable->forbidden_igi = digtable->cur_igvalue;
 317                        digtable->large_fa_hit = 1;
 318                }
 319
 320                if (digtable->large_fa_hit >= 3) {
 321                        if ((digtable->forbidden_igi + 1) >
 322                            digtable->rx_gain_max)
 323                                digtable->rx_gain_min = digtable->rx_gain_max;
 324                        else
 325                                digtable->rx_gain_min = (digtable->forbidden_igi + 1);
 326                        digtable->recover_cnt = 3600; /* 3600=2hr */
 327                }
 328        } else {
 329                /* Recovery mechanism for IGI lower bound */
 330                if (digtable->recover_cnt != 0) {
 331                        digtable->recover_cnt--;
 332                } else {
 333                        if (digtable->large_fa_hit == 0) {
 334                                if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
 335                                        digtable->forbidden_igi = DM_DIG_MIN;
 336                                        digtable->rx_gain_min = DM_DIG_MIN;
 337                                } else {
 338                                        digtable->forbidden_igi--;
 339                                        digtable->rx_gain_min = digtable->forbidden_igi + 1;
 340                                }
 341                        } else if (digtable->large_fa_hit == 3) {
 342                                digtable->large_fa_hit = 0;
 343                        }
 344                }
 345        }
 346        if (rtlpriv->falsealm_cnt.cnt_all < 250) {
 347                isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;
 348
 349                if (!isbt) {
 350                        if (rtlpriv->falsealm_cnt.cnt_all >
 351                            digtable->fa_lowthresh) {
 352                                if ((digtable->back_val - 2) <
 353                                   digtable->back_range_min)
 354                                        digtable->back_val = digtable->back_range_min;
 355                                else
 356                                        digtable->back_val -= 2;
 357                        } else if (rtlpriv->falsealm_cnt.cnt_all <
 358                                   digtable->fa_lowthresh) {
 359                                if ((digtable->back_val + 2) >
 360                                    digtable->back_range_max)
 361                                        digtable->back_val = digtable->back_range_max;
 362                                else
 363                                        digtable->back_val += 2;
 364                        }
 365                } else {
 366                        digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 367                }
 368        } else {
 369                /* Adjust initial gain by false alarm */
 370                if (rtlpriv->falsealm_cnt.cnt_all > 1000)
 371                        digtable->cur_igvalue = digtable->pre_igvalue + 2;
 372                else if (rtlpriv->falsealm_cnt.cnt_all > 750)
 373                        digtable->cur_igvalue = digtable->pre_igvalue + 1;
 374                else if (rtlpriv->falsealm_cnt.cnt_all < 500)
 375                        digtable->cur_igvalue = digtable->pre_igvalue - 1;
 376        }
 377
 378        /* Check initial gain by upper/lower bound */
 379        if (digtable->cur_igvalue > digtable->rx_gain_max)
 380                digtable->cur_igvalue = digtable->rx_gain_max;
 381
 382        if (digtable->cur_igvalue < digtable->rx_gain_min)
 383                digtable->cur_igvalue = digtable->rx_gain_min;
 384
 385        rtl92c_dm_write_dig(hw);
 386}
 387
 388static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 389{
 390        static u8 initialized; /* initialized to false */
 391        struct rtl_priv *rtlpriv = rtl_priv(hw);
 392        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 393        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 394        long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
 395        bool multi_sta = false;
 396
 397        if (mac->opmode == NL80211_IFTYPE_ADHOC)
 398                multi_sta = true;
 399
 400        if (!multi_sta ||
 401            dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {
 402                initialized = false;
 403                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 404                return;
 405        } else if (initialized == false) {
 406                initialized = true;
 407                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
 408                dm_digtable->cur_igvalue = 0x20;
 409                rtl92c_dm_write_dig(hw);
 410        }
 411
 412        if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
 413                if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
 414                    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
 415
 416                        if (dm_digtable->dig_ext_port_stage ==
 417                            DIG_EXT_PORT_STAGE_2) {
 418                                dm_digtable->cur_igvalue = 0x20;
 419                                rtl92c_dm_write_dig(hw);
 420                        }
 421
 422                        dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
 423                } else if (rssi_strength > dm_digtable->rssi_highthresh) {
 424                        dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
 425                        rtl92c_dm_ctrl_initgain_by_fa(hw);
 426                }
 427        } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
 428                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
 429                dm_digtable->cur_igvalue = 0x20;
 430                rtl92c_dm_write_dig(hw);
 431        }
 432
 433        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 434                 "curmultista_cstate = %x dig_ext_port_stage %x\n",
 435                 dm_digtable->curmultista_cstate,
 436                 dm_digtable->dig_ext_port_stage);
 437}
 438
 439static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
 440{
 441        struct rtl_priv *rtlpriv = rtl_priv(hw);
 442        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 443
 444        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 445                 "presta_cstate = %x, cursta_cstate = %x\n",
 446                 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
 447        if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
 448            dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
 449            dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 450
 451                if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
 452                        dm_digtable->rssi_val_min =
 453                            rtl92c_dm_initial_gain_min_pwdb(hw);
 454                        if (dm_digtable->rssi_val_min > 100)
 455                                dm_digtable->rssi_val_min = 100;
 456                        rtl92c_dm_ctrl_initgain_by_rssi(hw);
 457                }
 458        } else {
 459                dm_digtable->rssi_val_min = 0;
 460                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 461                dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 462                dm_digtable->cur_igvalue = 0x20;
 463                dm_digtable->pre_igvalue = 0;
 464                rtl92c_dm_write_dig(hw);
 465        }
 466}
 467
 468static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 469{
 470        struct rtl_priv *rtlpriv = rtl_priv(hw);
 471        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 472
 473        if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 474                dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
 475                if (dm_digtable->rssi_val_min > 100)
 476                        dm_digtable->rssi_val_min = 100;
 477
 478                if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
 479                        if (dm_digtable->rssi_val_min <= 25)
 480                                dm_digtable->cur_cck_pd_state =
 481                                    CCK_PD_STAGE_LOWRSSI;
 482                        else
 483                                dm_digtable->cur_cck_pd_state =
 484                                    CCK_PD_STAGE_HIGHRSSI;
 485                } else {
 486                        if (dm_digtable->rssi_val_min <= 20)
 487                                dm_digtable->cur_cck_pd_state =
 488                                    CCK_PD_STAGE_LOWRSSI;
 489                        else
 490                                dm_digtable->cur_cck_pd_state =
 491                                    CCK_PD_STAGE_HIGHRSSI;
 492                }
 493        } else {
 494                dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
 495        }
 496
 497        if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
 498                if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) ||
 499                    (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))
 500                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
 501                else
 502                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
 503
 504                dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
 505        }
 506}
 507
 508static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 509{
 510        struct rtl_priv *rtlpriv = rtl_priv(hw);
 511        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 512        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 513
 514        if (mac->act_scanning)
 515                return;
 516
 517        if (mac->link_state >= MAC80211_LINKED)
 518                dm_digtable->cursta_cstate = DIG_STA_CONNECT;
 519        else
 520                dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
 521
 522        dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
 523
 524        rtl92c_dm_initial_gain_sta(hw);
 525        rtl92c_dm_initial_gain_multi_sta(hw);
 526        rtl92c_dm_cck_packet_detection_thresh(hw);
 527
 528        dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
 529
 530}
 531
 532static void rtl92c_dm_dig(struct ieee80211_hw *hw)
 533{
 534        struct rtl_priv *rtlpriv = rtl_priv(hw);
 535
 536        if (rtlpriv->dm.dm_initialgain_enable == false)
 537                return;
 538        if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
 539                return;
 540
 541        rtl92c_dm_ctrl_initgain_by_twoport(hw);
 542}
 543
 544static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
 545{
 546        struct rtl_priv *rtlpriv = rtl_priv(hw);
 547
 548        if (rtlpriv->rtlhal.interface == INTF_USB &&
 549            rtlpriv->rtlhal.board_type & 0x1) {
 550                dm_savepowerindex(hw);
 551                rtlpriv->dm.dynamic_txpower_enable = true;
 552        } else {
 553                rtlpriv->dm.dynamic_txpower_enable = false;
 554        }
 555        rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
 556        rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 557}
 558
 559void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
 560{
 561        struct rtl_priv *rtlpriv = rtl_priv(hw);
 562        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 563
 564        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 565                 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
 566                 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
 567                 dm_digtable->back_val);
 568
 569        if (rtlpriv->rtlhal.interface == INTF_USB &&
 570            !dm_digtable->dig_enable_flag) {
 571                dm_digtable->pre_igvalue = 0x17;
 572                return;
 573        }
 574        dm_digtable->cur_igvalue -= 1;
 575        if (dm_digtable->cur_igvalue < DM_DIG_MIN)
 576                dm_digtable->cur_igvalue = DM_DIG_MIN;
 577
 578        if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
 579                rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 580                              dm_digtable->cur_igvalue);
 581                rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
 582                              dm_digtable->cur_igvalue);
 583
 584                dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
 585        }
 586        RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING,
 587                 "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 588                 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
 589                 dm_digtable->rssi_val_min, dm_digtable->back_val,
 590                 dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,
 591                 dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);
 592}
 593EXPORT_SYMBOL(rtl92c_dm_write_dig);
 594
 595static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
 596{
 597        struct rtl_priv *rtlpriv = rtl_priv(hw);
 598        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 599        long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
 600
 601        if (mac->link_state != MAC80211_LINKED)
 602                return;
 603
 604        if (mac->opmode == NL80211_IFTYPE_ADHOC ||
 605            mac->opmode == NL80211_IFTYPE_AP) {
 606                /* TODO: Handle ADHOC and AP Mode */
 607        }
 608
 609        if (tmpentry_max_pwdb != 0)
 610                rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
 611        else
 612                rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 613
 614        if (tmpentry_min_pwdb != 0xff)
 615                rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
 616        else
 617                rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 618
 619/* TODO:
 620 *      if (mac->opmode == NL80211_IFTYPE_STATION) {
 621 *              if (rtlpriv->rtlhal.fw_ready) {
 622 *                      u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);
 623 *                      rtl8192c_set_rssi_cmd(hw, param);
 624 *              }
 625 *      }
 626 */
 627}
 628
 629void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
 630{
 631        struct rtl_priv *rtlpriv = rtl_priv(hw);
 632        rtlpriv->dm.current_turbo_edca = false;
 633        rtlpriv->dm.is_any_nonbepkts = false;
 634        rtlpriv->dm.is_cur_rdlstate = false;
 635}
 636EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
 637
 638static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
 639{
 640        struct rtl_priv *rtlpriv = rtl_priv(hw);
 641        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 642
 643        static u64 last_txok_cnt;
 644        static u64 last_rxok_cnt;
 645        static u32 last_bt_edca_ul;
 646        static u32 last_bt_edca_dl;
 647        u64 cur_txok_cnt = 0;
 648        u64 cur_rxok_cnt = 0;
 649        u32 edca_be_ul = 0x5ea42b;
 650        u32 edca_be_dl = 0x5ea42b;
 651        bool bt_change_edca = false;
 652
 653        if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||
 654            (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {
 655                rtlpriv->dm.current_turbo_edca = false;
 656                last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;
 657                last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;
 658        }
 659
 660        if (rtlpriv->btcoexist.bt_edca_ul != 0) {
 661                edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;
 662                bt_change_edca = true;
 663        }
 664
 665        if (rtlpriv->btcoexist.bt_edca_dl != 0) {
 666                edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
 667                bt_change_edca = true;
 668        }
 669
 670        if (mac->link_state != MAC80211_LINKED) {
 671                rtlpriv->dm.current_turbo_edca = false;
 672                return;
 673        }
 674
 675        if ((!mac->ht_enable) && (!rtlpriv->btcoexist.bt_coexistence)) {
 676                if (!(edca_be_ul & 0xffff0000))
 677                        edca_be_ul |= 0x005e0000;
 678
 679                if (!(edca_be_dl & 0xffff0000))
 680                        edca_be_dl |= 0x005e0000;
 681        }
 682
 683        if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
 684             (!rtlpriv->dm.disable_framebursting))) {
 685
 686                cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
 687                cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
 688
 689                if (cur_rxok_cnt > 4 * cur_txok_cnt) {
 690                        if (!rtlpriv->dm.is_cur_rdlstate ||
 691                            !rtlpriv->dm.current_turbo_edca) {
 692                                rtl_write_dword(rtlpriv,
 693                                                REG_EDCA_BE_PARAM,
 694                                                edca_be_dl);
 695                                rtlpriv->dm.is_cur_rdlstate = true;
 696                        }
 697                } else {
 698                        if (rtlpriv->dm.is_cur_rdlstate ||
 699                            !rtlpriv->dm.current_turbo_edca) {
 700                                rtl_write_dword(rtlpriv,
 701                                                REG_EDCA_BE_PARAM,
 702                                                edca_be_ul);
 703                                rtlpriv->dm.is_cur_rdlstate = false;
 704                        }
 705                }
 706                rtlpriv->dm.current_turbo_edca = true;
 707        } else {
 708                if (rtlpriv->dm.current_turbo_edca) {
 709                        u8 tmp = AC0_BE;
 710                        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
 711                                                      &tmp);
 712                        rtlpriv->dm.current_turbo_edca = false;
 713                }
 714        }
 715
 716        rtlpriv->dm.is_any_nonbepkts = false;
 717        last_txok_cnt = rtlpriv->stats.txbytesunicast;
 718        last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
 719}
 720
 721static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
 722                                                             *hw)
 723{
 724        struct rtl_priv *rtlpriv = rtl_priv(hw);
 725        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 726        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 727        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 728        u8 thermalvalue, delta, delta_lck, delta_iqk;
 729        long ele_a, ele_d, temp_cck, val_x, value32;
 730        long val_y, ele_c = 0;
 731        u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
 732        s8 cck_index = 0;
 733        int i;
 734        bool is2t = IS_92C_SERIAL(rtlhal->version);
 735        s8 txpwr_level[3] = {0, 0, 0};
 736        u8 ofdm_min_index = 6, rf;
 737
 738        rtlpriv->dm.txpower_trackinginit = true;
 739        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 740                 "rtl92c_dm_txpower_tracking_callback_thermalmeter\n");
 741
 742        thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
 743
 744        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 745                 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
 746                 thermalvalue, rtlpriv->dm.thermalvalue,
 747                 rtlefuse->eeprom_thermalmeter);
 748
 749        rtl92c_phy_ap_calibrate(hw, (thermalvalue -
 750                                     rtlefuse->eeprom_thermalmeter));
 751        if (is2t)
 752                rf = 2;
 753        else
 754                rf = 1;
 755
 756        if (thermalvalue) {
 757                ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
 758                                      MASKDWORD) & MASKOFDM_D;
 759
 760                for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
 761                        if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
 762                                ofdm_index_old[0] = (u8) i;
 763
 764                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 765                                         "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
 766                                         ROFDM0_XATXIQIMBALANCE,
 767                                         ele_d, ofdm_index_old[0]);
 768                                break;
 769                        }
 770                }
 771
 772                if (is2t) {
 773                        ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
 774                                              MASKDWORD) & MASKOFDM_D;
 775
 776                        for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
 777                                if (ele_d == (ofdmswing_table[i] &
 778                                    MASKOFDM_D)) {
 779                                        ofdm_index_old[1] = (u8) i;
 780                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
 781                                                 DBG_LOUD,
 782                                                 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
 783                                                 ROFDM0_XBTXIQIMBALANCE, ele_d,
 784                                                 ofdm_index_old[1]);
 785                                        break;
 786                                }
 787                        }
 788                }
 789
 790                temp_cck =
 791                    rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
 792
 793                for (i = 0; i < CCK_TABLE_LENGTH; i++) {
 794                        if (rtlpriv->dm.cck_inch14) {
 795                                if (memcmp((void *)&temp_cck,
 796                                           (void *)&cckswing_table_ch14[i][2],
 797                                           4) == 0) {
 798                                        cck_index_old = (u8) i;
 799
 800                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
 801                                                 DBG_LOUD,
 802                                                 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",
 803                                                 RCCK0_TXFILTER2, temp_cck,
 804                                                 cck_index_old,
 805                                                 rtlpriv->dm.cck_inch14);
 806                                        break;
 807                                }
 808                        } else {
 809                                if (memcmp((void *)&temp_cck,
 810                                           (void *)
 811                                           &cckswing_table_ch1ch13[i][2],
 812                                           4) == 0) {
 813                                        cck_index_old = (u8) i;
 814
 815                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
 816                                                 DBG_LOUD,
 817                                                 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",
 818                                                 RCCK0_TXFILTER2, temp_cck,
 819                                                 cck_index_old,
 820                                                 rtlpriv->dm.cck_inch14);
 821                                        break;
 822                                }
 823                        }
 824                }
 825
 826                if (!rtlpriv->dm.thermalvalue) {
 827                        rtlpriv->dm.thermalvalue =
 828                            rtlefuse->eeprom_thermalmeter;
 829                        rtlpriv->dm.thermalvalue_lck = thermalvalue;
 830                        rtlpriv->dm.thermalvalue_iqk = thermalvalue;
 831                        for (i = 0; i < rf; i++)
 832                                rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
 833                        rtlpriv->dm.cck_index = cck_index_old;
 834                }
 835                /* Handle USB High PA boards */
 836
 837                delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
 838                    (thermalvalue - rtlpriv->dm.thermalvalue) :
 839                    (rtlpriv->dm.thermalvalue - thermalvalue);
 840
 841                delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
 842                    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
 843                    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
 844
 845                delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
 846                    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
 847                    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
 848
 849                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 850                         "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",
 851                         thermalvalue, rtlpriv->dm.thermalvalue,
 852                         rtlefuse->eeprom_thermalmeter, delta, delta_lck,
 853                         delta_iqk);
 854
 855                if (delta_lck > 1) {
 856                        rtlpriv->dm.thermalvalue_lck = thermalvalue;
 857                        rtl92c_phy_lc_calibrate(hw);
 858                }
 859
 860                if (delta > 0 && rtlpriv->dm.txpower_track_control) {
 861                        if (thermalvalue > rtlpriv->dm.thermalvalue) {
 862                                for (i = 0; i < rf; i++)
 863                                        rtlpriv->dm.ofdm_index[i] -= delta;
 864                                rtlpriv->dm.cck_index -= delta;
 865                        } else {
 866                                for (i = 0; i < rf; i++)
 867                                        rtlpriv->dm.ofdm_index[i] += delta;
 868                                rtlpriv->dm.cck_index += delta;
 869                        }
 870
 871                        if (is2t) {
 872                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 873                                         "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
 874                                         rtlpriv->dm.ofdm_index[0],
 875                                         rtlpriv->dm.ofdm_index[1],
 876                                         rtlpriv->dm.cck_index);
 877                        } else {
 878                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 879                                         "temp OFDM_A_index=0x%x, cck_index=0x%x\n",
 880                                         rtlpriv->dm.ofdm_index[0],
 881                                         rtlpriv->dm.cck_index);
 882                        }
 883
 884                        if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
 885                                for (i = 0; i < rf; i++)
 886                                        ofdm_index[i] =
 887                                            rtlpriv->dm.ofdm_index[i]
 888                                            + 1;
 889                                cck_index = rtlpriv->dm.cck_index + 1;
 890                        } else {
 891                                for (i = 0; i < rf; i++)
 892                                        ofdm_index[i] =
 893                                            rtlpriv->dm.ofdm_index[i];
 894                                cck_index = rtlpriv->dm.cck_index;
 895                        }
 896
 897                        for (i = 0; i < rf; i++) {
 898                                if (txpwr_level[i] >= 0 &&
 899                                    txpwr_level[i] <= 26) {
 900                                        if (thermalvalue >
 901                                            rtlefuse->eeprom_thermalmeter) {
 902                                                if (delta < 5)
 903                                                        ofdm_index[i] -= 1;
 904
 905                                                else
 906                                                        ofdm_index[i] -= 2;
 907                                        } else if (delta > 5 && thermalvalue <
 908                                                   rtlefuse->
 909                                                   eeprom_thermalmeter) {
 910                                                ofdm_index[i] += 1;
 911                                        }
 912                                } else if (txpwr_level[i] >= 27 &&
 913                                           txpwr_level[i] <= 32
 914                                           && thermalvalue >
 915                                           rtlefuse->eeprom_thermalmeter) {
 916                                        if (delta < 5)
 917                                                ofdm_index[i] -= 1;
 918
 919                                        else
 920                                                ofdm_index[i] -= 2;
 921                                } else if (txpwr_level[i] >= 32 &&
 922                                           txpwr_level[i] <= 38 &&
 923                                           thermalvalue >
 924                                           rtlefuse->eeprom_thermalmeter
 925                                           && delta > 5) {
 926                                        ofdm_index[i] -= 1;
 927                                }
 928                        }
 929
 930                        if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
 931                                if (thermalvalue >
 932                                    rtlefuse->eeprom_thermalmeter) {
 933                                        if (delta < 5)
 934                                                cck_index -= 1;
 935
 936                                        else
 937                                                cck_index -= 2;
 938                                } else if (delta > 5 && thermalvalue <
 939                                           rtlefuse->eeprom_thermalmeter) {
 940                                        cck_index += 1;
 941                                }
 942                        } else if (txpwr_level[i] >= 27 &&
 943                                   txpwr_level[i] <= 32 &&
 944                                   thermalvalue >
 945                                   rtlefuse->eeprom_thermalmeter) {
 946                                if (delta < 5)
 947                                        cck_index -= 1;
 948
 949                                else
 950                                        cck_index -= 2;
 951                        } else if (txpwr_level[i] >= 32 &&
 952                                   txpwr_level[i] <= 38 &&
 953                                   thermalvalue > rtlefuse->eeprom_thermalmeter
 954                                   && delta > 5) {
 955                                cck_index -= 1;
 956                        }
 957
 958                        for (i = 0; i < rf; i++) {
 959                                if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
 960                                        ofdm_index[i] = OFDM_TABLE_SIZE - 1;
 961
 962                                else if (ofdm_index[i] < ofdm_min_index)
 963                                        ofdm_index[i] = ofdm_min_index;
 964                        }
 965
 966                        if (cck_index > CCK_TABLE_SIZE - 1)
 967                                cck_index = CCK_TABLE_SIZE - 1;
 968                        else if (cck_index < 0)
 969                                cck_index = 0;
 970
 971                        if (is2t) {
 972                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 973                                         "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
 974                                         ofdm_index[0], ofdm_index[1],
 975                                         cck_index);
 976                        } else {
 977                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 978                                         "new OFDM_A_index=0x%x, cck_index=0x%x\n",
 979                                         ofdm_index[0], cck_index);
 980                        }
 981                }
 982
 983                if (rtlpriv->dm.txpower_track_control && delta != 0) {
 984                        ele_d =
 985                            (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
 986                        val_x = rtlphy->reg_e94;
 987                        val_y = rtlphy->reg_e9c;
 988
 989                        if (val_x != 0) {
 990                                if ((val_x & 0x00000200) != 0)
 991                                        val_x = val_x | 0xFFFFFC00;
 992                                ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
 993
 994                                if ((val_y & 0x00000200) != 0)
 995                                        val_y = val_y | 0xFFFFFC00;
 996                                ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
 997
 998                                value32 = (ele_d << 22) |
 999                                    ((ele_c & 0x3F) << 16) | ele_a;
1000
1001                                rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1002                                              MASKDWORD, value32);
1003
1004                                value32 = (ele_c & 0x000003C0) >> 6;
1005                                rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1006                                              value32);
1007
1008                                value32 = ((val_x * ele_d) >> 7) & 0x01;
1009                                rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1010                                              BIT(31), value32);
1011
1012                                value32 = ((val_y * ele_d) >> 7) & 0x01;
1013                                rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1014                                              BIT(29), value32);
1015                        } else {
1016                                rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1017                                              MASKDWORD,
1018                                              ofdmswing_table[ofdm_index[0]]);
1019
1020                                rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1021                                              0x00);
1022                                rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1023                                              BIT(31) | BIT(29), 0x00);
1024                        }
1025
1026                        if (!rtlpriv->dm.cck_inch14) {
1027                                rtl_write_byte(rtlpriv, 0xa22,
1028                                               cckswing_table_ch1ch13[cck_index]
1029                                               [0]);
1030                                rtl_write_byte(rtlpriv, 0xa23,
1031                                               cckswing_table_ch1ch13[cck_index]
1032                                               [1]);
1033                                rtl_write_byte(rtlpriv, 0xa24,
1034                                               cckswing_table_ch1ch13[cck_index]
1035                                               [2]);
1036                                rtl_write_byte(rtlpriv, 0xa25,
1037                                               cckswing_table_ch1ch13[cck_index]
1038                                               [3]);
1039                                rtl_write_byte(rtlpriv, 0xa26,
1040                                               cckswing_table_ch1ch13[cck_index]
1041                                               [4]);
1042                                rtl_write_byte(rtlpriv, 0xa27,
1043                                               cckswing_table_ch1ch13[cck_index]
1044                                               [5]);
1045                                rtl_write_byte(rtlpriv, 0xa28,
1046                                               cckswing_table_ch1ch13[cck_index]
1047                                               [6]);
1048                                rtl_write_byte(rtlpriv, 0xa29,
1049                                               cckswing_table_ch1ch13[cck_index]
1050                                               [7]);
1051                        } else {
1052                                rtl_write_byte(rtlpriv, 0xa22,
1053                                               cckswing_table_ch14[cck_index]
1054                                               [0]);
1055                                rtl_write_byte(rtlpriv, 0xa23,
1056                                               cckswing_table_ch14[cck_index]
1057                                               [1]);
1058                                rtl_write_byte(rtlpriv, 0xa24,
1059                                               cckswing_table_ch14[cck_index]
1060                                               [2]);
1061                                rtl_write_byte(rtlpriv, 0xa25,
1062                                               cckswing_table_ch14[cck_index]
1063                                               [3]);
1064                                rtl_write_byte(rtlpriv, 0xa26,
1065                                               cckswing_table_ch14[cck_index]
1066                                               [4]);
1067                                rtl_write_byte(rtlpriv, 0xa27,
1068                                               cckswing_table_ch14[cck_index]
1069                                               [5]);
1070                                rtl_write_byte(rtlpriv, 0xa28,
1071                                               cckswing_table_ch14[cck_index]
1072                                               [6]);
1073                                rtl_write_byte(rtlpriv, 0xa29,
1074                                               cckswing_table_ch14[cck_index]
1075                                               [7]);
1076                        }
1077
1078                        if (is2t) {
1079                                ele_d = (ofdmswing_table[ofdm_index[1]] &
1080                                         0xFFC00000) >> 22;
1081
1082                                val_x = rtlphy->reg_eb4;
1083                                val_y = rtlphy->reg_ebc;
1084
1085                                if (val_x != 0) {
1086                                        if ((val_x & 0x00000200) != 0)
1087                                                val_x = val_x | 0xFFFFFC00;
1088                                        ele_a = ((val_x * ele_d) >> 8) &
1089                                            0x000003FF;
1090
1091                                        if ((val_y & 0x00000200) != 0)
1092                                                val_y = val_y | 0xFFFFFC00;
1093                                        ele_c = ((val_y * ele_d) >> 8) &
1094                                            0x00003FF;
1095
1096                                        value32 = (ele_d << 22) |
1097                                            ((ele_c & 0x3F) << 16) | ele_a;
1098                                        rtl_set_bbreg(hw,
1099                                                      ROFDM0_XBTXIQIMBALANCE,
1100                                                      MASKDWORD, value32);
1101
1102                                        value32 = (ele_c & 0x000003C0) >> 6;
1103                                        rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1104                                                      MASKH4BITS, value32);
1105
1106                                        value32 = ((val_x * ele_d) >> 7) & 0x01;
1107                                        rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1108                                                      BIT(27), value32);
1109
1110                                        value32 = ((val_y * ele_d) >> 7) & 0x01;
1111                                        rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1112                                                      BIT(25), value32);
1113                                } else {
1114                                        rtl_set_bbreg(hw,
1115                                                      ROFDM0_XBTXIQIMBALANCE,
1116                                                      MASKDWORD,
1117                                                      ofdmswing_table[ofdm_index
1118                                                                      [1]]);
1119                                        rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1120                                                      MASKH4BITS, 0x00);
1121                                        rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1122                                                      BIT(27) | BIT(25), 0x00);
1123                                }
1124
1125                        }
1126                }
1127
1128                if (delta_iqk > 3) {
1129                        rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1130                        rtl92c_phy_iq_calibrate(hw, false);
1131                }
1132
1133                if (rtlpriv->dm.txpower_track_control)
1134                        rtlpriv->dm.thermalvalue = thermalvalue;
1135        }
1136
1137        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
1138
1139}
1140
1141static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
1142                                                struct ieee80211_hw *hw)
1143{
1144        struct rtl_priv *rtlpriv = rtl_priv(hw);
1145
1146        rtlpriv->dm.txpower_tracking = true;
1147        rtlpriv->dm.txpower_trackinginit = false;
1148
1149        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1150                 "pMgntInfo->txpower_tracking = %d\n",
1151                 rtlpriv->dm.txpower_tracking);
1152}
1153
1154static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
1155{
1156        rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
1157}
1158
1159static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
1160{
1161        rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
1162}
1163
1164static void rtl92c_dm_check_txpower_tracking_thermal_meter(
1165                                                struct ieee80211_hw *hw)
1166{
1167        struct rtl_priv *rtlpriv = rtl_priv(hw);
1168
1169        if (!rtlpriv->dm.txpower_tracking)
1170                return;
1171
1172        if (!rtlpriv->dm.tm_trigger) {
1173                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
1174                              0x60);
1175                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1176                         "Trigger 92S Thermal Meter!!\n");
1177                rtlpriv->dm.tm_trigger = 1;
1178                return;
1179        } else {
1180                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1181                         "Schedule TxPowerTracking direct call!!\n");
1182                rtl92c_dm_txpower_tracking_directcall(hw);
1183                rtlpriv->dm.tm_trigger = 0;
1184        }
1185}
1186
1187void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1188{
1189        rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
1190}
1191EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
1192
1193void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1194{
1195        struct rtl_priv *rtlpriv = rtl_priv(hw);
1196        struct rate_adaptive *p_ra = &(rtlpriv->ra);
1197
1198        p_ra->ratr_state = DM_RATR_STA_INIT;
1199        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1200
1201        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1202                rtlpriv->dm.useramask = true;
1203        else
1204                rtlpriv->dm.useramask = false;
1205
1206}
1207EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
1208
1209static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1210{
1211        struct rtl_priv *rtlpriv = rtl_priv(hw);
1212        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1213
1214        dm_pstable->pre_ccastate = CCA_MAX;
1215        dm_pstable->cur_ccasate = CCA_MAX;
1216        dm_pstable->pre_rfstate = RF_MAX;
1217        dm_pstable->cur_rfstate = RF_MAX;
1218        dm_pstable->rssi_val_min = 0;
1219}
1220
1221void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
1222{
1223        struct rtl_priv *rtlpriv = rtl_priv(hw);
1224        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1225
1226        if (!rtlpriv->reg_init) {
1227                rtlpriv->reg_874 = (rtl_get_bbreg(hw,
1228                                                  RFPGA0_XCD_RFINTERFACESW,
1229                                                  MASKDWORD) & 0x1CC000) >> 14;
1230
1231                rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
1232                                    MASKDWORD) & BIT(3)) >> 3;
1233
1234                rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1235                                    MASKDWORD) & 0xFF000000) >> 24;
1236
1237                rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
1238                                    0xF000) >> 12;
1239
1240                rtlpriv->reg_init = true;
1241        }
1242
1243        if (!bforce_in_normal) {
1244                if (dm_pstable->rssi_val_min != 0) {
1245                        if (dm_pstable->pre_rfstate == RF_NORMAL) {
1246                                if (dm_pstable->rssi_val_min >= 30)
1247                                        dm_pstable->cur_rfstate = RF_SAVE;
1248                                else
1249                                        dm_pstable->cur_rfstate = RF_NORMAL;
1250                        } else {
1251                                if (dm_pstable->rssi_val_min <= 25)
1252                                        dm_pstable->cur_rfstate = RF_NORMAL;
1253                                else
1254                                        dm_pstable->cur_rfstate = RF_SAVE;
1255                        }
1256                } else {
1257                        dm_pstable->cur_rfstate = RF_MAX;
1258                }
1259        } else {
1260                dm_pstable->cur_rfstate = RF_NORMAL;
1261        }
1262
1263        if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
1264                if (dm_pstable->cur_rfstate == RF_SAVE) {
1265                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1266                                      0x1C0000, 0x2);
1267                        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
1268                        rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1269                                      0xFF000000, 0x63);
1270                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1271                                      0xC000, 0x2);
1272                        rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
1273                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1274                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
1275                } else {
1276                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1277                                      0x1CC000, rtlpriv->reg_874);
1278                        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
1279                                      rtlpriv->reg_c70);
1280                        rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
1281                                      rtlpriv->reg_85c);
1282                        rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
1283                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1284                }
1285
1286                dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
1287        }
1288}
1289EXPORT_SYMBOL(rtl92c_dm_rf_saving);
1290
1291static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1292{
1293        struct rtl_priv *rtlpriv = rtl_priv(hw);
1294        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1295        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1296        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1297
1298        /* Determine the minimum RSSI */
1299        if (((mac->link_state == MAC80211_NOLINK)) &&
1300            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1301                dm_pstable->rssi_val_min = 0;
1302                RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
1303        }
1304
1305        if (mac->link_state == MAC80211_LINKED) {
1306                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1307                        dm_pstable->rssi_val_min =
1308                            rtlpriv->dm.entry_min_undec_sm_pwdb;
1309                        RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1310                                 "AP Client PWDB = 0x%lx\n",
1311                                 dm_pstable->rssi_val_min);
1312                } else {
1313                        dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
1314                        RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1315                                 "STA Default Port PWDB = 0x%lx\n",
1316                                 dm_pstable->rssi_val_min);
1317                }
1318        } else {
1319                dm_pstable->rssi_val_min =
1320                    rtlpriv->dm.entry_min_undec_sm_pwdb;
1321
1322                RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1323                         "AP Ext Port PWDB = 0x%lx\n",
1324                         dm_pstable->rssi_val_min);
1325        }
1326
1327        /* Power Saving for 92C */
1328        if (IS_92C_SERIAL(rtlhal->version))
1329                ;/* rtl92c_dm_1r_cca(hw); */
1330        else
1331                rtl92c_dm_rf_saving(hw, false);
1332}
1333
1334void rtl92c_dm_init(struct ieee80211_hw *hw)
1335{
1336        struct rtl_priv *rtlpriv = rtl_priv(hw);
1337
1338        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1339        rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;
1340        rtlpriv->dm.undec_sm_pwdb = -1;
1341        rtlpriv->dm.undec_sm_cck = -1;
1342        rtlpriv->dm.dm_initialgain_enable = true;
1343        rtl_dm_diginit(hw, 0x20);
1344
1345        rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;
1346        rtl92c_dm_init_dynamic_txpower(hw);
1347
1348        rtl92c_dm_init_edca_turbo(hw);
1349        rtl92c_dm_init_rate_adaptive_mask(hw);
1350        rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;
1351        rtl92c_dm_initialize_txpower_tracking(hw);
1352        rtl92c_dm_init_dynamic_bb_powersaving(hw);
1353
1354        rtlpriv->dm.ofdm_pkt_cnt = 0;
1355        rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;
1356}
1357EXPORT_SYMBOL(rtl92c_dm_init);
1358
1359void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
1360{
1361        struct rtl_priv *rtlpriv = rtl_priv(hw);
1362        struct rtl_phy *rtlphy = &(rtlpriv->phy);
1363        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1364        long undec_sm_pwdb;
1365
1366        if (!rtlpriv->dm.dynamic_txpower_enable)
1367                return;
1368
1369        if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
1370                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1371                return;
1372        }
1373
1374        if ((mac->link_state < MAC80211_LINKED) &&
1375            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1376                RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
1377                         "Not connected to any\n");
1378
1379                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1380
1381                rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
1382                return;
1383        }
1384
1385        if (mac->link_state >= MAC80211_LINKED) {
1386                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1387                        undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1388                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1389                                 "AP Client PWDB = 0x%lx\n",
1390                                 undec_sm_pwdb);
1391                } else {
1392                        undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
1393                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1394                                 "STA Default Port PWDB = 0x%lx\n",
1395                                 undec_sm_pwdb);
1396                }
1397        } else {
1398                undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1399
1400                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1401                         "AP Ext Port PWDB = 0x%lx\n",
1402                         undec_sm_pwdb);
1403        }
1404
1405        if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
1406                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;
1407                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1408                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
1409        } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
1410                   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
1411
1412                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1413                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1414                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
1415        } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
1416                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1417                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1418                         "TXHIGHPWRLEVEL_NORMAL\n");
1419        }
1420
1421        if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
1422                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1423                         "PHY_SetTxPowerLevel8192S() Channel = %d\n",
1424                         rtlphy->current_channel);
1425                rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
1426                if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1427                    TXHIGHPWRLEVEL_NORMAL)
1428                        dm_restorepowerindex(hw);
1429                else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1430                         TXHIGHPWRLEVEL_LEVEL1)
1431                        dm_writepowerindex(hw, 0x14);
1432                else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1433                         TXHIGHPWRLEVEL_LEVEL2)
1434                        dm_writepowerindex(hw, 0x10);
1435        }
1436        rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
1437}
1438
1439void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
1440{
1441        struct rtl_priv *rtlpriv = rtl_priv(hw);
1442        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1443        bool fw_current_inpsmode = false;
1444        bool fw_ps_awake = true;
1445
1446        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1447                                      (u8 *) (&fw_current_inpsmode));
1448        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1449                                      (u8 *) (&fw_ps_awake));
1450
1451        if (ppsc->p2p_ps_info.p2p_ps_mode)
1452                fw_ps_awake = false;
1453
1454        if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
1455                                             fw_ps_awake)
1456            && (!ppsc->rfchange_inprogress)) {
1457                rtl92c_dm_pwdb_monitor(hw);
1458                rtl92c_dm_dig(hw);
1459                rtl92c_dm_false_alarm_counter_statistics(hw);
1460                rtl92c_dm_dynamic_bb_powersaving(hw);
1461                rtl92c_dm_dynamic_txpower(hw);
1462                rtl92c_dm_check_txpower_tracking(hw);
1463                /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
1464                rtl92c_dm_bt_coexist(hw);
1465                rtl92c_dm_check_edca_turbo(hw);
1466        }
1467}
1468EXPORT_SYMBOL(rtl92c_dm_watchdog);
1469
1470u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
1471{
1472        struct rtl_priv *rtlpriv = rtl_priv(hw);
1473        long undec_sm_pwdb;
1474        u8 curr_bt_rssi_state = 0x00;
1475
1476        if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1477                undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
1478        } else {
1479                if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
1480                        undec_sm_pwdb = 100;
1481                else
1482                        undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1483        }
1484
1485        /* Check RSSI to determine HighPower/NormalPower state for
1486         * BT coexistence. */
1487        if (undec_sm_pwdb >= 67)
1488                curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
1489        else if (undec_sm_pwdb < 62)
1490                curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
1491
1492        /* Check RSSI to determine AMPDU setting for BT coexistence. */
1493        if (undec_sm_pwdb >= 40)
1494                curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
1495        else if (undec_sm_pwdb <= 32)
1496                curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
1497
1498        /* Marked RSSI state. It will be used to determine BT coexistence
1499         * setting later. */
1500        if (undec_sm_pwdb < 35)
1501                curr_bt_rssi_state |=  BT_RSSI_STATE_SPECIAL_LOW;
1502        else
1503                curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
1504
1505        /* Check BT state related to BT_Idle in B/G mode. */
1506        if (undec_sm_pwdb < 15)
1507                curr_bt_rssi_state |=  BT_RSSI_STATE_BG_EDCA_LOW;
1508        else
1509                curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
1510
1511        if (curr_bt_rssi_state != rtlpriv->btcoexist.bt_rssi_state) {
1512                rtlpriv->btcoexist.bt_rssi_state = curr_bt_rssi_state;
1513                return true;
1514        } else {
1515                return false;
1516        }
1517}
1518EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
1519
1520static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
1521{
1522        struct rtl_priv *rtlpriv = rtl_priv(hw);
1523
1524        u32 polling, ratio_tx, ratio_pri;
1525        u32 bt_tx, bt_pri;
1526        u8 bt_state;
1527        u8 cur_service_type;
1528
1529        if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
1530                return false;
1531
1532        bt_state = rtl_read_byte(rtlpriv, 0x4fd);
1533        bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK;
1534        bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK;
1535        polling = rtl_read_dword(rtlpriv, 0x490);
1536
1537        if (bt_tx == BT_MASK && bt_pri == BT_MASK &&
1538            polling == 0xffffffff && bt_state == 0xff)
1539                return false;
1540
1541        bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1);
1542        if (bt_state != rtlpriv->btcoexist.bt_cur_state) {
1543                rtlpriv->btcoexist.bt_cur_state = bt_state;
1544
1545                if (rtlpriv->btcoexist.reg_bt_sco == 3) {
1546                        rtlpriv->btcoexist.bt_service = BT_IDLE;
1547
1548                        bt_state = bt_state |
1549                          ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
1550                          0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1551                          BIT_OFFSET_LEN_MASK_32(2, 1);
1552                        rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1553                }
1554                return true;
1555        }
1556
1557        ratio_tx = bt_tx * 1000 / polling;
1558        ratio_pri = bt_pri * 1000 / polling;
1559        rtlpriv->btcoexist.ratio_tx = ratio_tx;
1560        rtlpriv->btcoexist.ratio_pri = ratio_pri;
1561
1562        if (bt_state && rtlpriv->btcoexist.reg_bt_sco == 3) {
1563
1564                if ((ratio_tx < 30)  && (ratio_pri < 30))
1565                        cur_service_type = BT_IDLE;
1566                else if ((ratio_pri > 110) && (ratio_pri < 250))
1567                        cur_service_type = BT_SCO;
1568                else if ((ratio_tx >= 200) && (ratio_pri >= 200))
1569                        cur_service_type = BT_BUSY;
1570                else if ((ratio_tx >= 350) && (ratio_tx < 500))
1571                        cur_service_type = BT_OTHERBUSY;
1572                else if (ratio_tx >= 500)
1573                        cur_service_type = BT_PAN;
1574                else
1575                        cur_service_type = BT_OTHER_ACTION;
1576
1577                if (cur_service_type != rtlpriv->btcoexist.bt_service) {
1578                        rtlpriv->btcoexist.bt_service = cur_service_type;
1579                        bt_state = bt_state |
1580                           ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
1581                           0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1582                           ((rtlpriv->btcoexist.bt_service != BT_IDLE) ?
1583                           0 : BIT_OFFSET_LEN_MASK_32(2, 1));
1584
1585                        /* Add interrupt migration when bt is not ini
1586                         * idle state (no traffic). */
1587                        if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1588                                rtl_write_word(rtlpriv, 0x504, 0x0ccc);
1589                                rtl_write_byte(rtlpriv, 0x506, 0x54);
1590                                rtl_write_byte(rtlpriv, 0x507, 0x54);
1591                        } else {
1592                                rtl_write_byte(rtlpriv, 0x506, 0x00);
1593                                rtl_write_byte(rtlpriv, 0x507, 0x00);
1594                        }
1595
1596                        rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1597                        return true;
1598                }
1599        }
1600
1601        return false;
1602
1603}
1604
1605static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
1606{
1607        struct rtl_priv *rtlpriv = rtl_priv(hw);
1608        static bool media_connect;
1609
1610        if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1611                media_connect = false;
1612        } else {
1613                if (!media_connect) {
1614                        media_connect = true;
1615                        return true;
1616                }
1617                media_connect = true;
1618        }
1619
1620        return false;
1621}
1622
1623static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
1624{
1625        struct rtl_priv *rtlpriv = rtl_priv(hw);
1626
1627        if (rtlpriv->btcoexist.bt_service == BT_OTHERBUSY) {
1628                rtlpriv->btcoexist.bt_edca_ul = 0x5ea72b;
1629                rtlpriv->btcoexist.bt_edca_dl = 0x5ea72b;
1630        } else if (rtlpriv->btcoexist.bt_service == BT_BUSY) {
1631                rtlpriv->btcoexist.bt_edca_ul = 0x5eb82f;
1632                rtlpriv->btcoexist.bt_edca_dl = 0x5eb82f;
1633        } else if (rtlpriv->btcoexist.bt_service == BT_SCO) {
1634                if (rtlpriv->btcoexist.ratio_tx > 160) {
1635                        rtlpriv->btcoexist.bt_edca_ul = 0x5ea72f;
1636                        rtlpriv->btcoexist.bt_edca_dl = 0x5ea72f;
1637                } else {
1638                        rtlpriv->btcoexist.bt_edca_ul = 0x5ea32b;
1639                        rtlpriv->btcoexist.bt_edca_dl = 0x5ea42b;
1640                }
1641        } else {
1642                rtlpriv->btcoexist.bt_edca_ul = 0;
1643                rtlpriv->btcoexist.bt_edca_dl = 0;
1644        }
1645
1646        if ((rtlpriv->btcoexist.bt_service != BT_IDLE) &&
1647            (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
1648             (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
1649            (rtlpriv->btcoexist.bt_rssi_state &
1650             BT_RSSI_STATE_BG_EDCA_LOW)) {
1651                rtlpriv->btcoexist.bt_edca_ul = 0x5eb82b;
1652                rtlpriv->btcoexist.bt_edca_dl = 0x5eb82b;
1653        }
1654}
1655
1656static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
1657{
1658        struct rtl_priv *rtlpriv = rtl_priv(hw);
1659
1660
1661        /* Only enable HW BT coexist when BT in "Busy" state. */
1662        if (rtlpriv->mac80211.vendor == PEER_CISCO &&
1663            rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {
1664                rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1665        } else {
1666                if ((rtlpriv->btcoexist.bt_service == BT_BUSY) &&
1667                    (rtlpriv->btcoexist.bt_rssi_state &
1668                     BT_RSSI_STATE_NORMAL_POWER)) {
1669                        rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1670                } else if ((rtlpriv->btcoexist.bt_service ==
1671                            BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
1672                            WIRELESS_MODE_N_24G) &&
1673                            (rtlpriv->btcoexist.bt_rssi_state &
1674                            BT_RSSI_STATE_SPECIAL_LOW)) {
1675                        rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1676                } else if (rtlpriv->btcoexist.bt_service == BT_PAN) {
1677                        rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1678                } else {
1679                        rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1680                }
1681        }
1682
1683        if (rtlpriv->btcoexist.bt_service == BT_PAN)
1684                rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
1685        else
1686                rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
1687
1688        if (rtlpriv->btcoexist.bt_rssi_state &
1689            BT_RSSI_STATE_NORMAL_POWER) {
1690                rtl92c_bt_set_normal(hw);
1691        } else {
1692                rtlpriv->btcoexist.bt_edca_ul = 0;
1693                rtlpriv->btcoexist.bt_edca_dl = 0;
1694        }
1695
1696        if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1697                rtlpriv->cfg->ops->set_rfreg(hw,
1698                                 RF90_PATH_A,
1699                                 0x1e,
1700                                 0xf0, 0xf);
1701        } else {
1702                rtlpriv->cfg->ops->set_rfreg(hw,
1703                     RF90_PATH_A, 0x1e, 0xf0,
1704                     rtlpriv->btcoexist.bt_rfreg_origin_1e);
1705        }
1706
1707        if (!rtlpriv->dm.dynamic_txpower_enable) {
1708                if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
1709                        if (rtlpriv->btcoexist.bt_rssi_state &
1710                                BT_RSSI_STATE_TXPOWER_LOW) {
1711                                rtlpriv->dm.dynamic_txhighpower_lvl =
1712                                                        TXHIGHPWRLEVEL_BT2;
1713                        } else {
1714                                rtlpriv->dm.dynamic_txhighpower_lvl =
1715                                        TXHIGHPWRLEVEL_BT1;
1716                        }
1717                } else {
1718                        rtlpriv->dm.dynamic_txhighpower_lvl =
1719                                TXHIGHPWRLEVEL_NORMAL;
1720                }
1721                rtl92c_phy_set_txpower_level(hw,
1722                        rtlpriv->phy.current_channel);
1723        }
1724}
1725
1726static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
1727{
1728        struct rtl_priv *rtlpriv = rtl_priv(hw);
1729        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1730        u8 tmp1byte = 0;
1731
1732        if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&
1733            rtlpriv->btcoexist.bt_coexistence)
1734                tmp1byte |= BIT(5);
1735        if (rtlpriv->btcoexist.bt_cur_state) {
1736                if (rtlpriv->btcoexist.bt_ant_isolation)
1737                        rtl92c_bt_ant_isolation(hw, tmp1byte);
1738        } else {
1739                rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1740                rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
1741                                rtlpriv->btcoexist.bt_rfreg_origin_1e);
1742
1743                rtlpriv->btcoexist.bt_edca_ul = 0;
1744                rtlpriv->btcoexist.bt_edca_dl = 0;
1745        }
1746}
1747
1748void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
1749{
1750        struct rtl_priv *rtlpriv = rtl_priv(hw);
1751        bool wifi_connect_change;
1752        bool bt_state_change;
1753        bool rssi_state_change;
1754
1755        if ((rtlpriv->btcoexist.bt_coexistence) &&
1756            (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) {
1757                wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
1758                bt_state_change = rtl92c_bt_state_change(hw);
1759                rssi_state_change = rtl92c_bt_rssi_state_change(hw);
1760
1761                if (wifi_connect_change || bt_state_change || rssi_state_change)
1762                        rtl92c_check_bt_change(hw);
1763        }
1764}
1765EXPORT_SYMBOL(rtl92c_dm_bt_coexist);
1766