sfc: Don't use enums as a bitmask.
[zen-stable.git] / drivers / net / wireless / rtlwifi / rtl8192se / dm.c
blobda86db86fa4a9ac3c8b6d6692d301343892f4368
1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
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.
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.
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
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
28 *****************************************************************************/
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"
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 */
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 */
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 */
72 static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw)
74 struct rtl_priv *rtlpriv = rtl_priv(hw);
75 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
77 static u64 last_txok_cnt;
78 static u64 last_rxok_cnt;
79 u64 cur_txok_cnt = 0;
80 u64 cur_rxok_cnt = 0;
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];
86 if (mac->link_state != MAC80211_LINKED) {
87 rtlpriv->dm.current_turbo_edca = false;
88 goto dm_checkedcaturbo_exit;
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;
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;
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;
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;
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;
144 rtlpriv->dm.current_turbo_edca = true;
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;
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;
161 static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
162 struct ieee80211_hw *hw)
164 struct rtl_priv *rtlpriv = rtl_priv(hw);
165 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
166 u8 thermalvalue = 0;
168 rtlpriv->dm.txpower_trackinginit = true;
170 thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
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));
177 if (thermalvalue) {
178 rtlpriv->dm.thermalvalue = thermalvalue;
179 rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
182 rtlpriv->dm.txpowercount = 0;
185 static void _rtl92s_dm_check_txpowertracking_thermalmeter(
186 struct ieee80211_hw *hw)
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;
193 /* 2T2R TP issue */
194 if (rtlphy->rf_type == RF_2T2R)
195 return;
197 if (!rtlpriv->dm.txpower_tracking)
198 return;
200 if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) {
201 rtlpriv->dm.txpowercount++;
202 return;
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;
215 static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
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);
222 u32 low_rssi_thresh = 0;
223 u32 middle_rssi_thresh = 0;
224 u32 high_rssi_thresh = 0;
225 u8 rssi_level;
226 struct ieee80211_sta *sta = NULL;
228 if (is_hal_stop(rtlhal))
229 return;
231 if (!rtlpriv->dm.useramask)
232 return;
234 if (!rtlpriv->dm.inform_fw_driverctrldm) {
235 rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
236 rtlpriv->dm.inform_fw_driverctrldm = true;
239 rcu_read_lock();
240 if (mac->opmode == NL80211_IFTYPE_STATION)
241 sta = get_sta(hw, mac->vif, mac->bssid);
242 if ((mac->link_state == MAC80211_LINKED) &&
243 (mac->opmode == NL80211_IFTYPE_STATION)) {
244 switch (ra->pre_ratr_state) {
245 case DM_RATR_STA_HIGH:
246 high_rssi_thresh = 40;
247 middle_rssi_thresh = 30;
248 low_rssi_thresh = 20;
249 break;
250 case DM_RATR_STA_MIDDLE:
251 high_rssi_thresh = 44;
252 middle_rssi_thresh = 30;
253 low_rssi_thresh = 20;
254 break;
255 case DM_RATR_STA_LOW:
256 high_rssi_thresh = 44;
257 middle_rssi_thresh = 34;
258 low_rssi_thresh = 20;
259 break;
260 case DM_RATR_STA_ULTRALOW:
261 high_rssi_thresh = 44;
262 middle_rssi_thresh = 34;
263 low_rssi_thresh = 24;
264 break;
265 default:
266 high_rssi_thresh = 44;
267 middle_rssi_thresh = 34;
268 low_rssi_thresh = 24;
269 break;
272 if (rtlpriv->dm.undecorated_smoothed_pwdb >
273 (long)high_rssi_thresh) {
274 ra->ratr_state = DM_RATR_STA_HIGH;
275 rssi_level = 1;
276 } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
277 (long)middle_rssi_thresh) {
278 ra->ratr_state = DM_RATR_STA_LOW;
279 rssi_level = 3;
280 } else if (rtlpriv->dm.undecorated_smoothed_pwdb >
281 (long)low_rssi_thresh) {
282 ra->ratr_state = DM_RATR_STA_LOW;
283 rssi_level = 5;
284 } else {
285 ra->ratr_state = DM_RATR_STA_ULTRALOW;
286 rssi_level = 6;
289 if (ra->pre_ratr_state != ra->ratr_state) {
290 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, ("RSSI = %ld "
291 "RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
292 rtlpriv->dm.undecorated_smoothed_pwdb,
293 ra->ratr_state,
294 ra->pre_ratr_state, ra->ratr_state));
296 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
297 ra->ratr_state);
298 ra->pre_ratr_state = ra->ratr_state;
301 rcu_read_unlock();
304 static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
306 struct rtl_priv *rtlpriv = rtl_priv(hw);
307 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
308 struct rtl_phy *rtlphy = &(rtlpriv->phy);
309 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
310 bool current_mrc;
311 bool enable_mrc = true;
312 long tmpentry_maxpwdb = 0;
313 u8 rssi_a = 0;
314 u8 rssi_b = 0;
316 if (is_hal_stop(rtlhal))
317 return;
319 if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R))
320 return;
322 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
324 if (mac->link_state >= MAC80211_LINKED) {
325 if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) {
326 rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
327 rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
331 /* MRC settings would NOT affect TP on Wireless B mode. */
332 if (mac->mode != WIRELESS_MODE_B) {
333 if ((rssi_a == 0) && (rssi_b == 0)) {
334 enable_mrc = true;
335 } else if (rssi_b > 30) {
336 /* Turn on B-Path */
337 enable_mrc = true;
338 } else if (rssi_b < 5) {
339 /* Turn off B-path */
340 enable_mrc = false;
341 /* Take care of RSSI differentiation. */
342 } else if (rssi_a > 15 && (rssi_a >= rssi_b)) {
343 if ((rssi_a - rssi_b) > 15)
344 /* Turn off B-path */
345 enable_mrc = false;
346 else if ((rssi_a - rssi_b) < 10)
347 /* Turn on B-Path */
348 enable_mrc = true;
349 else
350 enable_mrc = current_mrc;
351 } else {
352 /* Turn on B-Path */
353 enable_mrc = true;
357 /* Update MRC settings if needed. */
358 if (enable_mrc != current_mrc)
359 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC,
360 (u8 *)&enable_mrc);
364 void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw)
366 struct rtl_priv *rtlpriv = rtl_priv(hw);
368 rtlpriv->dm.current_turbo_edca = false;
369 rtlpriv->dm.is_any_nonbepkts = false;
370 rtlpriv->dm.is_cur_rdlstate = false;
373 static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
375 struct rtl_priv *rtlpriv = rtl_priv(hw);
376 struct rate_adaptive *ra = &(rtlpriv->ra);
378 ra->ratr_state = DM_RATR_STA_MAX;
379 ra->pre_ratr_state = DM_RATR_STA_MAX;
381 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
382 rtlpriv->dm.useramask = true;
383 else
384 rtlpriv->dm.useramask = false;
386 rtlpriv->dm.useramask = false;
387 rtlpriv->dm.inform_fw_driverctrldm = false;
390 static void _rtl92s_dm_init_txpowertracking_thermalmeter(
391 struct ieee80211_hw *hw)
393 struct rtl_priv *rtlpriv = rtl_priv(hw);
395 rtlpriv->dm.txpower_tracking = true;
396 rtlpriv->dm.txpowercount = 0;
397 rtlpriv->dm.txpower_trackinginit = false;
400 static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
402 struct rtl_priv *rtlpriv = rtl_priv(hw);
403 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
404 u32 ret_value;
406 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
407 falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
409 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
410 falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
411 falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
412 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
413 falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
415 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
416 falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail +
417 falsealm_cnt->cnt_mcs_fail;
419 /* read CCK false alarm */
420 ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD);
421 falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff);
422 falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
423 falsealm_cnt->cnt_cck_fail;
426 static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
428 struct rtl_priv *rtlpriv = rtl_priv(hw);
429 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
431 if (falsealm_cnt->cnt_all > digtable.fa_highthresh) {
432 if ((digtable.backoff_val - 6) <
433 digtable.backoffval_range_min)
434 digtable.backoff_val = digtable.backoffval_range_min;
435 else
436 digtable.backoff_val -= 6;
437 } else if (falsealm_cnt->cnt_all < digtable.fa_lowthresh) {
438 if ((digtable.backoff_val + 6) >
439 digtable.backoffval_range_max)
440 digtable.backoff_val =
441 digtable.backoffval_range_max;
442 else
443 digtable.backoff_val += 6;
447 static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
449 struct rtl_priv *rtlpriv = rtl_priv(hw);
450 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
451 static u8 initialized, force_write;
452 u8 initial_gain = 0;
454 if ((digtable.pre_sta_connectstate == digtable.cur_sta_connectstate) ||
455 (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) {
456 if (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) {
457 if (rtlpriv->psc.rfpwr_state != ERFON)
458 return;
460 if (digtable.backoff_enable_flag == true)
461 rtl92s_backoff_enable_flag(hw);
462 else
463 digtable.backoff_val = DM_DIG_BACKOFF;
465 if ((digtable.rssi_val + 10 - digtable.backoff_val) >
466 digtable.rx_gain_range_max)
467 digtable.cur_igvalue =
468 digtable.rx_gain_range_max;
469 else if ((digtable.rssi_val + 10 - digtable.backoff_val)
470 < digtable.rx_gain_range_min)
471 digtable.cur_igvalue =
472 digtable.rx_gain_range_min;
473 else
474 digtable.cur_igvalue = digtable.rssi_val + 10 -
475 digtable.backoff_val;
477 if (falsealm_cnt->cnt_all > 10000)
478 digtable.cur_igvalue =
479 (digtable.cur_igvalue > 0x33) ?
480 digtable.cur_igvalue : 0x33;
482 if (falsealm_cnt->cnt_all > 16000)
483 digtable.cur_igvalue =
484 digtable.rx_gain_range_max;
485 /* connected -> connected or disconnected -> disconnected */
486 } else {
487 /* Firmware control DIG, do nothing in driver dm */
488 return;
490 /* disconnected -> connected or connected ->
491 * disconnected or beforeconnect->(dis)connected */
492 } else {
493 /* Enable FW DIG */
494 digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
495 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
497 digtable.backoff_val = DM_DIG_BACKOFF;
498 digtable.cur_igvalue = rtlpriv->phy.default_initialgain[0];
499 digtable.pre_igvalue = 0;
500 return;
503 /* Forced writing to prevent from fw-dig overwriting. */
504 if (digtable.pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
505 MASKBYTE0))
506 force_write = 1;
508 if ((digtable.pre_igvalue != digtable.cur_igvalue) ||
509 !initialized || force_write) {
510 /* Disable FW DIG */
511 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE);
513 initial_gain = (u8)digtable.cur_igvalue;
515 /* Set initial gain. */
516 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain);
517 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain);
518 digtable.pre_igvalue = digtable.cur_igvalue;
519 initialized = 1;
520 force_write = 0;
524 static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
526 struct rtl_priv *rtlpriv = rtl_priv(hw);
528 if (rtlpriv->mac80211.act_scanning)
529 return;
531 /* Decide the current status and if modify initial gain or not */
532 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
533 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
534 digtable.cur_sta_connectstate = DIG_STA_CONNECT;
535 else
536 digtable.cur_sta_connectstate = DIG_STA_DISCONNECT;
538 digtable.rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb;
540 /* Change dig mode to rssi */
541 if (digtable.cur_sta_connectstate != DIG_STA_DISCONNECT) {
542 if (digtable.dig_twoport_algorithm ==
543 DIG_TWO_PORT_ALGO_FALSE_ALARM) {
544 digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
545 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
549 _rtl92s_dm_false_alarm_counter_statistics(hw);
550 _rtl92s_dm_initial_gain_sta_beforeconnect(hw);
552 digtable.pre_sta_connectstate = digtable.cur_sta_connectstate;
555 static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
557 struct rtl_priv *rtlpriv = rtl_priv(hw);
558 struct rtl_phy *rtlphy = &(rtlpriv->phy);
560 /* 2T2R TP issue */
561 if (rtlphy->rf_type == RF_2T2R)
562 return;
564 if (!rtlpriv->dm.dm_initialgain_enable)
565 return;
567 if (digtable.dig_enable_flag == false)
568 return;
570 _rtl92s_dm_ctrl_initgain_bytwoport(hw);
573 static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
575 struct rtl_priv *rtlpriv = rtl_priv(hw);
576 struct rtl_phy *rtlphy = &(rtlpriv->phy);
577 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
578 long undecorated_smoothed_pwdb;
579 long txpwr_threshold_lv1, txpwr_threshold_lv2;
581 /* 2T2R TP issue */
582 if (rtlphy->rf_type == RF_2T2R)
583 return;
585 if (!rtlpriv->dm.dynamic_txpower_enable ||
586 rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
587 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
588 return;
591 if ((mac->link_state < MAC80211_LINKED) &&
592 (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
593 RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
594 ("Not connected to any\n"));
596 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
598 rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
599 return;
602 if (mac->link_state >= MAC80211_LINKED) {
603 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
604 undecorated_smoothed_pwdb =
605 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
606 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
607 ("AP Client PWDB = 0x%lx\n",
608 undecorated_smoothed_pwdb));
609 } else {
610 undecorated_smoothed_pwdb =
611 rtlpriv->dm.undecorated_smoothed_pwdb;
612 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
613 ("STA Default Port PWDB = 0x%lx\n",
614 undecorated_smoothed_pwdb));
616 } else {
617 undecorated_smoothed_pwdb =
618 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
620 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
621 ("AP Ext Port PWDB = 0x%lx\n",
622 undecorated_smoothed_pwdb));
625 txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
626 txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1;
628 if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
629 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
630 else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2)
631 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
632 else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) &&
633 (undecorated_smoothed_pwdb >= txpwr_threshold_lv1))
634 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
635 else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3))
636 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
638 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
639 rtl92s_phy_set_txpower(hw, rtlphy->current_channel);
641 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
644 static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
646 struct rtl_priv *rtlpriv = rtl_priv(hw);
648 /* Disable DIG scheme now.*/
649 digtable.dig_enable_flag = true;
650 digtable.backoff_enable_flag = true;
652 if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) &&
653 (hal_get_firmwareversion(rtlpriv) >= 0x3c))
654 digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT;
655 else
656 digtable.dig_algorithm =
657 DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
659 digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
660 digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
661 /* off=by real rssi value, on=by digtable.rssi_val for new dig */
662 digtable.dig_dbgmode = DM_DBG_OFF;
663 digtable.dig_slgorithm_switch = 0;
665 /* 2007/10/04 MH Define init gain threshol. */
666 digtable.dig_state = DM_STA_DIG_MAX;
667 digtable.dig_highpwrstate = DM_STA_DIG_MAX;
669 digtable.cur_sta_connectstate = DIG_STA_DISCONNECT;
670 digtable.pre_sta_connectstate = DIG_STA_DISCONNECT;
671 digtable.cur_ap_connectstate = DIG_AP_DISCONNECT;
672 digtable.pre_ap_connectstate = DIG_AP_DISCONNECT;
674 digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
675 digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
677 digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
678 digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
680 digtable.rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
681 digtable.rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
683 /* for dig debug rssi value */
684 digtable.rssi_val = 50;
685 digtable.backoff_val = DM_DIG_BACKOFF;
686 digtable.rx_gain_range_max = DM_DIG_MAX;
688 digtable.rx_gain_range_min = DM_DIG_MIN;
690 digtable.backoffval_range_max = DM_DIG_BACKOFF_MAX;
691 digtable.backoffval_range_min = DM_DIG_BACKOFF_MIN;
694 static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
696 struct rtl_priv *rtlpriv = rtl_priv(hw);
698 if ((hal_get_firmwareversion(rtlpriv) >= 60) &&
699 (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER))
700 rtlpriv->dm.dynamic_txpower_enable = true;
701 else
702 rtlpriv->dm.dynamic_txpower_enable = false;
704 rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
705 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
708 void rtl92s_dm_init(struct ieee80211_hw *hw)
710 struct rtl_priv *rtlpriv = rtl_priv(hw);
712 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
713 rtlpriv->dm.undecorated_smoothed_pwdb = -1;
715 _rtl92s_dm_init_dynamic_txpower(hw);
716 rtl92s_dm_init_edca_turbo(hw);
717 _rtl92s_dm_init_rate_adaptive_mask(hw);
718 _rtl92s_dm_init_txpowertracking_thermalmeter(hw);
719 _rtl92s_dm_init_dig(hw);
721 rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE);
724 void rtl92s_dm_watchdog(struct ieee80211_hw *hw)
726 _rtl92s_dm_check_edca_turbo(hw);
727 _rtl92s_dm_check_txpowertracking_thermalmeter(hw);
728 _rtl92s_dm_ctrl_initgain_byrssi(hw);
729 _rtl92s_dm_dynamic_txpower(hw);
730 _rtl92s_dm_refresh_rateadaptive_mask(hw);
731 _rtl92s_dm_switch_baseband_mrc(hw);