]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8192e/r8192E_dm.c
Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd
[~andy/linux] / drivers / staging / rtl8192e / r8192E_dm.c
1 /*++
2 Copyright-c Realtek Semiconductor Corp. All rights reserved.
3
4 Module Name:
5         r8192U_dm.c
6
7 Abstract:
8         HW dynamic mechanism.
9
10 Major 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 //
28 static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
29 { 0x5e4322,     0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322,       0x5e4322};
30 static 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
37 dig_t   dm_digtable;
38 // For Dynamic Rx Path Selection by Signal Strength
39 DRxPathSel      DM_RxPathSelTable;
40
41 void dm_gpio_change_rf_callback(struct work_struct *work);
42
43 // DM --> Rate Adaptive
44 static void dm_check_rate_adaptive(struct r8192_priv *priv);
45
46 // DM --> Bandwidth switch
47 static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv);
48 static void dm_bandwidth_autoswitch(struct r8192_priv *priv);
49
50 // DM --> TX power control
51 static void dm_check_txpower_tracking(struct r8192_priv *priv);
52
53 // DM --> Dynamic Init Gain by RSSI
54 static void dm_dig_init(struct r8192_priv *priv);
55 static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv);
56 static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv);
57 static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv);
58 static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv);
59 static void dm_initial_gain(struct r8192_priv *priv);
60 static void dm_pd_th(struct r8192_priv *priv);
61 static void dm_cs_ratio(struct r8192_priv *priv);
62
63 static void dm_init_ctstoself(struct r8192_priv *priv);
64 // DM --> EDCA turboe mode control
65 static void dm_check_edca_turbo(struct r8192_priv *priv);
66 static void dm_init_edca_turbo(struct r8192_priv *priv);
67
68 // DM --> HW RF control
69 static void dm_check_rfctrl_gpio(struct r8192_priv *priv);
70
71 // DM --> Check current RX RF path state
72 static void dm_check_rx_path_selection(struct r8192_priv *priv);
73 static void dm_init_rxpath_selection(struct r8192_priv *priv);
74 static void dm_rxpath_sel_byrssi(struct r8192_priv *priv);
75
76 // DM --> Fsync for broadcom ap
77 static void dm_init_fsync(struct r8192_priv *priv);
78 static void dm_deInit_fsync(struct r8192_priv *priv);
79
80 static void dm_check_txrateandretrycount(struct r8192_priv *priv);
81 static 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
85 static void dm_init_dynamic_txpower(struct r8192_priv *priv);
86 static void dm_dynamic_txpower(struct r8192_priv *priv);
87
88 // DM --> For rate adaptive and DIG, we must send RSSI to firmware
89 static void dm_send_rssi_tofw(struct r8192_priv *priv);
90 static void dm_ctstoself(struct r8192_priv *priv);
91
92 static 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  */
98 void 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
117 void deinit_hal_dm(struct r8192_priv *priv)
118 {
119         dm_deInit_fsync(priv);
120 }
121
122 void 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   */
152 void 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
196 static 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
340 static 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
350 static 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.
367 static 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 };
388 static 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
403 static 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
423 static 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
671 static 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
784 void 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
796 static 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  */
840 static 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  */
870 static 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
896 static 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
908 static 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
921 void 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
930 static 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
946 static 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
978 static 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
987 static 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
1036 static 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
1098 void 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. */
1107 static 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  */
1142 static 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
1154 static 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
1189 static 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
1329 static 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
1385 static 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
1449 static 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
1537 static 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
1596 void 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
1604 static 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
1702 dm_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
1709 static void dm_init_ctstoself(struct r8192_priv *priv)
1710 {
1711         priv->ieee80211->bCTSToSelfEnable = TRUE;
1712         priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
1713 }
1714
1715 static 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 */
1755 static 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. */
1767 void 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 */
1806 void 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
1831 static 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
1852 static 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  */
2114 static 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
2119 static 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
2137 static void dm_deInit_fsync(struct r8192_priv *priv)
2138 {
2139         del_timer_sync(&priv->fsync_timer);
2140 }
2141
2142 static 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
2252 static 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
2259 static 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
2279 static 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
2316 static 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
2323 static 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  */
2457 static 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
2467 static 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
2536 static 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
2546 static 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