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