Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / net / wireless / rtlwifi / rtl8192se / dm.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29
30 #include "../wifi.h"
31 #include "../base.h"
32 #include "reg.h"
33 #include "def.h"
34 #include "phy.h"
35 #include "dm.h"
36 #include "fw.h"
37
38 struct dig_t digtable;
39 static const u32 edca_setting_dl[PEER_MAX] = {
40         0xa44f,         /* 0 UNKNOWN */
41         0x5ea44f,       /* 1 REALTEK_90 */
42         0x5ea44f,       /* 2 REALTEK_92SE */
43         0xa630,         /* 3 BROAD      */
44         0xa44f,         /* 4 RAL */
45         0xa630,         /* 5 ATH */
46         0xa630,         /* 6 CISCO */
47         0xa42b,         /* 7 MARV */
48 };
49
50 static const u32 edca_setting_dl_gmode[PEER_MAX] = {
51         0x4322,         /* 0 UNKNOWN */
52         0xa44f,         /* 1 REALTEK_90 */
53         0x5ea44f,       /* 2 REALTEK_92SE */
54         0xa42b,         /* 3 BROAD */
55         0x5e4322,       /* 4 RAL */
56         0x4322,         /* 5 ATH */
57         0xa430,         /* 6 CISCO */
58         0x5ea44f,       /* 7 MARV */
59 };
60
61 static const u32 edca_setting_ul[PEER_MAX] = {
62         0x5e4322,       /* 0 UNKNOWN */
63         0xa44f,         /* 1 REALTEK_90 */
64         0x5ea44f,       /* 2 REALTEK_92SE */
65         0x5ea322,       /* 3 BROAD */
66         0x5ea422,       /* 4 RAL */
67         0x5ea322,       /* 5 ATH */
68         0x3ea44f,       /* 6 CISCO */
69         0x5ea44f,       /* 7 MARV */
70 };
71
72 static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw)
73 {
74         struct rtl_priv *rtlpriv = rtl_priv(hw);
75         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
76
77         static u64 last_txok_cnt;
78         static u64 last_rxok_cnt;
79         u64 cur_txok_cnt = 0;
80         u64 cur_rxok_cnt = 0;
81
82         u32 edca_be_ul = edca_setting_ul[mac->vendor];
83         u32 edca_be_dl = edca_setting_dl[mac->vendor];
84         u32 edca_gmode = edca_setting_dl_gmode[mac->vendor];
85
86         if (mac->link_state != MAC80211_LINKED) {
87                 rtlpriv->dm.current_turbo_edca = false;
88                 goto dm_checkedcaturbo_exit;
89         }
90
91         if ((!rtlpriv->dm.is_any_nonbepkts) &&
92             (!rtlpriv->dm.disable_framebursting)) {
93                 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
94                 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
95
96                 if (rtlpriv->phy.rf_type == RF_1T2R) {
97                         if (cur_txok_cnt > 4 * cur_rxok_cnt) {
98                                 /* Uplink TP is present. */
99                                 if (rtlpriv->dm.is_cur_rdlstate ||
100                                         !rtlpriv->dm.current_turbo_edca) {
101                                         rtl_write_dword(rtlpriv, EDCAPARA_BE,
102                                                         edca_be_ul);
103                                         rtlpriv->dm.is_cur_rdlstate = false;
104                                 }
105                         } else {/* Balance TP is present. */
106                                 if (!rtlpriv->dm.is_cur_rdlstate ||
107                                         !rtlpriv->dm.current_turbo_edca) {
108                                         if (mac->mode == WIRELESS_MODE_G ||
109                                             mac->mode == WIRELESS_MODE_B)
110                                                 rtl_write_dword(rtlpriv,
111                                                                 EDCAPARA_BE,
112                                                                 edca_gmode);
113                                         else
114                                                 rtl_write_dword(rtlpriv,
115                                                                 EDCAPARA_BE,
116                                                                 edca_be_dl);
117                                         rtlpriv->dm.is_cur_rdlstate = true;
118                                 }
119                         }
120                         rtlpriv->dm.current_turbo_edca = true;
121                 } else {
122                         if (cur_rxok_cnt > 4 * cur_txok_cnt) {
123                                 if (!rtlpriv->dm.is_cur_rdlstate ||
124                                         !rtlpriv->dm.current_turbo_edca) {
125                                         if (mac->mode == WIRELESS_MODE_G ||
126                                             mac->mode == WIRELESS_MODE_B)
127                                                 rtl_write_dword(rtlpriv,
128                                                                 EDCAPARA_BE,
129                                                                 edca_gmode);
130                                         else
131                                                 rtl_write_dword(rtlpriv,
132                                                                 EDCAPARA_BE,
133                                                                 edca_be_dl);
134                                         rtlpriv->dm.is_cur_rdlstate = true;
135                                 }
136                         } else {
137                                 if (rtlpriv->dm.is_cur_rdlstate ||
138                                         !rtlpriv->dm.current_turbo_edca) {
139                                         rtl_write_dword(rtlpriv, EDCAPARA_BE,
140                                                         edca_be_ul);
141                                         rtlpriv->dm.is_cur_rdlstate = false;
142                                 }
143                         }
144                         rtlpriv->dm.current_turbo_edca = true;
145                 }
146         } else {
147                 if (rtlpriv->dm.current_turbo_edca) {
148                         u8 tmp = AC0_BE;
149                         rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
150                                                       (u8 *)(&tmp));
151                         rtlpriv->dm.current_turbo_edca = false;
152                 }
153         }
154
155 dm_checkedcaturbo_exit:
156         rtlpriv->dm.is_any_nonbepkts = false;
157         last_txok_cnt = rtlpriv->stats.txbytesunicast;
158         last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
159 }
160
161 static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
162                                         struct ieee80211_hw *hw)
163 {
164         struct rtl_priv *rtlpriv = rtl_priv(hw);
165         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
166         u8 thermalvalue = 0;
167
168         rtlpriv->dm.txpower_trackinginit = true;
169
170         thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
171
172         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
173                  ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
174                   "eeprom_thermalmeter 0x%x\n", thermalvalue,
175                   rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter));
176
177         if (thermalvalue) {
178                 rtlpriv->dm.thermalvalue = thermalvalue;
179                 rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
180         }
181
182         rtlpriv->dm.txpowercount = 0;
183 }
184
185 static void _rtl92s_dm_check_txpowertracking_thermalmeter(
186                                         struct ieee80211_hw *hw)
187 {
188         struct rtl_priv *rtlpriv = rtl_priv(hw);
189         struct rtl_phy *rtlphy = &(rtlpriv->phy);
190         static u8 tm_trigger;
191         u8 tx_power_checkcnt = 5;
192
193         /* 2T2R TP issue */
194         if (rtlphy->rf_type == RF_2T2R)
195                 return;
196
197         if (!rtlpriv->dm.txpower_tracking)
198                 return;
199
200         if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) {
201                 rtlpriv->dm.txpowercount++;
202                 return;
203         }
204
205         if (!tm_trigger) {
206                 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
207                               RFREG_OFFSET_MASK, 0x60);
208                 tm_trigger = 1;
209         } else {
210                 _rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
211                 tm_trigger = 0;
212         }
213 }
214
215 static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
216 {
217         struct rtl_priv *rtlpriv = rtl_priv(hw);
218         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
219         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
220         struct rate_adaptive *ra = &(rtlpriv->ra);
221
222         u32 low_rssi_thresh = 0;
223         u32 middle_rssi_thresh = 0;
224         u32 high_rssi_thresh = 0;
225         struct ieee80211_sta *sta = NULL;
226
227         if (is_hal_stop(rtlhal))
228                 return;
229
230         if (!rtlpriv->dm.useramask)
231                 return;
232
233         if (!rtlpriv->dm.inform_fw_driverctrldm) {
234                 rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
235                 rtlpriv->dm.inform_fw_driverctrldm = true;
236         }
237
238         rcu_read_lock();
239         if (mac->opmode == NL80211_IFTYPE_STATION)
240                 sta = get_sta(hw, mac->vif, mac->bssid);
241         if ((mac->link_state == MAC80211_LINKED) &&
242             (mac->opmode == NL80211_IFTYPE_STATION)) {
243                 switch (ra->pre_ratr_state) {
244                 case DM_RATR_STA_HIGH:
245                         high_rssi_thresh = 40;
246                         middle_rssi_thresh = 30;
247                         low_rssi_thresh = 20;
248                         break;
249                 case DM_RATR_STA_MIDDLE:
250                         high_rssi_thresh = 44;
251                         middle_rssi_thresh = 30;
252                         low_rssi_thresh = 20;
253                         break;
254                 case DM_RATR_STA_LOW:
255                         high_rssi_thresh = 44;
256                         middle_rssi_thresh = 34;
257                         low_rssi_thresh = 20;
258                         break;
259                 case DM_RATR_STA_ULTRALOW:
260                         high_rssi_thresh = 44;
261                         middle_rssi_thresh = 34;
262                         low_rssi_thresh = 24;
263                         break;
264                 default:
265                         high_rssi_thresh = 44;
266                         middle_rssi_thresh = 34;
267                         low_rssi_thresh = 24;
268                         break;
269                 }
270
271                 if (rtlpriv->dm.undecorated_smoothed_pwdb >
272                     (long)high_rssi_thresh) {
273                         ra->ratr_state = DM_RATR_STA_HIGH;
274                 } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
275                            (long)middle_rssi_thresh) {
276                         ra->ratr_state = DM_RATR_STA_LOW;
277                 } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
278                            (long)low_rssi_thresh) {
279                         ra->ratr_state = DM_RATR_STA_LOW;
280                 } else {
281                         ra->ratr_state = DM_RATR_STA_ULTRALOW;
282                 }
283
284                 if (ra->pre_ratr_state != ra->ratr_state) {
285                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, ("RSSI = %ld "
286                                 "RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
287                                 rtlpriv->dm.undecorated_smoothed_pwdb,
288                                 ra->ratr_state,
289                                 ra->pre_ratr_state, ra->ratr_state));
290
291                         rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
292                                                            ra->ratr_state);
293                         ra->pre_ratr_state = ra->ratr_state;
294                 }
295         }
296         rcu_read_unlock();
297 }
298
299 static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
300 {
301         struct rtl_priv *rtlpriv = rtl_priv(hw);
302         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
303         struct rtl_phy *rtlphy = &(rtlpriv->phy);
304         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
305         bool current_mrc;
306         bool enable_mrc = true;
307         long tmpentry_maxpwdb = 0;
308         u8 rssi_a = 0;
309         u8 rssi_b = 0;
310
311         if (is_hal_stop(rtlhal))
312                 return;
313
314         if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R))
315                 return;
316
317         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
318
319         if (mac->link_state >= MAC80211_LINKED) {
320                 if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) {
321                         rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
322                         rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
323                 }
324         }
325
326         /* MRC settings would NOT affect TP on Wireless B mode. */
327         if (mac->mode != WIRELESS_MODE_B) {
328                 if ((rssi_a == 0) && (rssi_b == 0)) {
329                         enable_mrc = true;
330                 } else if (rssi_b > 30) {
331                         /* Turn on B-Path */
332                         enable_mrc = true;
333                 } else if (rssi_b < 5) {
334                         /* Turn off B-path  */
335                         enable_mrc = false;
336                 /* Take care of RSSI differentiation. */
337                 } else if (rssi_a > 15 && (rssi_a >= rssi_b)) {
338                         if ((rssi_a - rssi_b) > 15)
339                                 /* Turn off B-path  */
340                                 enable_mrc = false;
341                         else if ((rssi_a - rssi_b) < 10)
342                                 /* Turn on B-Path */
343                                 enable_mrc = true;
344                         else
345                                 enable_mrc = current_mrc;
346                 } else {
347                         /* Turn on B-Path */
348                         enable_mrc = true;
349                 }
350         }
351
352         /* Update MRC settings if needed. */
353         if (enable_mrc != current_mrc)
354                 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC,
355                                               (u8 *)&enable_mrc);
356
357 }
358
359 void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw)
360 {
361         struct rtl_priv *rtlpriv = rtl_priv(hw);
362
363         rtlpriv->dm.current_turbo_edca = false;
364         rtlpriv->dm.is_any_nonbepkts = false;
365         rtlpriv->dm.is_cur_rdlstate = false;
366 }
367
368 static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
369 {
370         struct rtl_priv *rtlpriv = rtl_priv(hw);
371         struct rate_adaptive *ra = &(rtlpriv->ra);
372
373         ra->ratr_state = DM_RATR_STA_MAX;
374         ra->pre_ratr_state = DM_RATR_STA_MAX;
375
376         if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
377                 rtlpriv->dm.useramask = true;
378         else
379                 rtlpriv->dm.useramask = false;
380
381         rtlpriv->dm.useramask = false;
382         rtlpriv->dm.inform_fw_driverctrldm = false;
383 }
384
385 static void _rtl92s_dm_init_txpowertracking_thermalmeter(
386                                 struct ieee80211_hw *hw)
387 {
388         struct rtl_priv *rtlpriv = rtl_priv(hw);
389
390         rtlpriv->dm.txpower_tracking = true;
391         rtlpriv->dm.txpowercount = 0;
392         rtlpriv->dm.txpower_trackinginit = false;
393 }
394
395 static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
396 {
397         struct rtl_priv *rtlpriv = rtl_priv(hw);
398         struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
399         u32 ret_value;
400
401         ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
402         falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
403
404         ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
405         falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
406         falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
407         ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
408         falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
409
410         falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
411                 falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail +
412                 falsealm_cnt->cnt_mcs_fail;
413
414         /* read CCK false alarm */
415         ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD);
416         falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff);
417         falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
418                 falsealm_cnt->cnt_cck_fail;
419 }
420
421 static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
422 {
423         struct rtl_priv *rtlpriv = rtl_priv(hw);
424         struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
425
426         if (falsealm_cnt->cnt_all > digtable.fa_highthresh) {
427                 if ((digtable.backoff_val - 6) <
428                         digtable.backoffval_range_min)
429                         digtable.backoff_val = digtable.backoffval_range_min;
430                 else
431                         digtable.backoff_val -= 6;
432         } else if (falsealm_cnt->cnt_all < digtable.fa_lowthresh) {
433                 if ((digtable.backoff_val + 6) >
434                         digtable.backoffval_range_max)
435                         digtable.backoff_val =
436                                  digtable.backoffval_range_max;
437                 else
438                         digtable.backoff_val += 6;
439         }
440 }
441
442 static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
443 {
444         struct rtl_priv *rtlpriv = rtl_priv(hw);
445         struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
446         static u8 initialized, force_write;
447         u8 initial_gain = 0;
448
449         if ((digtable.pre_sta_connectstate == digtable.cur_sta_connectstate) ||
450                 (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) {
451                 if (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) {
452                         if (rtlpriv->psc.rfpwr_state != ERFON)
453                                 return;
454
455                         if (digtable.backoff_enable_flag)
456                                 rtl92s_backoff_enable_flag(hw);
457                         else
458                                 digtable.backoff_val = DM_DIG_BACKOFF;
459
460                         if ((digtable.rssi_val + 10 - digtable.backoff_val) >
461                                 digtable.rx_gain_range_max)
462                                 digtable.cur_igvalue =
463                                                 digtable.rx_gain_range_max;
464                         else if ((digtable.rssi_val + 10 - digtable.backoff_val)
465                                  < digtable.rx_gain_range_min)
466                                 digtable.cur_igvalue =
467                                                 digtable.rx_gain_range_min;
468                         else
469                                 digtable.cur_igvalue = digtable.rssi_val + 10 -
470                                                 digtable.backoff_val;
471
472                         if (falsealm_cnt->cnt_all > 10000)
473                                 digtable.cur_igvalue =
474                                          (digtable.cur_igvalue > 0x33) ?
475                                          digtable.cur_igvalue : 0x33;
476
477                         if (falsealm_cnt->cnt_all > 16000)
478                                 digtable.cur_igvalue =
479                                                  digtable.rx_gain_range_max;
480                 /* connected -> connected or disconnected -> disconnected  */
481                 } else {
482                         /* Firmware control DIG, do nothing in driver dm */
483                         return;
484                 }
485                 /* disconnected -> connected or connected ->
486                  * disconnected or beforeconnect->(dis)connected */
487         } else {
488                 /* Enable FW DIG */
489                 digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
490                 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
491
492                 digtable.backoff_val = DM_DIG_BACKOFF;
493                 digtable.cur_igvalue = rtlpriv->phy.default_initialgain[0];
494                 digtable.pre_igvalue = 0;
495                 return;
496         }
497
498         /* Forced writing to prevent from fw-dig overwriting. */
499         if (digtable.pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
500                                                   MASKBYTE0))
501                 force_write = 1;
502
503         if ((digtable.pre_igvalue != digtable.cur_igvalue) ||
504             !initialized || force_write) {
505                 /* Disable FW DIG */
506                 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE);
507
508                 initial_gain = (u8)digtable.cur_igvalue;
509
510                 /* Set initial gain. */
511                 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain);
512                 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain);
513                 digtable.pre_igvalue = digtable.cur_igvalue;
514                 initialized = 1;
515                 force_write = 0;
516         }
517 }
518
519 static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
520 {
521         struct rtl_priv *rtlpriv = rtl_priv(hw);
522
523         if (rtlpriv->mac80211.act_scanning)
524                 return;
525
526         /* Decide the current status and if modify initial gain or not */
527         if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
528             rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
529                 digtable.cur_sta_connectstate = DIG_STA_CONNECT;
530         else
531                 digtable.cur_sta_connectstate = DIG_STA_DISCONNECT;
532
533         digtable.rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb;
534
535         /* Change dig mode to rssi */
536         if (digtable.cur_sta_connectstate != DIG_STA_DISCONNECT) {
537                 if (digtable.dig_twoport_algorithm ==
538                     DIG_TWO_PORT_ALGO_FALSE_ALARM) {
539                         digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
540                         rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
541                 }
542         }
543
544         _rtl92s_dm_false_alarm_counter_statistics(hw);
545         _rtl92s_dm_initial_gain_sta_beforeconnect(hw);
546
547         digtable.pre_sta_connectstate = digtable.cur_sta_connectstate;
548 }
549
550 static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
551 {
552         struct rtl_priv *rtlpriv = rtl_priv(hw);
553         struct rtl_phy *rtlphy = &(rtlpriv->phy);
554
555         /* 2T2R TP issue */
556         if (rtlphy->rf_type == RF_2T2R)
557                 return;
558
559         if (!rtlpriv->dm.dm_initialgain_enable)
560                 return;
561
562         if (digtable.dig_enable_flag == false)
563                 return;
564
565         _rtl92s_dm_ctrl_initgain_bytwoport(hw);
566 }
567
568 static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
569 {
570         struct rtl_priv *rtlpriv = rtl_priv(hw);
571         struct rtl_phy *rtlphy = &(rtlpriv->phy);
572         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
573         long undecorated_smoothed_pwdb;
574         long txpwr_threshold_lv1, txpwr_threshold_lv2;
575
576         /* 2T2R TP issue */
577         if (rtlphy->rf_type == RF_2T2R)
578                 return;
579
580         if (!rtlpriv->dm.dynamic_txpower_enable ||
581             rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
582                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
583                 return;
584         }
585
586         if ((mac->link_state < MAC80211_LINKED) &&
587             (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
588                 RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
589                          ("Not connected to any\n"));
590
591                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
592
593                 rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
594                 return;
595         }
596
597         if (mac->link_state >= MAC80211_LINKED) {
598                 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
599                         undecorated_smoothed_pwdb =
600                             rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
601                         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
602                                  ("AP Client PWDB = 0x%lx\n",
603                                   undecorated_smoothed_pwdb));
604                 } else {
605                         undecorated_smoothed_pwdb =
606                             rtlpriv->dm.undecorated_smoothed_pwdb;
607                         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
608                                  ("STA Default Port PWDB = 0x%lx\n",
609                                   undecorated_smoothed_pwdb));
610                 }
611         } else {
612                 undecorated_smoothed_pwdb =
613                     rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
614
615                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
616                          ("AP Ext Port PWDB = 0x%lx\n",
617                           undecorated_smoothed_pwdb));
618         }
619
620         txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
621         txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1;
622
623         if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
624                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
625         else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2)
626                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
627         else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) &&
628                 (undecorated_smoothed_pwdb >= txpwr_threshold_lv1))
629                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
630         else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3))
631                 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
632
633         if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
634                 rtl92s_phy_set_txpower(hw, rtlphy->current_channel);
635
636         rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
637 }
638
639 static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
640 {
641         struct rtl_priv *rtlpriv = rtl_priv(hw);
642
643         /* Disable DIG scheme now.*/
644         digtable.dig_enable_flag = true;
645         digtable.backoff_enable_flag = true;
646
647         if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) &&
648             (hal_get_firmwareversion(rtlpriv) >= 0x3c))
649                 digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT;
650         else
651                 digtable.dig_algorithm =
652                          DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
653
654         digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
655         digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
656         /* off=by real rssi value, on=by digtable.rssi_val for new dig */
657         digtable.dig_dbgmode = DM_DBG_OFF;
658         digtable.dig_slgorithm_switch = 0;
659
660         /* 2007/10/04 MH Define init gain threshol. */
661         digtable.dig_state = DM_STA_DIG_MAX;
662         digtable.dig_highpwrstate = DM_STA_DIG_MAX;
663
664         digtable.cur_sta_connectstate = DIG_STA_DISCONNECT;
665         digtable.pre_sta_connectstate = DIG_STA_DISCONNECT;
666         digtable.cur_ap_connectstate = DIG_AP_DISCONNECT;
667         digtable.pre_ap_connectstate = DIG_AP_DISCONNECT;
668
669         digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
670         digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
671
672         digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
673         digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
674
675         digtable.rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
676         digtable.rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
677
678         /* for dig debug rssi value */
679         digtable.rssi_val = 50;
680         digtable.backoff_val = DM_DIG_BACKOFF;
681         digtable.rx_gain_range_max = DM_DIG_MAX;
682
683         digtable.rx_gain_range_min = DM_DIG_MIN;
684
685         digtable.backoffval_range_max = DM_DIG_BACKOFF_MAX;
686         digtable.backoffval_range_min = DM_DIG_BACKOFF_MIN;
687 }
688
689 static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
690 {
691         struct rtl_priv *rtlpriv = rtl_priv(hw);
692
693         if ((hal_get_firmwareversion(rtlpriv) >= 60) &&
694             (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER))
695                 rtlpriv->dm.dynamic_txpower_enable = true;
696         else
697                 rtlpriv->dm.dynamic_txpower_enable = false;
698
699         rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
700         rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
701 }
702
703 void rtl92s_dm_init(struct ieee80211_hw *hw)
704 {
705         struct rtl_priv *rtlpriv = rtl_priv(hw);
706
707         rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
708         rtlpriv->dm.undecorated_smoothed_pwdb = -1;
709
710         _rtl92s_dm_init_dynamic_txpower(hw);
711         rtl92s_dm_init_edca_turbo(hw);
712         _rtl92s_dm_init_rate_adaptive_mask(hw);
713         _rtl92s_dm_init_txpowertracking_thermalmeter(hw);
714         _rtl92s_dm_init_dig(hw);
715
716         rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE);
717 }
718
719 void rtl92s_dm_watchdog(struct ieee80211_hw *hw)
720 {
721         _rtl92s_dm_check_edca_turbo(hw);
722         _rtl92s_dm_check_txpowertracking_thermalmeter(hw);
723         _rtl92s_dm_ctrl_initgain_byrssi(hw);
724         _rtl92s_dm_dynamic_txpower(hw);
725         _rtl92s_dm_refresh_rateadaptive_mask(hw);
726         _rtl92s_dm_switch_baseband_mrc(hw);
727 }
728