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