linux/drivers/staging/rtl8192e/r8192E_dm.c
<<
>>
Prefs
   1/*++
   2Copyright-c Realtek Semiconductor Corp. All rights reserved.
   3
   4Module Name:
   5        r8192U_dm.c
   6
   7Abstract:
   8        HW dynamic mechanism.
   9
  10Major Change History:
  11        When            Who                             What
  12        ----------      --------------- -------------------------------
  13        2008-05-14      amy                     create version 0 porting from windows code.
  14
  15--*/
  16#include "r8192E.h"
  17#include "r8192E_dm.h"
  18#include "r8192E_hw.h"
  19#include "r819xE_phy.h"
  20#include "r819xE_phyreg.h"
  21#include "r8190_rtl8256.h"
  22
  23#define DRV_NAME "rtl819xE"
  24
  25//
  26// Indicate different AP vendor for IOT issue.
  27//
  28static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
  29{ 0x5e4322,     0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322,       0x5e4322};
  30static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
  31{ 0x5e4322,     0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322,       0x5e4322};
  32
  33#define RTK_UL_EDCA 0xa44f
  34#define RTK_DL_EDCA 0x5e4322
  35
  36
  37dig_t   dm_digtable;
  38// For Dynamic Rx Path Selection by Signal Strength
  39DRxPathSel      DM_RxPathSelTable;
  40
  41void dm_gpio_change_rf_callback(struct work_struct *work);
  42
  43// DM --> Rate Adaptive
  44static void dm_check_rate_adaptive(struct r8192_priv *priv);
  45
  46// DM --> Bandwidth switch
  47static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv);
  48static void dm_bandwidth_autoswitch(struct r8192_priv *priv);
  49
  50// DM --> TX power control
  51static void dm_check_txpower_tracking(struct r8192_priv *priv);
  52
  53// DM --> Dynamic Init Gain by RSSI
  54static void dm_dig_init(struct r8192_priv *priv);
  55static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv);
  56static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv);
  57static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv);
  58static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv);
  59static void dm_initial_gain(struct r8192_priv *priv);
  60static void dm_pd_th(struct r8192_priv *priv);
  61static void dm_cs_ratio(struct r8192_priv *priv);
  62
  63static void dm_init_ctstoself(struct r8192_priv *priv);
  64// DM --> EDCA turboe mode control
  65static void dm_check_edca_turbo(struct r8192_priv *priv);
  66static void dm_init_edca_turbo(struct r8192_priv *priv);
  67
  68// DM --> HW RF control
  69static void dm_check_rfctrl_gpio(struct r8192_priv *priv);
  70
  71// DM --> Check current RX RF path state
  72static void dm_check_rx_path_selection(struct r8192_priv *priv);
  73static void dm_init_rxpath_selection(struct r8192_priv *priv);
  74static void dm_rxpath_sel_byrssi(struct r8192_priv *priv);
  75
  76// DM --> Fsync for broadcom ap
  77static void dm_init_fsync(struct r8192_priv *priv);
  78static void dm_deInit_fsync(struct r8192_priv *priv);
  79
  80static void dm_check_txrateandretrycount(struct r8192_priv *priv);
  81static void dm_check_fsync(struct r8192_priv *priv);
  82
  83
  84/*---------------------Define of Tx Power Control For Near/Far Range --------*/   //Add by Jacken 2008/02/18
  85static void dm_init_dynamic_txpower(struct r8192_priv *priv);
  86static void dm_dynamic_txpower(struct r8192_priv *priv);
  87
  88// DM --> For rate adaptive and DIG, we must send RSSI to firmware
  89static void dm_send_rssi_tofw(struct r8192_priv *priv);
  90static void dm_ctstoself(struct r8192_priv *priv);
  91
  92static void dm_fsync_timer_callback(unsigned long data);
  93
  94/*
  95 * Prepare SW resource for HW dynamic mechanism.
  96 * This function is only invoked at driver intialization once.
  97 */
  98void init_hal_dm(struct r8192_priv *priv)
  99{
 100        // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism.
 101        priv->undecorated_smoothed_pwdb = -1;
 102
 103        //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
 104        dm_init_dynamic_txpower(priv);
 105        init_rate_adaptive(priv);
 106        //dm_initialize_txpower_tracking(dev);
 107        dm_dig_init(priv);
 108        dm_init_edca_turbo(priv);
 109        dm_init_bandwidth_autoswitch(priv);
 110        dm_init_fsync(priv);
 111        dm_init_rxpath_selection(priv);
 112        dm_init_ctstoself(priv);
 113        INIT_DELAYED_WORK(&priv->gpio_change_rf_wq,  dm_gpio_change_rf_callback);
 114
 115}
 116
 117void deinit_hal_dm(struct r8192_priv *priv)
 118{
 119        dm_deInit_fsync(priv);
 120}
 121
 122void hal_dm_watchdog(struct r8192_priv *priv)
 123{
 124
 125        /*Add by amy 2008/05/15 ,porting from windows code.*/
 126        dm_check_rate_adaptive(priv);
 127        dm_dynamic_txpower(priv);
 128        dm_check_txrateandretrycount(priv);
 129
 130        dm_check_txpower_tracking(priv);
 131
 132        dm_ctrl_initgain_byrssi(priv);
 133        dm_check_edca_turbo(priv);
 134        dm_bandwidth_autoswitch(priv);
 135
 136        dm_check_rfctrl_gpio(priv);
 137        dm_check_rx_path_selection(priv);
 138        dm_check_fsync(priv);
 139
 140        // Add by amy 2008-05-15 porting from windows code.
 141        dm_send_rssi_tofw(priv);
 142        dm_ctstoself(priv);
 143}
 144
 145
 146/*
 147  * Decide Rate Adaptive Set according to distance (signal strength)
 148  *     01/11/2008      MHC             Modify input arguments and RATR table level.
 149  *     01/16/2008      MHC             RF_Type is assigned in ReadAdapterInfo(). We must call
 150  *                                             the function after making sure RF_Type.
 151  */
 152void init_rate_adaptive(struct r8192_priv *priv)
 153{
 154        prate_adaptive pra = &priv->rate_adaptive;
 155
 156        pra->ratr_state = DM_RATR_STA_MAX;
 157        pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
 158        pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
 159        pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
 160
 161        pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
 162        pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
 163        pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
 164
 165        if(priv->CustomerID == RT_CID_819x_Netcore)
 166                pra->ping_rssi_enable = 1;
 167        else
 168                pra->ping_rssi_enable = 0;
 169        pra->ping_rssi_thresh_for_ra = 15;
 170
 171
 172        if (priv->rf_type == RF_2T4R)
 173        {
 174                // 07/10/08 MH Modify for RA smooth scheme.
 175                /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/
 176                pra->upper_rssi_threshold_ratr          =       0x8f0f0000;
 177                pra->middle_rssi_threshold_ratr         =       0x8f0ff000;
 178                pra->low_rssi_threshold_ratr            =       0x8f0ff001;
 179                pra->low_rssi_threshold_ratr_40M        =       0x8f0ff005;
 180                pra->low_rssi_threshold_ratr_20M        =       0x8f0ff001;
 181                pra->ping_rssi_ratr     =       0x0000000d;//cosa add for test
 182        }
 183        else if (priv->rf_type == RF_1T2R)
 184        {
 185                pra->upper_rssi_threshold_ratr          =       0x000f0000;
 186                pra->middle_rssi_threshold_ratr         =       0x000ff000;
 187                pra->low_rssi_threshold_ratr            =       0x000ff001;
 188                pra->low_rssi_threshold_ratr_40M        =       0x000ff005;
 189                pra->low_rssi_threshold_ratr_20M        =       0x000ff001;
 190                pra->ping_rssi_ratr     =       0x0000000d;//cosa add for test
 191        }
 192
 193}
 194
 195
 196static void dm_check_rate_adaptive(struct r8192_priv *priv)
 197{
 198        PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
 199        prate_adaptive                  pra = (prate_adaptive)&priv->rate_adaptive;
 200        u32                                             currentRATR, targetRATR = 0;
 201        u32                                             LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
 202        bool                                            bshort_gi_enabled = false;
 203        static u8                                       ping_rssi_state=0;
 204
 205
 206        if(!priv->up)
 207        {
 208                RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
 209                return;
 210        }
 211
 212        if(pra->rate_adaptive_disabled)//this variable is set by ioctl.
 213                return;
 214
 215        // TODO: Only 11n mode is implemented currently,
 216        if( !(priv->ieee80211->mode == WIRELESS_MODE_N_24G ||
 217                 priv->ieee80211->mode == WIRELESS_MODE_N_5G))
 218                 return;
 219
 220        if( priv->ieee80211->state == IEEE80211_LINKED )
 221        {
 222        //      RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");
 223
 224                //
 225                // Check whether Short GI is enabled
 226                //
 227                bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
 228                        (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
 229
 230
 231                pra->upper_rssi_threshold_ratr =
 232                                (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
 233
 234                pra->middle_rssi_threshold_ratr =
 235                                (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
 236
 237                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 238                {
 239                        pra->low_rssi_threshold_ratr =
 240                                (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
 241                }
 242                else
 243                {
 244                        pra->low_rssi_threshold_ratr =
 245                        (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
 246                }
 247                //cosa add for test
 248                pra->ping_rssi_ratr =
 249                                (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
 250
 251                /* 2007/10/08 MH We support RA smooth scheme now. When it is the first
 252                   time to link with AP. We will not change upper/lower threshold. If
 253                   STA stay in high or low level, we must change two different threshold
 254                   to prevent jumping frequently. */
 255                if (pra->ratr_state == DM_RATR_STA_HIGH)
 256                {
 257                        HighRSSIThreshForRA     = pra->high2low_rssi_thresh_for_ra;
 258                        LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
 259                                        (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
 260                }
 261                else if (pra->ratr_state == DM_RATR_STA_LOW)
 262                {
 263                        HighRSSIThreshForRA     = pra->high_rssi_thresh_for_ra;
 264                        LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
 265                                        (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M);
 266                }
 267                else
 268                {
 269                        HighRSSIThreshForRA     = pra->high_rssi_thresh_for_ra;
 270                        LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
 271                                        (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
 272                }
 273
 274                if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA)
 275                {
 276                        pra->ratr_state = DM_RATR_STA_HIGH;
 277                        targetRATR = pra->upper_rssi_threshold_ratr;
 278                }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA)
 279                {
 280                        pra->ratr_state = DM_RATR_STA_MIDDLE;
 281                        targetRATR = pra->middle_rssi_threshold_ratr;
 282                }else
 283                {
 284                        pra->ratr_state = DM_RATR_STA_LOW;
 285                        targetRATR = pra->low_rssi_threshold_ratr;
 286                }
 287
 288                        //cosa add for test
 289                if(pra->ping_rssi_enable)
 290                {
 291                        //pHalData->UndecoratedSmoothedPWDB = 19;
 292                        if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5))
 293                        {
 294                                if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
 295                                        ping_rssi_state )
 296                                {
 297                                        pra->ratr_state = DM_RATR_STA_LOW;
 298                                        targetRATR = pra->ping_rssi_ratr;
 299                                        ping_rssi_state = 1;
 300                                }
 301                        }
 302                        else
 303                        {
 304                                ping_rssi_state = 0;
 305                        }
 306                }
 307
 308                // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
 309                if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(priv->ieee80211))
 310                        targetRATR &=  0xf00fffff;
 311
 312                //
 313                // Check whether updating of RATR0 is required
 314                //
 315                currentRATR = read_nic_dword(priv, RATR0);
 316                if( targetRATR !=  currentRATR )
 317                {
 318                        u32 ratr_value;
 319                        ratr_value = targetRATR;
 320                        RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);
 321                        if(priv->rf_type == RF_1T2R)
 322                        {
 323                                ratr_value &= ~(RATE_ALL_OFDM_2SS);
 324                        }
 325                        write_nic_dword(priv, RATR0, ratr_value);
 326                        write_nic_byte(priv, UFWP, 1);
 327
 328                        pra->last_ratr = targetRATR;
 329                }
 330
 331        }
 332        else
 333        {
 334                pra->ratr_state = DM_RATR_STA_MAX;
 335        }
 336
 337}
 338
 339
 340static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv)
 341{
 342        priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
 343        priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
 344        priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
 345        priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false;
 346
 347}
 348
 349
 350static void dm_bandwidth_autoswitch(struct r8192_priv *priv)
 351{
 352        if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){
 353                return;
 354        }else{
 355                if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40
 356                        if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
 357                                priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
 358                }else{//in force send packets in 20 Mhz in 20/40
 359                        if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
 360                                priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
 361
 362                }
 363        }
 364}
 365
 366//OFDM default at 0db, index=6.
 367static const u32 OFDMSwingTable[OFDM_Table_Length] = {
 368        0x7f8001fe,     // 0, +6db
 369        0x71c001c7,     // 1, +5db
 370        0x65400195,     // 2, +4db
 371        0x5a400169,     // 3, +3db
 372        0x50800142,     // 4, +2db
 373        0x47c0011f,     // 5, +1db
 374        0x40000100,     // 6, +0db ===> default, upper for higher temperature, lower for low temperature
 375        0x390000e4,     // 7, -1db
 376        0x32c000cb,     // 8, -2db
 377        0x2d4000b5,     // 9, -3db
 378        0x288000a2,     // 10, -4db
 379        0x24000090,     // 11, -5db
 380        0x20000080,     // 12, -6db
 381        0x1c800072,     // 13, -7db
 382        0x19800066,     // 14, -8db
 383        0x26c0005b,     // 15, -9db
 384        0x24400051,     // 16, -10db
 385        0x12000048,     // 17, -11db
 386        0x10000040      // 18, -12db
 387};
 388static const u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
 389        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},       // 0, +0db ===> CCK40M default
 390        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},       // 1, -1db
 391        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},       // 2, -2db
 392        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},       // 3, -3db
 393        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},       // 4, -4db
 394        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},       // 5, -5db
 395        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},       // 6, -6db ===> CCK20M default
 396        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},       // 7, -7db
 397        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},       // 8, -8db
 398        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},       // 9, -9db
 399        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},       // 10, -10db
 400        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}        // 11, -11db
 401};
 402
 403static const u8 CCKSwingTable_Ch14[CCK_Table_length][8] = {
 404        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},       // 0, +0db  ===> CCK40M default
 405        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},       // 1, -1db
 406        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},       // 2, -2db
 407        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},       // 3, -3db
 408        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},       // 4, -4db
 409        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},       // 5, -5db
 410        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},       // 6, -6db  ===> CCK20M default
 411        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},       // 7, -7db
 412        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},       // 8, -8db
 413        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},       // 9, -9db
 414        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},       // 10, -10db
 415        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}        // 11, -11db
 416};
 417
 418#define         Pw_Track_Flag                           0x11d
 419#define         Tssi_Mea_Value                          0x13c
 420#define         Tssi_Report_Value1                      0x134
 421#define         Tssi_Report_Value2                      0x13e
 422#define         FW_Busy_Flag                            0x13f
 423static void dm_TXPowerTrackingCallback_TSSI(struct r8192_priv *priv)
 424{
 425        bool                                            bHighpowerstate, viviflag = FALSE;
 426        DCMD_TXCMD_T                    tx_cmd;
 427        u8                                      powerlevelOFDM24G;
 428        int                                     i =0, j = 0, k = 0;
 429        u8                                              RF_Type, tmp_report[5]={0, 0, 0, 0, 0};
 430        u32                                             Value;
 431        u8                                              Pwr_Flag;
 432        u16                                     Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0;
 433//      bool rtStatus = true;
 434        u32                                             delta=0;
 435        RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
 436//      write_nic_byte(priv, 0x1ba, 0);
 437        write_nic_byte(priv, Pw_Track_Flag, 0);
 438        write_nic_byte(priv, FW_Busy_Flag, 0);
 439        priv->ieee80211->bdynamic_txpower_enable = false;
 440        bHighpowerstate = priv->bDynamicTxHighPower;
 441
 442        powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24);
 443        RF_Type = priv->rf_type;
 444        Value = (RF_Type<<8) | powerlevelOFDM24G;
 445
 446        RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G);
 447
 448        for(j = 0; j<=30; j++)
 449{       //fill tx_cmd
 450
 451        tx_cmd.Op               = TXCMD_SET_TX_PWR_TRACKING;
 452        tx_cmd.Length   = 4;
 453        tx_cmd.Value            = Value;
 454        cmpk_message_handle_tx(priv, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
 455        mdelay(1);
 456
 457        for(i = 0;i <= 30; i++)
 458        {
 459                Pwr_Flag = read_nic_byte(priv, Pw_Track_Flag);
 460
 461                if (Pwr_Flag == 0)
 462                {
 463                        mdelay(1);
 464                        continue;
 465                }
 466
 467                Avg_TSSI_Meas = read_nic_word(priv, Tssi_Mea_Value);
 468
 469                if(Avg_TSSI_Meas == 0)
 470                {
 471                        write_nic_byte(priv, Pw_Track_Flag, 0);
 472                        write_nic_byte(priv, FW_Busy_Flag, 0);
 473                        return;
 474                }
 475
 476                for(k = 0;k < 5; k++)
 477                {
 478                        if(k !=4)
 479                                tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value1+k);
 480                        else
 481                                tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value2);
 482
 483                        RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
 484                }
 485
 486                //check if the report value is right
 487                for(k = 0;k < 5; k++)
 488                {
 489                        if(tmp_report[k] <= 20)
 490                        {
 491                                viviflag =TRUE;
 492                                break;
 493                        }
 494                }
 495                if(viviflag ==TRUE)
 496                {
 497                        write_nic_byte(priv, Pw_Track_Flag, 0);
 498                        viviflag = FALSE;
 499                        RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
 500                        for(k = 0;k < 5; k++)
 501                                tmp_report[k] = 0;
 502                        break;
 503                }
 504
 505                for(k = 0;k < 5; k++)
 506                {
 507                        Avg_TSSI_Meas_from_driver += tmp_report[k];
 508                }
 509
 510                Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
 511                RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver);
 512                TSSI_13dBm = priv->TSSI_13dBm;
 513                RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
 514
 515                //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)
 516                // For MacOS-compatible
 517                if(Avg_TSSI_Meas_from_driver > TSSI_13dBm)
 518                        delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
 519                else
 520                        delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
 521
 522                if(delta <= E_FOR_TX_POWER_TRACK)
 523                {
 524                        priv->ieee80211->bdynamic_txpower_enable = TRUE;
 525                        write_nic_byte(priv, Pw_Track_Flag, 0);
 526                        write_nic_byte(priv, FW_Busy_Flag, 0);
 527                        RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
 528                        RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 529                        RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
 530                        RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
 531                        RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
 532                        return;
 533                }
 534                else
 535                {
 536                        if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
 537                        {
 538                                if (RF_Type == RF_2T4R)
 539                                {
 540
 541                                                if((priv->rfa_txpowertrackingindex > 0) &&(priv->rfc_txpowertrackingindex > 0))
 542                                {
 543                                        priv->rfa_txpowertrackingindex--;
 544                                        if(priv->rfa_txpowertrackingindex_real > 4)
 545                                        {
 546                                                priv->rfa_txpowertrackingindex_real--;
 547                                                rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 548                                        }
 549
 550                                        priv->rfc_txpowertrackingindex--;
 551                                        if(priv->rfc_txpowertrackingindex_real > 4)
 552                                        {
 553                                                priv->rfc_txpowertrackingindex_real--;
 554                                                rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 555                                        }
 556                                                }
 557                                                else
 558                                                {
 559                                                                rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
 560                                                                rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
 561                                }
 562                        }
 563                        else
 564                        {
 565                                                if(priv->rfc_txpowertrackingindex > 0)
 566                                                {
 567                                                        priv->rfc_txpowertrackingindex--;
 568                                                        if(priv->rfc_txpowertrackingindex_real > 4)
 569                                                        {
 570                                                                priv->rfc_txpowertrackingindex_real--;
 571                                                                rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 572                                                        }
 573                                                }
 574                                                else
 575                                                        rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
 576                                }
 577                        }
 578                        else
 579                        {
 580                                if (RF_Type == RF_2T4R)
 581                                {
 582                                        if((priv->rfa_txpowertrackingindex < TxBBGainTableLength - 1) &&(priv->rfc_txpowertrackingindex < TxBBGainTableLength - 1))
 583                                {
 584                                        priv->rfa_txpowertrackingindex++;
 585                                        priv->rfa_txpowertrackingindex_real++;
 586                                        rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 587                                        priv->rfc_txpowertrackingindex++;
 588                                        priv->rfc_txpowertrackingindex_real++;
 589                                        rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 590                                }
 591                                        else
 592                                        {
 593                                                rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
 594                                                rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
 595                        }
 596                                }
 597                                else
 598                                {
 599                                        if(priv->rfc_txpowertrackingindex < (TxBBGainTableLength - 1))
 600                                        {
 601                                                        priv->rfc_txpowertrackingindex++;
 602                                                        priv->rfc_txpowertrackingindex_real++;
 603                                                        rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 604                                        }
 605                                        else
 606                                                        rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
 607                                }
 608                        }
 609                        if (RF_Type == RF_2T4R)
 610                        priv->CCKPresentAttentuation_difference
 611                                = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
 612                        else
 613                                priv->CCKPresentAttentuation_difference
 614                                        = priv->rfc_txpowertrackingindex - priv->rfc_txpowertracking_default;
 615
 616                        if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
 617                                priv->CCKPresentAttentuation
 618                                = priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference;
 619                        else
 620                                priv->CCKPresentAttentuation
 621                                = priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference;
 622
 623                        if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
 624                                        priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
 625                        if(priv->CCKPresentAttentuation < 0)
 626                                        priv->CCKPresentAttentuation = 0;
 627
 628                        if(1)
 629                        {
 630                                if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
 631                                {
 632                                        priv->bcck_in_ch14 = TRUE;
 633                                        dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 634                                }
 635                                else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
 636                                {
 637                                        priv->bcck_in_ch14 = FALSE;
 638                                        dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 639                                }
 640                                else
 641                                        dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 642                        }
 643                RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 644                RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
 645                RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
 646                RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
 647
 648                if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24)
 649                {
 650                        priv->ieee80211->bdynamic_txpower_enable = TRUE;
 651                        write_nic_byte(priv, Pw_Track_Flag, 0);
 652                        write_nic_byte(priv, FW_Busy_Flag, 0);
 653                        RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
 654                        return;
 655                }
 656
 657
 658        }
 659                write_nic_byte(priv, Pw_Track_Flag, 0);
 660                Avg_TSSI_Meas_from_driver = 0;
 661                for(k = 0;k < 5; k++)
 662                        tmp_report[k] = 0;
 663                break;
 664        }
 665        write_nic_byte(priv, FW_Busy_Flag, 0);
 666}
 667                priv->ieee80211->bdynamic_txpower_enable = TRUE;
 668                write_nic_byte(priv, Pw_Track_Flag, 0);
 669}
 670
 671static void dm_TXPowerTrackingCallback_ThermalMeter(struct r8192_priv *priv)
 672{
 673#define ThermalMeterVal 9
 674        u32 tmpRegA, TempCCk;
 675        u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
 676        int i =0, CCKSwingNeedUpdate=0;
 677
 678        if(!priv->btxpower_trackingInit)
 679        {
 680                //Query OFDM default setting
 681                tmpRegA = rtl8192_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord);
 682                for(i=0; i<OFDM_Table_Length; i++)      //find the index
 683                {
 684                        if(tmpRegA == OFDMSwingTable[i])
 685                        {
 686                                priv->OFDM_index= (u8)i;
 687                                RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n",
 688                                        rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index);
 689                        }
 690                }
 691
 692                //Query CCK default setting From 0xa22
 693                TempCCk = rtl8192_QueryBBReg(priv, rCCK0_TxFilter1, bMaskByte2);
 694                for(i=0 ; i<CCK_Table_length ; i++)
 695                {
 696                        if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0])
 697                        {
 698                                priv->CCK_index =(u8) i;
 699                                RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n",
 700                                        rCCK0_TxFilter1, TempCCk, priv->CCK_index);
 701                                break;
 702                        }
 703                }
 704                priv->btxpower_trackingInit = TRUE;
 705                //pHalData->TXPowercount = 0;
 706                return;
 707        }
 708
 709        // read and filter out unreasonable value
 710        tmpRegA = rtl8192_phy_QueryRFReg(priv, RF90_PATH_A, 0x12, 0x078);       // 0x12: RF Reg[10:7]
 711        RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
 712        if(tmpRegA < 3 || tmpRegA > 13)
 713                return;
 714        if(tmpRegA >= 12)       // if over 12, TP will be bad when high temperature
 715                tmpRegA = 12;
 716        RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA);
 717        priv->ThermalMeter[0] = ThermalMeterVal;        //We use fixed value by Bryant's suggestion
 718        priv->ThermalMeter[1] = ThermalMeterVal;        //We use fixed value by Bryant's suggestion
 719
 720        //Get current RF-A temperature index
 721        if(priv->ThermalMeter[0] >= (u8)tmpRegA)        //lower temperature
 722        {
 723                tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
 724                tmpCCK40Mindex = tmpCCK20Mindex - 6;
 725                if(tmpOFDMindex >= OFDM_Table_Length)
 726                        tmpOFDMindex = OFDM_Table_Length-1;
 727                if(tmpCCK20Mindex >= CCK_Table_length)
 728                        tmpCCK20Mindex = CCK_Table_length-1;
 729                if(tmpCCK40Mindex >= CCK_Table_length)
 730                        tmpCCK40Mindex = CCK_Table_length-1;
 731        }
 732        else
 733        {
 734                tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
 735                if(tmpval >= 6)                                                         // higher temperature
 736                        tmpOFDMindex = tmpCCK20Mindex = 0;              // max to +6dB
 737                else
 738                        tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
 739                tmpCCK40Mindex = 0;
 740        }
 741
 742        if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)       //40M
 743                tmpCCKindex = tmpCCK40Mindex;
 744        else
 745                tmpCCKindex = tmpCCK20Mindex;
 746
 747        //record for bandwidth swith
 748        priv->Record_CCK_20Mindex = tmpCCK20Mindex;
 749        priv->Record_CCK_40Mindex = tmpCCK40Mindex;
 750        RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n",
 751                priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
 752
 753        if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
 754        {
 755                priv->bcck_in_ch14 = TRUE;
 756                CCKSwingNeedUpdate = 1;
 757        }
 758        else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
 759        {
 760                priv->bcck_in_ch14 = FALSE;
 761                CCKSwingNeedUpdate = 1;
 762        }
 763
 764        if(priv->CCK_index != tmpCCKindex)
 765{
 766                priv->CCK_index = tmpCCKindex;
 767                CCKSwingNeedUpdate = 1;
 768        }
 769
 770        if(CCKSwingNeedUpdate)
 771        {
 772                dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 773        }
 774        if(priv->OFDM_index != tmpOFDMindex)
 775        {
 776                priv->OFDM_index = tmpOFDMindex;
 777                rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
 778                RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
 779                        priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
 780        }
 781        priv->txpower_count = 0;
 782}
 783
 784void dm_txpower_trackingcallback(struct work_struct *work)
 785{
 786        struct delayed_work *dwork = container_of(work,struct delayed_work,work);
 787        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
 788
 789        if(priv->IC_Cut >= IC_VersionCut_D)
 790                dm_TXPowerTrackingCallback_TSSI(priv);
 791        else
 792                dm_TXPowerTrackingCallback_ThermalMeter(priv);
 793}
 794
 795
 796static const txbbgain_struct rtl8192_txbbgain_table[] = {
 797        { 12,   0x7f8001fe },
 798        { 11,   0x788001e2 },
 799        { 10,   0x71c001c7 },
 800        { 9,    0x6b8001ae },
 801        { 8,    0x65400195 },
 802        { 7,    0x5fc0017f },
 803        { 6,    0x5a400169 },
 804        { 5,    0x55400155 },
 805        { 4,    0x50800142 },
 806        { 3,    0x4c000130 },
 807        { 2,    0x47c0011f },
 808        { 1,    0x43c0010f },
 809        { 0,    0x40000100 },
 810        { -1,   0x3c8000f2 },
 811        { -2,   0x390000e4 },
 812        { -3,   0x35c000d7 },
 813        { -4,   0x32c000cb },
 814        { -5,   0x300000c0 },
 815        { -6,   0x2d4000b5 },
 816        { -7,   0x2ac000ab },
 817        { -8,   0x288000a2 },
 818        { -9,   0x26000098 },
 819        { -10,  0x24000090 },
 820        { -11,  0x22000088 },
 821        { -12,  0x20000080 },
 822        { -13,  0x1a00006c },
 823        { -14,  0x1c800072 },
 824        { -15,  0x18000060 },
 825        { -16,  0x19800066 },
 826        { -17,  0x15800056 },
 827        { -18,  0x26c0005b },
 828        { -19,  0x14400051 },
 829        { -20,  0x24400051 },
 830        { -21,  0x1300004c },
 831        { -22,  0x12000048 },
 832        { -23,  0x11000044 },
 833        { -24,  0x10000040 },
 834};
 835
 836/*
 837 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
 838 * This Table is for CH1~CH13
 839 */
 840static const ccktxbbgain_struct rtl8192_cck_txbbgain_table[] = {
 841        {{ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 }},
 842        {{ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 }},
 843        {{ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03 }},
 844        {{ 0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03 }},
 845        {{ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 }},
 846        {{ 0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03 }},
 847        {{ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }},
 848        {{ 0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03 }},
 849        {{ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02 }},
 850        {{ 0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02 }},
 851        {{ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02 }},
 852        {{ 0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02 }},
 853        {{ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02 }},
 854        {{ 0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02 }},
 855        {{ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02 }},
 856        {{ 0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02 }},
 857        {{ 0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01 }},
 858        {{ 0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02 }},
 859        {{ 0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01 }},
 860        {{ 0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
 861        {{ 0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
 862        {{ 0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
 863        {{ 0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
 864};
 865
 866/*
 867 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
 868 * This Table is for CH14
 869 */
 870static const ccktxbbgain_struct rtl8192_cck_txbbgain_ch14_table[] = {
 871        {{ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 }},
 872        {{ 0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00 }},
 873        {{ 0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00 }},
 874        {{ 0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00 }},
 875        {{ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 }},
 876        {{ 0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00 }},
 877        {{ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00 }},
 878        {{ 0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00 }},
 879        {{ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00 }},
 880        {{ 0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00 }},
 881        {{ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
 882        {{ 0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
 883        {{ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
 884        {{ 0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00 }},
 885        {{ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
 886        {{ 0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
 887        {{ 0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
 888        {{ 0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
 889        {{ 0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
 890        {{ 0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
 891        {{ 0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
 892        {{ 0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00 }},
 893        {{ 0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00 }},
 894};
 895
 896static void dm_InitializeTXPowerTracking_TSSI(struct r8192_priv *priv)
 897{
 898        priv->txbbgain_table = rtl8192_txbbgain_table;
 899        priv->cck_txbbgain_table = rtl8192_cck_txbbgain_table;
 900        priv->cck_txbbgain_ch14_table = rtl8192_cck_txbbgain_ch14_table;
 901
 902        priv->btxpower_tracking = TRUE;
 903        priv->txpower_count       = 0;
 904        priv->btxpower_trackingInit = FALSE;
 905
 906}
 907
 908static void dm_InitializeTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
 909{
 910        // Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism
 911        // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
 912        // 3-wire by driver cause RF goes into wrong state.
 913        if(priv->ieee80211->FwRWRF)
 914                priv->btxpower_tracking = TRUE;
 915        else
 916                priv->btxpower_tracking = FALSE;
 917        priv->txpower_count       = 0;
 918        priv->btxpower_trackingInit = FALSE;
 919}
 920
 921void dm_initialize_txpower_tracking(struct r8192_priv *priv)
 922{
 923        if(priv->IC_Cut >= IC_VersionCut_D)
 924                dm_InitializeTXPowerTracking_TSSI(priv);
 925        else
 926                dm_InitializeTXPowerTracking_ThermalMeter(priv);
 927}
 928
 929
 930static void dm_CheckTXPowerTracking_TSSI(struct r8192_priv *priv)
 931{
 932        static u32 tx_power_track_counter = 0;
 933        RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
 934        if(read_nic_byte(priv, 0x11e) ==1)
 935                return;
 936        if(!priv->btxpower_tracking)
 937                return;
 938        tx_power_track_counter++;
 939
 940        if (tx_power_track_counter > 90) {
 941                queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
 942                tx_power_track_counter =0;
 943        }
 944}
 945
 946static void dm_CheckTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
 947{
 948        static u8       TM_Trigger=0;
 949
 950        if(!priv->btxpower_tracking)
 951                return;
 952        else
 953        {
 954                if(priv->txpower_count  <= 2)
 955                {
 956                        priv->txpower_count++;
 957                        return;
 958                }
 959        }
 960
 961        if(!TM_Trigger)
 962        {
 963                //Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash
 964                //actually write reg0x02 bit1=0, then bit1=1.
 965                rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
 966                rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
 967                rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
 968                rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
 969                TM_Trigger = 1;
 970                return;
 971        }
 972        else {
 973                queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
 974                TM_Trigger = 0;
 975        }
 976}
 977
 978static void dm_check_txpower_tracking(struct r8192_priv *priv)
 979{
 980        if(priv->IC_Cut >= IC_VersionCut_D)
 981                dm_CheckTXPowerTracking_TSSI(priv);
 982        else
 983                dm_CheckTXPowerTracking_ThermalMeter(priv);
 984}
 985
 986
 987static void dm_CCKTxPowerAdjust_TSSI(struct r8192_priv *priv, bool bInCH14)
 988{
 989        u32 TempVal;
 990        //Write 0xa22 0xa23
 991        TempVal = 0;
 992        if(!bInCH14){
 993                //Write 0xa22 0xa23
 994                TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
 995                                        (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
 996
 997                rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
 998                //Write 0xa24 ~ 0xa27
 999                TempVal = 0;
1000                TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1001                                        (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1002                                        (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1003                                        (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1004                rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1005                //Write 0xa28  0xa29
1006                TempVal = 0;
1007                TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1008                                        (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1009
1010                rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1011        }
1012        else
1013        {
1014                TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
1015                                        (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
1016
1017                rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1018                //Write 0xa24 ~ 0xa27
1019                TempVal = 0;
1020                TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1021                                        (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1022                                        (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1023                                        (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1024                rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1025                //Write 0xa28  0xa29
1026                TempVal = 0;
1027                TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1028                                        (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1029
1030                rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1031        }
1032
1033
1034}
1035
1036static void dm_CCKTxPowerAdjust_ThermalMeter(struct r8192_priv *priv,
1037                                             bool bInCH14)
1038{
1039        u32 TempVal;
1040
1041        TempVal = 0;
1042        if(!bInCH14)
1043        {
1044                //Write 0xa22 0xa23
1045                TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
1046                                        (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
1047                rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1048                RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1049                        rCCK0_TxFilter1, TempVal);
1050                //Write 0xa24 ~ 0xa27
1051                TempVal = 0;
1052                TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
1053                                        (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
1054                                        (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+
1055                                        (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
1056                rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1057                RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1058                        rCCK0_TxFilter2, TempVal);
1059                //Write 0xa28  0xa29
1060                TempVal = 0;
1061                TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
1062                                        (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ;
1063
1064                rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1065                RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1066                        rCCK0_DebugPort, TempVal);
1067        }
1068        else
1069        {
1070//              priv->CCKTxPowerAdjustCntNotCh14++;     //cosa add for debug.
1071                //Write 0xa22 0xa23
1072                TempVal =       CCKSwingTable_Ch14[priv->CCK_index][0] +
1073                                        (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
1074
1075                rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1076                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1077                        rCCK0_TxFilter1, TempVal);
1078                //Write 0xa24 ~ 0xa27
1079                TempVal = 0;
1080                TempVal =       CCKSwingTable_Ch14[priv->CCK_index][2] +
1081                                        (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
1082                                        (CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+
1083                                        (CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
1084                rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1085                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1086                        rCCK0_TxFilter2, TempVal);
1087                //Write 0xa28  0xa29
1088                TempVal = 0;
1089                TempVal =       CCKSwingTable_Ch14[priv->CCK_index][6] +
1090                                        (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ;
1091
1092                rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1093                RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n",
1094                        rCCK0_DebugPort, TempVal);
1095        }
1096}
1097
1098void dm_cck_txpower_adjust(struct r8192_priv *priv, bool binch14)
1099{
1100        if(priv->IC_Cut >= IC_VersionCut_D)
1101                dm_CCKTxPowerAdjust_TSSI(priv, binch14);
1102        else
1103                dm_CCKTxPowerAdjust_ThermalMeter(priv, binch14);
1104}
1105
1106/* Set DIG scheme init value. */
1107static void dm_dig_init(struct r8192_priv *priv)
1108{
1109        /* 2007/10/05 MH Disable DIG scheme now. Not tested. */
1110        dm_digtable.dig_enable_flag     = true;
1111        dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
1112        dm_digtable.dbg_mode = DM_DBG_OFF;      //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig
1113        dm_digtable.dig_algorithm_switch = 0;
1114
1115        /* 2007/10/04 MH Define init gain threshold. */
1116        dm_digtable.dig_state           = DM_STA_DIG_MAX;
1117        dm_digtable.dig_highpwr_state   = DM_STA_DIG_MAX;
1118        dm_digtable.initialgain_lowerbound_state = false;
1119
1120        dm_digtable.rssi_low_thresh     = DM_DIG_THRESH_LOW;
1121        dm_digtable.rssi_high_thresh    = DM_DIG_THRESH_HIGH;
1122
1123        dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
1124        dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
1125
1126        dm_digtable.rssi_val = 50;      //for new dig debug rssi value
1127        dm_digtable.backoff_val = DM_DIG_BACKOFF;
1128        dm_digtable.rx_gain_range_max = DM_DIG_MAX;
1129        if(priv->CustomerID == RT_CID_819x_Netcore)
1130                dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;
1131        else
1132                dm_digtable.rx_gain_range_min = DM_DIG_MIN;
1133
1134}
1135
1136
1137/*
1138 * Driver must monitor RSSI and notify firmware to change initial
1139 * gain according to different threshold. BB team provide the
1140 * suggested solution.
1141 */
1142static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv)
1143{
1144        if (dm_digtable.dig_enable_flag == false)
1145                return;
1146
1147        if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
1148                dm_ctrl_initgain_byrssi_by_fwfalse_alarm(priv);
1149        else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1150                dm_ctrl_initgain_byrssi_by_driverrssi(priv);
1151}
1152
1153
1154static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv)
1155{
1156        u8 i;
1157        static u8       fw_dig=0;
1158
1159        if (dm_digtable.dig_enable_flag == false)
1160                return;
1161
1162        if(dm_digtable.dig_algorithm_switch)    // if swithed algorithm, we have to disable FW Dig.
1163                fw_dig = 0;
1164        if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled
1165        {// FW DIG Off
1166                for(i=0; i<3; i++)
1167                        rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);  // Only clear byte 1 and rewrite.
1168                fw_dig++;
1169                dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off.
1170        }
1171
1172        if(priv->ieee80211->state == IEEE80211_LINKED)
1173                dm_digtable.cur_connect_state = DIG_CONNECT;
1174        else
1175                dm_digtable.cur_connect_state = DIG_DISCONNECT;
1176
1177        if(dm_digtable.dbg_mode == DM_DBG_OFF)
1178                dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
1179
1180        dm_initial_gain(priv);
1181        dm_pd_th(priv);
1182        dm_cs_ratio(priv);
1183        if(dm_digtable.dig_algorithm_switch)
1184                dm_digtable.dig_algorithm_switch = 0;
1185        dm_digtable.pre_connect_state = dm_digtable.cur_connect_state;
1186
1187}
1188
1189static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv)
1190{
1191        static u32 reset_cnt = 0;
1192        u8 i;
1193
1194        if (dm_digtable.dig_enable_flag == false)
1195                return;
1196
1197        if(dm_digtable.dig_algorithm_switch)
1198        {
1199                dm_digtable.dig_state = DM_STA_DIG_MAX;
1200                // Fw DIG On.
1201                for(i=0; i<3; i++)
1202                        rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1);  // Only clear byte 1 and rewrite.
1203                dm_digtable.dig_algorithm_switch = 0;
1204        }
1205
1206        if (priv->ieee80211->state != IEEE80211_LINKED)
1207                return;
1208
1209        // For smooth, we can not change DIG state.
1210        if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
1211                (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
1212        {
1213                return;
1214        }
1215
1216        /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
1217                  and then execute below step. */
1218        if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
1219        {
1220                /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters
1221                   will be reset to init value. We must prevent the condition. */
1222                if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
1223                        (priv->reset_count == reset_cnt))
1224                {
1225                        return;
1226                }
1227                else
1228                {
1229                        reset_cnt = priv->reset_count;
1230                }
1231
1232                // If DIG is off, DIG high power state must reset.
1233                dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
1234                dm_digtable.dig_state = DM_STA_DIG_OFF;
1235
1236                // 1.1 DIG Off.
1237                rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);  // Only clear byte 1 and rewrite.
1238
1239                // 1.2 Set initial gain.
1240                write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x17);
1241                write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x17);
1242                write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x17);
1243                write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x17);
1244
1245                // 1.3 Lower PD_TH for OFDM.
1246                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1247                {
1248                        /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1249                        // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1250                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1251                }
1252                else
1253                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1254
1255                // 1.4 Lower CS ratio for CCK.
1256                write_nic_byte(priv, 0xa0a, 0x08);
1257
1258                // 1.5 Higher EDCCA.
1259                //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);
1260                return;
1261
1262        }
1263
1264        /* 2. When RSSI increase, We have to judge if it is larger than a threshold
1265                  and then execute below step.  */
1266        if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) )
1267        {
1268                u8 reset_flag = 0;
1269
1270                if (dm_digtable.dig_state == DM_STA_DIG_ON &&
1271                        (priv->reset_count == reset_cnt))
1272                {
1273                        dm_ctrl_initgain_byrssi_highpwr(priv);
1274                        return;
1275                }
1276                else
1277                {
1278                        if (priv->reset_count != reset_cnt)
1279                                reset_flag = 1;
1280
1281                        reset_cnt = priv->reset_count;
1282                }
1283
1284                dm_digtable.dig_state = DM_STA_DIG_ON;
1285
1286                // 2.1 Set initial gain.
1287                // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment.
1288                if (reset_flag == 1)
1289                {
1290                        write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x2c);
1291                        write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x2c);
1292                        write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x2c);
1293                        write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x2c);
1294                }
1295                else
1296                {
1297                        write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x20);
1298                        write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x20);
1299                        write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x20);
1300                        write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x20);
1301                }
1302
1303                // 2.2 Higher PD_TH for OFDM.
1304                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1305                {
1306                        /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1307                        // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1308                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1309                }
1310                else
1311                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1312
1313                // 2.3 Higher CS ratio for CCK.
1314                write_nic_byte(priv, 0xa0a, 0xcd);
1315
1316                // 2.4 Lower EDCCA.
1317                /* 2008/01/11 MH 90/92 series are the same. */
1318                //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);
1319
1320                // 2.5 DIG On.
1321                rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1);  // Only clear byte 1 and rewrite.
1322
1323        }
1324
1325        dm_ctrl_initgain_byrssi_highpwr(priv);
1326
1327}
1328
1329static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv)
1330{
1331        static u32 reset_cnt_highpwr = 0;
1332
1333        // For smooth, we can not change high power DIG state in the range.
1334        if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
1335                (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
1336        {
1337                return;
1338        }
1339
1340        /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if
1341                  it is larger than a threshold and then execute below step.  */
1342        // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue.
1343        if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh)
1344        {
1345                if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
1346                        (priv->reset_count == reset_cnt_highpwr))
1347                        return;
1348                else
1349                        dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
1350
1351                // 3.1 Higher PD_TH for OFDM for high power state.
1352                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1353                {
1354                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1355                }
1356                else
1357                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1358        }
1359        else
1360        {
1361                if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&&
1362                        (priv->reset_count == reset_cnt_highpwr))
1363                        return;
1364                else
1365                        dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
1366
1367                if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
1368                         priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)
1369                {
1370                        // 3.2 Recover PD_TH for OFDM for normal power region.
1371                        if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1372                        {
1373                                write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1374                        }
1375                        else
1376                                write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1377                }
1378        }
1379
1380        reset_cnt_highpwr = priv->reset_count;
1381
1382}
1383
1384
1385static void dm_initial_gain(struct r8192_priv *priv)
1386{
1387        u8                                      initial_gain=0;
1388        static u8                               initialized=0, force_write=0;
1389        static u32                      reset_cnt=0;
1390
1391        if(dm_digtable.dig_algorithm_switch)
1392        {
1393                initialized = 0;
1394                reset_cnt = 0;
1395        }
1396
1397        if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1398        {
1399                if(dm_digtable.cur_connect_state == DIG_CONNECT)
1400                {
1401                        if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
1402                                dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
1403                        else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
1404                                dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
1405                        else
1406                                dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
1407                }
1408                else            //current state is disconnected
1409                {
1410                        if(dm_digtable.cur_ig_value == 0)
1411                                dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1412                        else
1413                                dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
1414                }
1415        }
1416        else    // disconnected -> connected or connected -> disconnected
1417        {
1418                dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1419                dm_digtable.pre_ig_value = 0;
1420        }
1421
1422        // if silent reset happened, we should rewrite the values back
1423        if(priv->reset_count != reset_cnt)
1424        {
1425                force_write = 1;
1426                reset_cnt = priv->reset_count;
1427        }
1428
1429        if(dm_digtable.pre_ig_value != read_nic_byte(priv, rOFDM0_XAAGCCore1))
1430                force_write = 1;
1431
1432        {
1433                if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
1434                        || !initialized || force_write)
1435                {
1436                        initial_gain = (u8)dm_digtable.cur_ig_value;
1437                        // Set initial gain.
1438                        write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
1439                        write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
1440                        write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
1441                        write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
1442                        dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
1443                        initialized = 1;
1444                        force_write = 0;
1445                }
1446        }
1447}
1448
1449static void dm_pd_th(struct r8192_priv *priv)
1450{
1451        static u8                               initialized=0, force_write=0;
1452        static u32                      reset_cnt = 0;
1453
1454        if(dm_digtable.dig_algorithm_switch)
1455        {
1456                initialized = 0;
1457                reset_cnt = 0;
1458        }
1459
1460        if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1461        {
1462                if(dm_digtable.cur_connect_state == DIG_CONNECT)
1463                {
1464                        if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
1465                                dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
1466                        else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1467                                dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1468                        else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
1469                                        (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
1470                                dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
1471                        else
1472                                dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
1473                }
1474                else
1475                {
1476                        dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1477                }
1478        }
1479        else    // disconnected -> connected or connected -> disconnected
1480        {
1481                dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1482        }
1483
1484        // if silent reset happened, we should rewrite the values back
1485        if(priv->reset_count != reset_cnt)
1486        {
1487                force_write = 1;
1488                reset_cnt = priv->reset_count;
1489        }
1490
1491        {
1492                if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
1493                        (initialized<=3) || force_write)
1494                {
1495                        if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER)
1496                        {
1497                                // Lower PD_TH for OFDM.
1498                                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1499                                {
1500                                        /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1501                                        // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1502                                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1503                                }
1504                                else
1505                                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1506                        }
1507                        else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER)
1508                        {
1509                                // Higher PD_TH for OFDM.
1510                                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1511                                {
1512                                        /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1513                                        // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1514                                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1515                                }
1516                                else
1517                                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1518                        }
1519                        else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER)
1520                        {
1521                                // Higher PD_TH for OFDM for high power state.
1522                                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1523                                {
1524                                        write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1525                                }
1526                                else
1527                                        write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1528                        }
1529                        dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
1530                        if(initialized <= 3)
1531                                initialized++;
1532                        force_write = 0;
1533                }
1534        }
1535}
1536
1537static void dm_cs_ratio(struct r8192_priv *priv)
1538{
1539        static u8                               initialized=0,force_write=0;
1540        static u32                      reset_cnt = 0;
1541
1542        if(dm_digtable.dig_algorithm_switch)
1543        {
1544                initialized = 0;
1545                reset_cnt = 0;
1546        }
1547
1548        if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1549        {
1550                if(dm_digtable.cur_connect_state == DIG_CONNECT)
1551                {
1552                        if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1553                                dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1554                        else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) )
1555                                dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
1556                        else
1557                                dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
1558                }
1559                else
1560                {
1561                        dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1562                }
1563        }
1564        else    // disconnected -> connected or connected -> disconnected
1565        {
1566                dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1567        }
1568
1569        // if silent reset happened, we should rewrite the values back
1570        if(priv->reset_count != reset_cnt)
1571        {
1572                force_write = 1;
1573                reset_cnt = priv->reset_count;
1574        }
1575
1576
1577        if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
1578                !initialized || force_write)
1579        {
1580                if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
1581                {
1582                        // Lower CS ratio for CCK.
1583                        write_nic_byte(priv, 0xa0a, 0x08);
1584                }
1585                else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
1586                {
1587                        // Higher CS ratio for CCK.
1588                        write_nic_byte(priv, 0xa0a, 0xcd);
1589                }
1590                dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
1591                initialized = 1;
1592                force_write = 0;
1593        }
1594}
1595
1596void dm_init_edca_turbo(struct r8192_priv *priv)
1597{
1598
1599        priv->bcurrent_turbo_EDCA = false;
1600        priv->ieee80211->bis_any_nonbepkts = false;
1601        priv->bis_cur_rdlstate = false;
1602}
1603
1604static void dm_check_edca_turbo(struct r8192_priv *priv)
1605{
1606        PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
1607        //PSTA_QOS                      pStaQos = pMgntInfo->pStaQos;
1608
1609        // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.
1610        static unsigned long                    lastTxOkCnt = 0;
1611        static unsigned long                    lastRxOkCnt = 0;
1612        unsigned long                           curTxOkCnt = 0;
1613        unsigned long                           curRxOkCnt = 0;
1614
1615        //
1616        // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters
1617        // should follow the settings from QAP. By Bruce, 2007-12-07.
1618        //
1619        if(priv->ieee80211->state != IEEE80211_LINKED)
1620                goto dm_CheckEdcaTurbo_EXIT;
1621        // We do not turn on EDCA turbo mode for some AP that has IOT issue
1622        if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
1623                goto dm_CheckEdcaTurbo_EXIT;
1624
1625        // Check the status for current condition.
1626        if(!priv->ieee80211->bis_any_nonbepkts)
1627        {
1628                curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1629                curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1630                // For RT-AP, we needs to turn it on when Rx>Tx
1631                if(curRxOkCnt > 4*curTxOkCnt)
1632                {
1633                        if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1634                        {
1635                                write_nic_dword(priv, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
1636                                priv->bis_cur_rdlstate = true;
1637                        }
1638                }
1639                else
1640                {
1641                        if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1642                        {
1643                                write_nic_dword(priv, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
1644                                priv->bis_cur_rdlstate = false;
1645                        }
1646
1647                }
1648
1649                priv->bcurrent_turbo_EDCA = true;
1650        }
1651        else
1652        {
1653                //
1654                // Turn Off EDCA turbo here.
1655                // Restore original EDCA according to the declaration of AP.
1656                //
1657                 if(priv->bcurrent_turbo_EDCA)
1658                {
1659
1660                        {
1661                                u8              u1bAIFS;
1662                                u32             u4bAcParam;
1663                                struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
1664                                u8 mode = priv->ieee80211->mode;
1665
1666                        // For Each time updating EDCA parameter, reset EDCA turbo mode status.
1667                                dm_init_edca_turbo(priv);
1668                                u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
1669                                u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
1670                                        (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)|
1671                                        (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)|
1672                                        ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
1673                                printk("===>u4bAcParam:%x, ", u4bAcParam);
1674                        //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
1675                                write_nic_dword(priv, EDCAPARA_BE,  u4bAcParam);
1676
1677                        // Check ACM bit.
1678                        // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
1679                                {
1680                        // TODO:  Modified this part and try to set acm control in only 1 IO processing!!
1681
1682                                        PACI_AIFSN      pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
1683                                        u8              AcmCtrl = read_nic_byte(priv, AcmHwCtrl );
1684                                        if( pAciAifsn->f.ACM )
1685                                        { // ACM bit is 1.
1686                                                AcmCtrl |= AcmHw_BeqEn;
1687                                        }
1688                                        else
1689                                        { // ACM bit is 0.
1690                                                AcmCtrl &= (~AcmHw_BeqEn);
1691                                        }
1692
1693                                        RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ;
1694                                        write_nic_byte(priv, AcmHwCtrl, AcmCtrl );
1695                                }
1696                        }
1697                        priv->bcurrent_turbo_EDCA = false;
1698                }
1699        }
1700
1701
1702dm_CheckEdcaTurbo_EXIT:
1703        // Set variables for next time.
1704        priv->ieee80211->bis_any_nonbepkts = false;
1705        lastTxOkCnt = priv->stats.txbytesunicast;
1706        lastRxOkCnt = priv->stats.rxbytesunicast;
1707}
1708
1709static void dm_init_ctstoself(struct r8192_priv *priv)
1710{
1711        priv->ieee80211->bCTSToSelfEnable = TRUE;
1712        priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
1713}
1714
1715static void dm_ctstoself(struct r8192_priv *priv)
1716{
1717        PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
1718        static unsigned long                            lastTxOkCnt = 0;
1719        static unsigned long                            lastRxOkCnt = 0;
1720        unsigned long                                           curTxOkCnt = 0;
1721        unsigned long                                           curRxOkCnt = 0;
1722
1723        if(priv->ieee80211->bCTSToSelfEnable != TRUE)
1724        {
1725                pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1726                return;
1727        }
1728        /*
1729        1. Uplink
1730        2. Linksys350/Linksys300N
1731        3. <50 disable, >55 enable
1732        */
1733
1734        if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
1735        {
1736                curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1737                curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1738                if(curRxOkCnt > 4*curTxOkCnt)   //downlink, disable CTS to self
1739                {
1740                        pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1741                }
1742                else    //uplink
1743                {
1744                        pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
1745                }
1746
1747                lastTxOkCnt = priv->stats.txbytesunicast;
1748                lastRxOkCnt = priv->stats.rxbytesunicast;
1749        }
1750}
1751
1752
1753
1754/* Copy 8187B template for 9xseries */
1755static void dm_check_rfctrl_gpio(struct r8192_priv *priv)
1756{
1757
1758        // Walk around for DTM test, we will not enable HW - radio on/off because r/w
1759        // page 1 register before Lextra bus is enabled cause system fails when resuming
1760        // from S4. 20080218, Emily
1761
1762        // Stop to execute workitem to prevent S3/S4 bug.
1763        queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
1764}
1765
1766/* PCI will not support workitem call back HW radio on-off control. */
1767void dm_gpio_change_rf_callback(struct work_struct *work)
1768{
1769        struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1770        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
1771        u8 tmp1byte;
1772        RT_RF_POWER_STATE       eRfPowerStateToSet;
1773        bool bActuallySet = false;
1774
1775        if (!priv->up) {
1776                RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n");
1777        } else {
1778                // 0x108 GPIO input register is read only
1779                //set 0x108 B1= 1: RF-ON; 0: RF-OFF.
1780                tmp1byte = read_nic_byte(priv, GPI);
1781
1782                eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
1783
1784                if (priv->bHwRadioOff && (eRfPowerStateToSet == eRfOn)) {
1785                        RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio ON\n");
1786
1787                        priv->bHwRadioOff = false;
1788                        bActuallySet = true;
1789                } else if ((!priv->bHwRadioOff) && (eRfPowerStateToSet == eRfOff)) {
1790                        RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio OFF\n");
1791                        priv->bHwRadioOff = true;
1792                        bActuallySet = true;
1793                }
1794
1795                if (bActuallySet) {
1796                        priv->bHwRfOffAction = 1;
1797                        MgntActSet_RF_State(priv, eRfPowerStateToSet, RF_CHANGE_BY_HW);
1798                        //DrvIFIndicateCurrentPhyStatus(pAdapter);
1799                } else {
1800                        msleep(2000);
1801                }
1802        }
1803}
1804
1805/* Check if Current RF RX path is enabled */
1806void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
1807{
1808        struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1809        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq);
1810        u8 rfpath = 0, i;
1811
1812
1813        /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will
1814           always be the same. We only read 0xc04 now. */
1815        rfpath = read_nic_byte(priv, 0xc04);
1816
1817        // Check Bit 0-3, it means if RF A-D is enabled.
1818        for (i = 0; i < RF90_PATH_MAX; i++)
1819        {
1820                if (rfpath & (0x01<<i))
1821                        priv->brfpath_rxenable[i] = 1;
1822                else
1823                        priv->brfpath_rxenable[i] = 0;
1824        }
1825        if(!DM_RxPathSelTable.Enable)
1826                return;
1827
1828        dm_rxpath_sel_byrssi(priv);
1829}
1830
1831static void dm_init_rxpath_selection(struct r8192_priv *priv)
1832{
1833        u8 i;
1834
1835        DM_RxPathSelTable.Enable = 1;   //default enabled
1836        DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
1837        DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
1838        if(priv->CustomerID == RT_CID_819x_Netcore)
1839                DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
1840        else
1841                DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
1842        DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
1843        DM_RxPathSelTable.disabledRF = 0;
1844        for(i=0; i<4; i++)
1845        {
1846                DM_RxPathSelTable.rf_rssi[i] = 50;
1847                DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
1848                DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
1849        }
1850}
1851
1852static void dm_rxpath_sel_byrssi(struct r8192_priv *priv)
1853{
1854        u8                              i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0;
1855        u8                              tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0;
1856        u8                              cck_default_Rx=0x2;     //RF-C
1857        u8                              cck_optional_Rx=0x3;//RF-D
1858        long                            tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0;
1859        u8                              cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0;
1860        u8                              cur_rf_rssi;
1861        long                            cur_cck_pwdb;
1862        static u8                       disabled_rf_cnt=0, cck_Rx_Path_initialized=0;
1863        u8                              update_cck_rx_path;
1864
1865        if(priv->rf_type != RF_2T4R)
1866                return;
1867
1868        if(!cck_Rx_Path_initialized)
1869        {
1870                DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(priv, 0xa07)&0xf);
1871                cck_Rx_Path_initialized = 1;
1872        }
1873
1874        DM_RxPathSelTable.disabledRF = 0xf;
1875        DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(priv, 0xc04));
1876
1877        if(priv->ieee80211->mode == WIRELESS_MODE_B)
1878        {
1879                DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;        //pure B mode, fixed cck version2
1880        }
1881
1882        //decide max/sec/min rssi index
1883        for (i=0; i<RF90_PATH_MAX; i++)
1884        {
1885                if(!DM_RxPathSelTable.DbgMode)
1886                        DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
1887
1888                if(priv->brfpath_rxenable[i])
1889                {
1890                        rf_num++;
1891                        cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
1892
1893                        if(rf_num == 1) // find first enabled rf path and the rssi values
1894                        {       //initialize, set all rssi index to the same one
1895                                max_rssi_index = min_rssi_index = sec_rssi_index = i;
1896                                tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
1897                        }
1898                        else if(rf_num == 2)
1899                        {       // we pick up the max index first, and let sec and min to be the same one
1900                                if(cur_rf_rssi >= tmp_max_rssi)
1901                                {
1902                                        tmp_max_rssi = cur_rf_rssi;
1903                                        max_rssi_index = i;
1904                                }
1905                                else
1906                                {
1907                                        tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
1908                                        sec_rssi_index = min_rssi_index = i;
1909                                }
1910                        }
1911                        else
1912                        {
1913                                if(cur_rf_rssi > tmp_max_rssi)
1914                                {
1915                                        tmp_sec_rssi = tmp_max_rssi;
1916                                        sec_rssi_index = max_rssi_index;
1917                                        tmp_max_rssi = cur_rf_rssi;
1918                                        max_rssi_index = i;
1919                                }
1920                                else if(cur_rf_rssi == tmp_max_rssi)
1921                                {       // let sec and min point to the different index
1922                                        tmp_sec_rssi = cur_rf_rssi;
1923                                        sec_rssi_index = i;
1924                                }
1925                                else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi))
1926                                {
1927                                        tmp_sec_rssi = cur_rf_rssi;
1928                                        sec_rssi_index = i;
1929                                }
1930                                else if(cur_rf_rssi == tmp_sec_rssi)
1931                                {
1932                                        if(tmp_sec_rssi == tmp_min_rssi)
1933                                        {       // let sec and min point to the different index
1934                                                tmp_sec_rssi = cur_rf_rssi;
1935                                                sec_rssi_index = i;
1936                                        }
1937                                        else
1938                                        {
1939                                                // This case we don't need to set any index
1940                                        }
1941                                }
1942                                else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi))
1943                                {
1944                                        // This case we don't need to set any index
1945                                }
1946                                else if(cur_rf_rssi == tmp_min_rssi)
1947                                {
1948                                        if(tmp_sec_rssi == tmp_min_rssi)
1949                                        {       // let sec and min point to the different index
1950                                                tmp_min_rssi = cur_rf_rssi;
1951                                                min_rssi_index = i;
1952                                        }
1953                                        else
1954                                        {
1955                                                // This case we don't need to set any index
1956                                        }
1957                                }
1958                                else if(cur_rf_rssi < tmp_min_rssi)
1959                                {
1960                                        tmp_min_rssi = cur_rf_rssi;
1961                                        min_rssi_index = i;
1962                                }
1963                        }
1964                }
1965        }
1966
1967        rf_num = 0;
1968        // decide max/sec/min cck pwdb index
1969        if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
1970        {
1971                for (i=0; i<RF90_PATH_MAX; i++)
1972                {
1973                        if(priv->brfpath_rxenable[i])
1974                        {
1975                                rf_num++;
1976                                cur_cck_pwdb =  DM_RxPathSelTable.cck_pwdb_sta[i];
1977
1978                                if(rf_num == 1) // find first enabled rf path and the rssi values
1979                                {       //initialize, set all rssi index to the same one
1980                                        cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i;
1981                                        tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb;
1982                                }
1983                                else if(rf_num == 2)
1984                                {       // we pick up the max index first, and let sec and min to be the same one
1985                                        if(cur_cck_pwdb >= tmp_cck_max_pwdb)
1986                                        {
1987                                                tmp_cck_max_pwdb = cur_cck_pwdb;
1988                                                cck_rx_ver2_max_index = i;
1989                                        }
1990                                        else
1991                                        {
1992                                                tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb;
1993                                                cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i;
1994                                        }
1995                                }
1996                                else
1997                                {
1998                                        if(cur_cck_pwdb > tmp_cck_max_pwdb)
1999                                        {
2000                                                tmp_cck_sec_pwdb = tmp_cck_max_pwdb;
2001                                                cck_rx_ver2_sec_index = cck_rx_ver2_max_index;
2002                                                tmp_cck_max_pwdb = cur_cck_pwdb;
2003                                                cck_rx_ver2_max_index = i;
2004                                        }
2005                                        else if(cur_cck_pwdb == tmp_cck_max_pwdb)
2006                                        {       // let sec and min point to the different index
2007                                                tmp_cck_sec_pwdb = cur_cck_pwdb;
2008                                                cck_rx_ver2_sec_index = i;
2009                                        }
2010                                        else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb))
2011                                        {
2012                                                tmp_cck_sec_pwdb = cur_cck_pwdb;
2013                                                cck_rx_ver2_sec_index = i;
2014                                        }
2015                                        else if(cur_cck_pwdb == tmp_cck_sec_pwdb)
2016                                        {
2017                                                if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2018                                                {       // let sec and min point to the different index
2019                                                        tmp_cck_sec_pwdb = cur_cck_pwdb;
2020                                                        cck_rx_ver2_sec_index = i;
2021                                                }
2022                                                else
2023                                                {
2024                                                        // This case we don't need to set any index
2025                                                }
2026                                        }
2027                                        else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb))
2028                                        {
2029                                                // This case we don't need to set any index
2030                                        }
2031                                        else if(cur_cck_pwdb == tmp_cck_min_pwdb)
2032                                        {
2033                                                if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2034                                                {       // let sec and min point to the different index
2035                                                        tmp_cck_min_pwdb = cur_cck_pwdb;
2036                                                        cck_rx_ver2_min_index = i;
2037                                                }
2038                                                else
2039                                                {
2040                                                        // This case we don't need to set any index
2041                                                }
2042                                        }
2043                                        else if(cur_cck_pwdb < tmp_cck_min_pwdb)
2044                                        {
2045                                                tmp_cck_min_pwdb = cur_cck_pwdb;
2046                                                cck_rx_ver2_min_index = i;
2047                                        }
2048                                }
2049
2050                        }
2051                }
2052        }
2053
2054
2055        // Set CCK Rx path
2056        // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path.
2057        update_cck_rx_path = 0;
2058        if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
2059        {
2060                cck_default_Rx = cck_rx_ver2_max_index;
2061                cck_optional_Rx = cck_rx_ver2_sec_index;
2062                if(tmp_cck_max_pwdb != -64)
2063                        update_cck_rx_path = 1;
2064        }
2065
2066        if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2)
2067        {
2068                if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH)
2069                {
2070                        //record the enabled rssi threshold
2071                        DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
2072                        //disable the BB Rx path, OFDM
2073                        rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xc04[3:0]
2074                        rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xd04[3:0]
2075                        disabled_rf_cnt++;
2076                }
2077                if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1)
2078                {
2079                        cck_default_Rx = max_rssi_index;
2080                        cck_optional_Rx = sec_rssi_index;
2081                        if(tmp_max_rssi)
2082                                update_cck_rx_path = 1;
2083                }
2084        }
2085
2086        if(update_cck_rx_path)
2087        {
2088                DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
2089                rtl8192_setBBreg(priv, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
2090        }
2091
2092        if(DM_RxPathSelTable.disabledRF)
2093        {
2094                for(i=0; i<4; i++)
2095                {
2096                        if((DM_RxPathSelTable.disabledRF>>i) & 0x1)     //disabled rf
2097                        {
2098                                if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i])
2099                                {
2100                                        //enable the BB Rx path
2101                                        rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);      // 0xc04[3:0]
2102                                        rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);      // 0xd04[3:0]
2103                                        DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2104                                        disabled_rf_cnt--;
2105                                }
2106                        }
2107                }
2108        }
2109}
2110
2111/*
2112 * Call a workitem to check current RXRF path and Rx Path selection by RSSI.
2113 */
2114static void dm_check_rx_path_selection(struct r8192_priv *priv)
2115{
2116        queue_delayed_work(priv->priv_wq,&priv->rfpath_check_wq,0);
2117}
2118
2119static void dm_init_fsync(struct r8192_priv *priv)
2120{
2121        priv->ieee80211->fsync_time_interval = 500;
2122        priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
2123        priv->ieee80211->fsync_rssi_threshold = 30;
2124        priv->ieee80211->bfsync_enable = false;
2125        priv->ieee80211->fsync_multiple_timeinterval = 3;
2126        priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
2127        priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
2128        priv->ieee80211->fsync_state = Default_Fsync;
2129        priv->framesyncMonitor = 1;     // current default 0xc38 monitor on
2130
2131        init_timer(&priv->fsync_timer);
2132        priv->fsync_timer.data = (unsigned long)priv;
2133        priv->fsync_timer.function = dm_fsync_timer_callback;
2134}
2135
2136
2137static void dm_deInit_fsync(struct r8192_priv *priv)
2138{
2139        del_timer_sync(&priv->fsync_timer);
2140}
2141
2142static void dm_fsync_timer_callback(unsigned long data)
2143{
2144        struct r8192_priv *priv = (struct r8192_priv *)data;
2145        u32 rate_index, rate_count = 0, rate_count_diff=0;
2146        bool            bSwitchFromCountDiff = false;
2147        bool            bDoubleTimeInterval = false;
2148
2149        if(     priv->ieee80211->state == IEEE80211_LINKED &&
2150                priv->ieee80211->bfsync_enable &&
2151                (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2152        {
2153                 // Count rate 54, MCS [7], [12, 13, 14, 15]
2154                u32 rate_bitmap;
2155                for(rate_index = 0; rate_index <= 27; rate_index++)
2156                {
2157                        rate_bitmap  = 1 << rate_index;
2158                        if(priv->ieee80211->fsync_rate_bitmap &  rate_bitmap)
2159                                rate_count+= priv->stats.received_rate_histogram[1][rate_index];
2160                }
2161
2162                if(rate_count < priv->rate_record)
2163                        rate_count_diff = 0xffffffff - rate_count + priv->rate_record;
2164                else
2165                        rate_count_diff = rate_count - priv->rate_record;
2166                if(rate_count_diff < priv->rateCountDiffRecord)
2167                {
2168
2169                        u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
2170                        // Contiune count
2171                        if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold)
2172                                priv->ContiuneDiffCount++;
2173                        else
2174                                priv->ContiuneDiffCount = 0;
2175
2176                        // Contiune count over
2177                        if(priv->ContiuneDiffCount >=2)
2178                        {
2179                                bSwitchFromCountDiff = true;
2180                                priv->ContiuneDiffCount = 0;
2181                        }
2182                }
2183                else
2184                {
2185                        // Stop contiune count
2186                        priv->ContiuneDiffCount = 0;
2187                }
2188
2189                //If Count diff <= FsyncRateCountThreshold
2190                if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold)
2191                {
2192                        bSwitchFromCountDiff = true;
2193                        priv->ContiuneDiffCount = 0;
2194                }
2195                priv->rate_record = rate_count;
2196                priv->rateCountDiffRecord = rate_count_diff;
2197                RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2198                // if we never receive those mcs rate and rssi > 30 % then switch fsyn
2199                if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff)
2200                {
2201                        bDoubleTimeInterval = true;
2202                        priv->bswitch_fsync = !priv->bswitch_fsync;
2203                        if(priv->bswitch_fsync)
2204                        {
2205                                write_nic_byte(priv,0xC36, 0x1c);
2206                                write_nic_byte(priv, 0xC3e, 0x90);
2207                        }
2208                        else
2209                        {
2210                                write_nic_byte(priv, 0xC36, 0x5c);
2211                                write_nic_byte(priv, 0xC3e, 0x96);
2212                        }
2213                }
2214                else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold)
2215                {
2216                        if(priv->bswitch_fsync)
2217                        {
2218                                priv->bswitch_fsync  = false;
2219                                write_nic_byte(priv, 0xC36, 0x5c);
2220                                write_nic_byte(priv, 0xC3e, 0x96);
2221                        }
2222                }
2223                if(bDoubleTimeInterval){
2224                        if(timer_pending(&priv->fsync_timer))
2225                                del_timer_sync(&priv->fsync_timer);
2226                        priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval);
2227                        add_timer(&priv->fsync_timer);
2228                }
2229                else{
2230                        if(timer_pending(&priv->fsync_timer))
2231                                del_timer_sync(&priv->fsync_timer);
2232                        priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2233                        add_timer(&priv->fsync_timer);
2234                }
2235        }
2236        else
2237        {
2238                // Let Register return to default value;
2239                if(priv->bswitch_fsync)
2240                {
2241                        priv->bswitch_fsync  = false;
2242                        write_nic_byte(priv, 0xC36, 0x5c);
2243                        write_nic_byte(priv, 0xC3e, 0x96);
2244                }
2245                priv->ContiuneDiffCount = 0;
2246                write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2247        }
2248        RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
2249        RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2250}
2251
2252static void dm_StartHWFsync(struct r8192_priv *priv)
2253{
2254        RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2255        write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cf);
2256        write_nic_byte(priv, 0xc3b, 0x41);
2257}
2258
2259static void dm_EndSWFsync(struct r8192_priv *priv)
2260{
2261        RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2262        del_timer_sync(&(priv->fsync_timer));
2263
2264        // Let Register return to default value;
2265        if(priv->bswitch_fsync)
2266        {
2267                priv->bswitch_fsync  = false;
2268
2269                write_nic_byte(priv, 0xC36, 0x40);
2270
2271                write_nic_byte(priv, 0xC3e, 0x96);
2272        }
2273
2274        priv->ContiuneDiffCount = 0;
2275
2276        write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2277}
2278
2279static void dm_StartSWFsync(struct r8192_priv *priv)
2280{
2281        u32                     rateIndex;
2282        u32                     rateBitmap;
2283
2284        RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2285        // Initial rate record to zero, start to record.
2286        priv->rate_record = 0;
2287        // Initial contiune diff count to zero, start to record.
2288        priv->ContiuneDiffCount = 0;
2289        priv->rateCountDiffRecord = 0;
2290        priv->bswitch_fsync  = false;
2291
2292        if(priv->ieee80211->mode == WIRELESS_MODE_N_24G)
2293        {
2294                priv->ieee80211->fsync_firstdiff_ratethreshold= 600;
2295                priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff;
2296        }
2297        else
2298        {
2299                priv->ieee80211->fsync_firstdiff_ratethreshold= 200;
2300                priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
2301        }
2302        for(rateIndex = 0; rateIndex <= 27; rateIndex++)
2303        {
2304                rateBitmap  = 1 << rateIndex;
2305                if(priv->ieee80211->fsync_rate_bitmap &  rateBitmap)
2306                        priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
2307        }
2308        if(timer_pending(&priv->fsync_timer))
2309                del_timer_sync(&priv->fsync_timer);
2310        priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2311        add_timer(&priv->fsync_timer);
2312
2313        write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cd);
2314}
2315
2316static void dm_EndHWFsync(struct r8192_priv *priv)
2317{
2318        RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2319        write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2320        write_nic_byte(priv, 0xc3b, 0x49);
2321}
2322
2323static void dm_check_fsync(struct r8192_priv *priv)
2324{
2325#define RegC38_Default                          0
2326#define RegC38_NonFsync_Other_AP        1
2327#define RegC38_Fsync_AP_BCM             2
2328        //u32                   framesyncC34;
2329        static u8               reg_c38_State=RegC38_Default;
2330        static u32      reset_cnt=0;
2331
2332        RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval);
2333        RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold);
2334
2335        if(     priv->ieee80211->state == IEEE80211_LINKED &&
2336                (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2337        {
2338                if(priv->ieee80211->bfsync_enable == 0)
2339                {
2340                        switch(priv->ieee80211->fsync_state)
2341                        {
2342                                case Default_Fsync:
2343                                        dm_StartHWFsync(priv);
2344                                        priv->ieee80211->fsync_state = HW_Fsync;
2345                                        break;
2346                                case SW_Fsync:
2347                                        dm_EndSWFsync(priv);
2348                                        dm_StartHWFsync(priv);
2349                                        priv->ieee80211->fsync_state = HW_Fsync;
2350                                        break;
2351                                case HW_Fsync:
2352                                default:
2353                                        break;
2354                        }
2355                }
2356                else
2357                {
2358                        switch(priv->ieee80211->fsync_state)
2359                        {
2360                                case Default_Fsync:
2361                                        dm_StartSWFsync(priv);
2362                                        priv->ieee80211->fsync_state = SW_Fsync;
2363                                        break;
2364                                case HW_Fsync:
2365                                        dm_EndHWFsync(priv);
2366                                        dm_StartSWFsync(priv);
2367                                        priv->ieee80211->fsync_state = SW_Fsync;
2368                                        break;
2369                                case SW_Fsync:
2370                                default:
2371                                        break;
2372
2373                        }
2374                }
2375                if(priv->framesyncMonitor)
2376                {
2377                        if(reg_c38_State != RegC38_Fsync_AP_BCM)
2378                        {       //For broadcom AP we write different default value
2379                                write_nic_byte(priv, rOFDM0_RxDetector3, 0x95);
2380
2381                                reg_c38_State = RegC38_Fsync_AP_BCM;
2382                        }
2383                }
2384        }
2385        else
2386        {
2387                switch(priv->ieee80211->fsync_state)
2388                {
2389                        case HW_Fsync:
2390                                dm_EndHWFsync(priv);
2391                                priv->ieee80211->fsync_state = Default_Fsync;
2392                                break;
2393                        case SW_Fsync:
2394                                dm_EndSWFsync(priv);
2395                                priv->ieee80211->fsync_state = Default_Fsync;
2396                                break;
2397                        case Default_Fsync:
2398                        default:
2399                                break;
2400                }
2401
2402                if(priv->framesyncMonitor)
2403                {
2404                        if(priv->ieee80211->state == IEEE80211_LINKED)
2405                        {
2406                                if(priv->undecorated_smoothed_pwdb <= RegC38_TH)
2407                                {
2408                                        if(reg_c38_State != RegC38_NonFsync_Other_AP)
2409                                        {
2410                                                write_nic_byte(priv, rOFDM0_RxDetector3, 0x90);
2411
2412                                                reg_c38_State = RegC38_NonFsync_Other_AP;
2413                                        }
2414                                }
2415                                else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5))
2416                                {
2417                                        if(reg_c38_State)
2418                                        {
2419                                                write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2420                                                reg_c38_State = RegC38_Default;
2421                                        }
2422                                }
2423                        }
2424                        else
2425                        {
2426                                if(reg_c38_State)
2427                                {
2428                                        write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2429                                        reg_c38_State = RegC38_Default;
2430                                }
2431                        }
2432                }
2433        }
2434        if(priv->framesyncMonitor)
2435        {
2436                if(priv->reset_count != reset_cnt)
2437                {       //After silent reset, the reg_c38_State will be returned to default value
2438                        write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2439                        reg_c38_State = RegC38_Default;
2440                        reset_cnt = priv->reset_count;
2441                }
2442        }
2443        else
2444        {
2445                if(reg_c38_State)
2446                {
2447                        write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2448                        reg_c38_State = RegC38_Default;
2449                }
2450        }
2451}
2452
2453/*
2454 * Detect Signal strength to control TX Registry
2455 * Tx Power Control For Near/Far Range
2456 */
2457static void dm_init_dynamic_txpower(struct r8192_priv *priv)
2458{
2459        //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
2460        priv->ieee80211->bdynamic_txpower_enable = true;    //Default to enable Tx Power Control
2461        priv->bLastDTPFlag_High = false;
2462        priv->bLastDTPFlag_Low = false;
2463        priv->bDynamicTxHighPower = false;
2464        priv->bDynamicTxLowPower = false;
2465}
2466
2467static void dm_dynamic_txpower(struct r8192_priv *priv)
2468{
2469        unsigned int txhipower_threshhold=0;
2470        unsigned int txlowpower_threshold=0;
2471        if(priv->ieee80211->bdynamic_txpower_enable != true)
2472        {
2473                priv->bDynamicTxHighPower = false;
2474                priv->bDynamicTxLowPower = false;
2475                return;
2476        }
2477        if((priv->ieee80211->current_network.atheros_cap_exist ) && (priv->ieee80211->mode == IEEE_G)){
2478                txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
2479                txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
2480        }
2481        else
2482        {
2483                txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
2484                txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
2485        }
2486
2487        RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n" , priv->undecorated_smoothed_pwdb);
2488
2489        if(priv->ieee80211->state == IEEE80211_LINKED)
2490        {
2491                if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold)
2492                {
2493                        priv->bDynamicTxHighPower = true;
2494                        priv->bDynamicTxLowPower = false;
2495                }
2496                else
2497                {
2498                        // high power state check
2499                        if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true)
2500                        {
2501                                priv->bDynamicTxHighPower = false;
2502                        }
2503                        // low power state check
2504                        if(priv->undecorated_smoothed_pwdb < 35)
2505                        {
2506                                priv->bDynamicTxLowPower = true;
2507                        }
2508                        else if(priv->undecorated_smoothed_pwdb >= 40)
2509                        {
2510                                priv->bDynamicTxLowPower = false;
2511                        }
2512                }
2513        }
2514        else
2515        {
2516                //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;
2517                priv->bDynamicTxHighPower = false;
2518                priv->bDynamicTxLowPower = false;
2519        }
2520
2521        if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) ||
2522                (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) )
2523        {
2524                RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->ieee80211->current_network.channel);
2525
2526
2527                rtl8192_phy_setTxPower(priv, priv->ieee80211->current_network.channel);
2528
2529        }
2530        priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
2531        priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
2532
2533}
2534
2535//added by vivi, for read tx rate and retrycount
2536static void dm_check_txrateandretrycount(struct r8192_priv *priv)
2537{
2538        struct ieee80211_device* ieee = priv->ieee80211;
2539
2540        //for initial tx rate
2541        ieee->softmac_stats.last_packet_rate = read_nic_byte(priv ,Initial_Tx_Rate_Reg);
2542        //for tx tx retry count
2543        ieee->softmac_stats.txretrycount = read_nic_dword(priv, Tx_Retry_Count_Reg);
2544}
2545
2546static void dm_send_rssi_tofw(struct r8192_priv *priv)
2547{
2548        // If we test chariot, we should stop the TX command ?
2549        // Because 92E will always silent reset when we send tx command. We use register
2550        // 0x1e0(byte) to botify driver.
2551        write_nic_byte(priv, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
2552        return;
2553}
2554
2555