1739 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2012 Realtek Corporation.*/3 4#include <linux/export.h>5#include "dm_common.h"6#include "phy_common.h"7#include "../pci.h"8#include "../base.h"9#include "../core.h"10 11#define BT_RSSI_STATE_NORMAL_POWER BIT(0)12#define BT_RSSI_STATE_AMDPU_OFF BIT(1)13#define BT_RSSI_STATE_SPECIAL_LOW BIT(2)14#define BT_RSSI_STATE_BG_EDCA_LOW BIT(3)15#define BT_RSSI_STATE_TXPOWER_LOW BIT(4)16#define BT_MASK 0x00ffffff17 18#define RTLPRIV (struct rtl_priv *)19#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \20 ((RTLPRIV(_priv))->mac80211.opmode == \21 NL80211_IFTYPE_ADHOC) ? \22 ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \23 ((RTLPRIV(_priv))->dm.undec_sm_pwdb)24 25static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {26 0x7f8001fe,27 0x788001e2,28 0x71c001c7,29 0x6b8001ae,30 0x65400195,31 0x5fc0017f,32 0x5a400169,33 0x55400155,34 0x50800142,35 0x4c000130,36 0x47c0011f,37 0x43c0010f,38 0x40000100,39 0x3c8000f2,40 0x390000e4,41 0x35c000d7,42 0x32c000cb,43 0x300000c0,44 0x2d4000b5,45 0x2ac000ab,46 0x288000a2,47 0x26000098,48 0x24000090,49 0x22000088,50 0x20000080,51 0x1e400079,52 0x1c800072,53 0x1b00006c,54 0x19800066,55 0x18000060,56 0x16c0005b,57 0x15800056,58 0x14400051,59 0x1300004c,60 0x12000048,61 0x11000044,62 0x10000040,63};64 65static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {66 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},67 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},68 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},69 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},70 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},71 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},72 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},73 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},74 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},75 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},76 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},77 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},78 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},79 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},80 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},81 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},82 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},83 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},84 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},85 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},86 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},87 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},88 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},89 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},90 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},91 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},92 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},93 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},94 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},95 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},96 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},97 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},98 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}99};100 101static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {102 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},103 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},104 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},105 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},106 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},107 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},108 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},109 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},110 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},111 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},112 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},113 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},114 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},115 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},116 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},117 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},118 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},119 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},120 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},121 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},122 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},123 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},124 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},125 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},126 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},127 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},128 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},129 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},130 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},131 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},132 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},133 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},134 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}135};136 137static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};138 139void dm_restorepowerindex(struct ieee80211_hw *hw)140{141 struct rtl_priv *rtlpriv = rtl_priv(hw);142 u8 index;143 144 for (index = 0; index < 6; index++)145 rtl_write_byte(rtlpriv, power_index_reg[index],146 rtlpriv->dm.powerindex_backup[index]);147}148EXPORT_SYMBOL_GPL(dm_restorepowerindex);149 150void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)151{152 struct rtl_priv *rtlpriv = rtl_priv(hw);153 u8 index;154 155 for (index = 0; index < 6; index++)156 rtl_write_byte(rtlpriv, power_index_reg[index], value);157}158EXPORT_SYMBOL_GPL(dm_writepowerindex);159 160void dm_savepowerindex(struct ieee80211_hw *hw)161{162 struct rtl_priv *rtlpriv = rtl_priv(hw);163 u8 index;164 u8 tmp;165 166 for (index = 0; index < 6; index++) {167 tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);168 rtlpriv->dm.powerindex_backup[index] = tmp;169 }170}171EXPORT_SYMBOL_GPL(dm_savepowerindex);172 173static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)174{175 struct rtl_priv *rtlpriv = rtl_priv(hw);176 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;177 long rssi_val_min = 0;178 179 if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&180 (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {181 if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)182 rssi_val_min =183 (rtlpriv->dm.entry_min_undec_sm_pwdb >184 rtlpriv->dm.undec_sm_pwdb) ?185 rtlpriv->dm.undec_sm_pwdb :186 rtlpriv->dm.entry_min_undec_sm_pwdb;187 else188 rssi_val_min = rtlpriv->dm.undec_sm_pwdb;189 } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||190 dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {191 rssi_val_min = rtlpriv->dm.undec_sm_pwdb;192 } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {193 rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;194 }195 196 if (rssi_val_min > 100)197 rssi_val_min = 100;198 return (u8)rssi_val_min;199}200 201static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)202{203 u32 ret_value;204 struct rtl_priv *rtlpriv = rtl_priv(hw);205 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);206 207 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);208 falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);209 210 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);211 falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);212 falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);213 214 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);215 falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);216 217 ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);218 falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);219 falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);220 221 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +222 falsealm_cnt->cnt_rate_illegal +223 falsealm_cnt->cnt_crc8_fail +224 falsealm_cnt->cnt_mcs_fail +225 falsealm_cnt->cnt_fast_fsync_fail +226 falsealm_cnt->cnt_sb_search_fail;227 228 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);229 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);230 falsealm_cnt->cnt_cck_fail = ret_value;231 232 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);233 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;234 falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +235 falsealm_cnt->cnt_rate_illegal +236 falsealm_cnt->cnt_crc8_fail +237 falsealm_cnt->cnt_mcs_fail +238 falsealm_cnt->cnt_cck_fail);239 240 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);241 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);242 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);243 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);244 245 rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,246 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",247 falsealm_cnt->cnt_parity_fail,248 falsealm_cnt->cnt_rate_illegal,249 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);250 251 rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,252 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",253 falsealm_cnt->cnt_ofdm_fail,254 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);255}256 257static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)258{259 struct rtl_priv *rtlpriv = rtl_priv(hw);260 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;261 u8 value_igi = dm_digtable->cur_igvalue;262 263 if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)264 value_igi--;265 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)266 value_igi += 0;267 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)268 value_igi++;269 else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)270 value_igi += 2;271 272 if (value_igi > DM_DIG_FA_UPPER)273 value_igi = DM_DIG_FA_UPPER;274 else if (value_igi < DM_DIG_FA_LOWER)275 value_igi = DM_DIG_FA_LOWER;276 277 if (rtlpriv->falsealm_cnt.cnt_all > 10000)278 value_igi = DM_DIG_FA_UPPER;279 280 dm_digtable->cur_igvalue = value_igi;281 rtl92c_dm_write_dig(hw);282}283 284static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)285{286 struct rtl_priv *rtlpriv = rtl_priv(hw);287 struct dig_t *digtable = &rtlpriv->dm_digtable;288 u32 isbt;289 290 /* modify DIG lower bound, deal with abnormally large false alarm */291 if (rtlpriv->falsealm_cnt.cnt_all > 10000) {292 digtable->large_fa_hit++;293 if (digtable->forbidden_igi < digtable->cur_igvalue) {294 digtable->forbidden_igi = digtable->cur_igvalue;295 digtable->large_fa_hit = 1;296 }297 298 if (digtable->large_fa_hit >= 3) {299 if ((digtable->forbidden_igi + 1) >300 digtable->rx_gain_max)301 digtable->rx_gain_min = digtable->rx_gain_max;302 else303 digtable->rx_gain_min = (digtable->forbidden_igi + 1);304 digtable->recover_cnt = 3600; /* 3600=2hr */305 }306 } else {307 /* Recovery mechanism for IGI lower bound */308 if (digtable->recover_cnt != 0) {309 digtable->recover_cnt--;310 } else {311 if (digtable->large_fa_hit == 0) {312 if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {313 digtable->forbidden_igi = DM_DIG_MIN;314 digtable->rx_gain_min = DM_DIG_MIN;315 } else {316 digtable->forbidden_igi--;317 digtable->rx_gain_min = digtable->forbidden_igi + 1;318 }319 } else if (digtable->large_fa_hit == 3) {320 digtable->large_fa_hit = 0;321 }322 }323 }324 if (rtlpriv->falsealm_cnt.cnt_all < 250) {325 isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;326 327 if (!isbt) {328 if (rtlpriv->falsealm_cnt.cnt_all >329 digtable->fa_lowthresh) {330 if ((digtable->back_val - 2) <331 digtable->back_range_min)332 digtable->back_val = digtable->back_range_min;333 else334 digtable->back_val -= 2;335 } else if (rtlpriv->falsealm_cnt.cnt_all <336 digtable->fa_lowthresh) {337 if ((digtable->back_val + 2) >338 digtable->back_range_max)339 digtable->back_val = digtable->back_range_max;340 else341 digtable->back_val += 2;342 }343 } else {344 digtable->back_val = DM_DIG_BACKOFF_DEFAULT;345 }346 } else {347 /* Adjust initial gain by false alarm */348 if (rtlpriv->falsealm_cnt.cnt_all > 1000)349 digtable->cur_igvalue = digtable->pre_igvalue + 2;350 else if (rtlpriv->falsealm_cnt.cnt_all > 750)351 digtable->cur_igvalue = digtable->pre_igvalue + 1;352 else if (rtlpriv->falsealm_cnt.cnt_all < 500)353 digtable->cur_igvalue = digtable->pre_igvalue - 1;354 }355 356 /* Check initial gain by upper/lower bound */357 if (digtable->cur_igvalue > digtable->rx_gain_max)358 digtable->cur_igvalue = digtable->rx_gain_max;359 360 if (digtable->cur_igvalue < digtable->rx_gain_min)361 digtable->cur_igvalue = digtable->rx_gain_min;362 363 rtl92c_dm_write_dig(hw);364}365 366static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)367{368 static u8 initialized; /* initialized to false */369 struct rtl_priv *rtlpriv = rtl_priv(hw);370 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;371 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));372 long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;373 bool multi_sta = false;374 375 if (mac->opmode == NL80211_IFTYPE_ADHOC)376 multi_sta = true;377 378 if (!multi_sta ||379 dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {380 initialized = false;381 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;382 return;383 } else if (!initialized) {384 initialized = true;385 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;386 dm_digtable->cur_igvalue = 0x20;387 rtl92c_dm_write_dig(hw);388 }389 390 if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {391 if ((rssi_strength < dm_digtable->rssi_lowthresh) &&392 (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {393 394 if (dm_digtable->dig_ext_port_stage ==395 DIG_EXT_PORT_STAGE_2) {396 dm_digtable->cur_igvalue = 0x20;397 rtl92c_dm_write_dig(hw);398 }399 400 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;401 } else if (rssi_strength > dm_digtable->rssi_highthresh) {402 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;403 rtl92c_dm_ctrl_initgain_by_fa(hw);404 }405 } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {406 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;407 dm_digtable->cur_igvalue = 0x20;408 rtl92c_dm_write_dig(hw);409 }410 411 rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,412 "curmultista_cstate = %x dig_ext_port_stage %x\n",413 dm_digtable->curmultista_cstate,414 dm_digtable->dig_ext_port_stage);415}416 417static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)418{419 struct rtl_priv *rtlpriv = rtl_priv(hw);420 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;421 422 rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,423 "presta_cstate = %x, cursta_cstate = %x\n",424 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);425 if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||426 dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||427 dm_digtable->cursta_cstate == DIG_STA_CONNECT) {428 if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {429 dm_digtable->rssi_val_min =430 rtl92c_dm_initial_gain_min_pwdb(hw);431 if (dm_digtable->rssi_val_min > 100)432 dm_digtable->rssi_val_min = 100;433 rtl92c_dm_ctrl_initgain_by_rssi(hw);434 }435 } else {436 dm_digtable->rssi_val_min = 0;437 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;438 dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;439 dm_digtable->cur_igvalue = 0x20;440 dm_digtable->pre_igvalue = 0;441 rtl92c_dm_write_dig(hw);442 }443}444 445static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)446{447 struct rtl_priv *rtlpriv = rtl_priv(hw);448 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;449 450 if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {451 dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);452 if (dm_digtable->rssi_val_min > 100)453 dm_digtable->rssi_val_min = 100;454 455 if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {456 if (dm_digtable->rssi_val_min <= 25)457 dm_digtable->cur_cck_pd_state =458 CCK_PD_STAGE_LOWRSSI;459 else460 dm_digtable->cur_cck_pd_state =461 CCK_PD_STAGE_HIGHRSSI;462 } else {463 if (dm_digtable->rssi_val_min <= 20)464 dm_digtable->cur_cck_pd_state =465 CCK_PD_STAGE_LOWRSSI;466 else467 dm_digtable->cur_cck_pd_state =468 CCK_PD_STAGE_HIGHRSSI;469 }470 } else {471 dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;472 }473 474 if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {475 if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) ||476 (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))477 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);478 else479 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);480 481 dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;482 }483}484 485static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)486{487 struct rtl_priv *rtlpriv = rtl_priv(hw);488 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;489 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));490 491 if (mac->act_scanning)492 return;493 494 if (mac->link_state >= MAC80211_LINKED)495 dm_digtable->cursta_cstate = DIG_STA_CONNECT;496 else497 dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;498 499 dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;500 501 rtl92c_dm_initial_gain_sta(hw);502 rtl92c_dm_initial_gain_multi_sta(hw);503 rtl92c_dm_cck_packet_detection_thresh(hw);504 505 dm_digtable->presta_cstate = dm_digtable->cursta_cstate;506}507 508static void rtl92c_dm_dig(struct ieee80211_hw *hw)509{510 struct rtl_priv *rtlpriv = rtl_priv(hw);511 512 if (!rtlpriv->dm.dm_initialgain_enable)513 return;514 if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))515 return;516 517 rtl92c_dm_ctrl_initgain_by_twoport(hw);518}519 520static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)521{522 struct rtl_priv *rtlpriv = rtl_priv(hw);523 524 if (rtlpriv->rtlhal.interface == INTF_USB &&525 rtlpriv->rtlhal.board_type & 0x1) {526 dm_savepowerindex(hw);527 rtlpriv->dm.dynamic_txpower_enable = true;528 } else {529 rtlpriv->dm.dynamic_txpower_enable = false;530 }531 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;532 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;533}534 535void rtl92c_dm_write_dig(struct ieee80211_hw *hw)536{537 struct rtl_priv *rtlpriv = rtl_priv(hw);538 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;539 540 rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,541 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",542 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,543 dm_digtable->back_val);544 545 if (rtlpriv->rtlhal.interface == INTF_USB &&546 !dm_digtable->dig_enable_flag) {547 dm_digtable->pre_igvalue = 0x17;548 return;549 }550 dm_digtable->cur_igvalue -= 1;551 if (dm_digtable->cur_igvalue < DM_DIG_MIN)552 dm_digtable->cur_igvalue = DM_DIG_MIN;553 554 if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {555 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,556 dm_digtable->cur_igvalue);557 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,558 dm_digtable->cur_igvalue);559 560 dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;561 }562 rtl_dbg(rtlpriv, COMP_DIG, DBG_WARNING,563 "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",564 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,565 dm_digtable->rssi_val_min, dm_digtable->back_val,566 dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,567 dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);568}569EXPORT_SYMBOL(rtl92c_dm_write_dig);570 571static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)572{573 struct rtl_priv *rtlpriv = rtl_priv(hw);574 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));575 long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;576 577 if (mac->link_state != MAC80211_LINKED)578 return;579 580 if (mac->opmode == NL80211_IFTYPE_ADHOC ||581 mac->opmode == NL80211_IFTYPE_AP) {582 /* TODO: Handle ADHOC and AP Mode */583 }584 585 if (tmpentry_max_pwdb != 0)586 rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;587 else588 rtlpriv->dm.entry_max_undec_sm_pwdb = 0;589 590 if (tmpentry_min_pwdb != 0xff)591 rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;592 else593 rtlpriv->dm.entry_min_undec_sm_pwdb = 0;594 595/* TODO:596 * if (mac->opmode == NL80211_IFTYPE_STATION) {597 * if (rtlpriv->rtlhal.fw_ready) {598 * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);599 * rtl8192c_set_rssi_cmd(hw, param);600 * }601 * }602 */603}604 605void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)606{607 struct rtl_priv *rtlpriv = rtl_priv(hw);608 609 rtlpriv->dm.current_turbo_edca = false;610 rtlpriv->dm.is_any_nonbepkts = false;611 rtlpriv->dm.is_cur_rdlstate = false;612}613EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);614 615static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)616{617 struct rtl_priv *rtlpriv = rtl_priv(hw);618 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));619 620 static u64 last_txok_cnt;621 static u64 last_rxok_cnt;622 static u32 last_bt_edca_ul;623 static u32 last_bt_edca_dl;624 u64 cur_txok_cnt = 0;625 u64 cur_rxok_cnt = 0;626 u32 edca_be_ul = 0x5ea42b;627 u32 edca_be_dl = 0x5ea42b;628 bool bt_change_edca = false;629 630 if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||631 (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {632 rtlpriv->dm.current_turbo_edca = false;633 last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;634 last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;635 }636 637 if (rtlpriv->btcoexist.bt_edca_ul != 0) {638 edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;639 bt_change_edca = true;640 }641 642 if (rtlpriv->btcoexist.bt_edca_dl != 0) {643 edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;644 bt_change_edca = true;645 }646 647 if (mac->link_state != MAC80211_LINKED) {648 rtlpriv->dm.current_turbo_edca = false;649 return;650 }651 652 if ((!mac->ht_enable) && (!rtlpriv->btcoexist.bt_coexistence)) {653 if (!(edca_be_ul & 0xffff0000))654 edca_be_ul |= 0x005e0000;655 656 if (!(edca_be_dl & 0xffff0000))657 edca_be_dl |= 0x005e0000;658 }659 660 if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&661 (!rtlpriv->dm.disable_framebursting))) {662 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;663 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;664 665 if (cur_rxok_cnt > 4 * cur_txok_cnt) {666 if (!rtlpriv->dm.is_cur_rdlstate ||667 !rtlpriv->dm.current_turbo_edca) {668 rtl_write_dword(rtlpriv,669 REG_EDCA_BE_PARAM,670 edca_be_dl);671 rtlpriv->dm.is_cur_rdlstate = true;672 }673 } else {674 if (rtlpriv->dm.is_cur_rdlstate ||675 !rtlpriv->dm.current_turbo_edca) {676 rtl_write_dword(rtlpriv,677 REG_EDCA_BE_PARAM,678 edca_be_ul);679 rtlpriv->dm.is_cur_rdlstate = false;680 }681 }682 rtlpriv->dm.current_turbo_edca = true;683 } else {684 if (rtlpriv->dm.current_turbo_edca) {685 u8 tmp = AC0_BE;686 687 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,688 &tmp);689 rtlpriv->dm.current_turbo_edca = false;690 }691 }692 693 rtlpriv->dm.is_any_nonbepkts = false;694 last_txok_cnt = rtlpriv->stats.txbytesunicast;695 last_rxok_cnt = rtlpriv->stats.rxbytesunicast;696}697 698static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw699 *hw)700{701 struct rtl_priv *rtlpriv = rtl_priv(hw);702 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));703 struct rtl_phy *rtlphy = &(rtlpriv->phy);704 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));705 u8 thermalvalue, delta, delta_lck, delta_iqk;706 long ele_a, ele_d, temp_cck, val_x, value32;707 long val_y, ele_c = 0;708 u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;709 s8 cck_index = 0;710 int i;711 bool is2t = IS_92C_SERIAL(rtlhal->version);712 s8 txpwr_level[3] = {0, 0, 0};713 u8 ofdm_min_index = 6, rf;714 715 rtlpriv->dm.txpower_trackinginit = true;716 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,717 "%s\n", __func__);718 719 thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);720 721 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,722 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",723 thermalvalue, rtlpriv->dm.thermalvalue,724 rtlefuse->eeprom_thermalmeter);725 726 rtl92c_phy_ap_calibrate(hw, (thermalvalue -727 rtlefuse->eeprom_thermalmeter));728 if (is2t)729 rf = 2;730 else731 rf = 1;732 733 if (thermalvalue) {734 ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,735 MASKDWORD) & MASKOFDM_D;736 737 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {738 if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {739 ofdm_index_old[0] = (u8) i;740 741 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,742 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",743 ROFDM0_XATXIQIMBALANCE,744 ele_d, ofdm_index_old[0]);745 break;746 }747 }748 749 if (is2t) {750 ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,751 MASKDWORD) & MASKOFDM_D;752 753 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {754 if (ele_d == (ofdmswing_table[i] &755 MASKOFDM_D)) {756 ofdm_index_old[1] = (u8) i;757 rtl_dbg(rtlpriv, COMP_POWER_TRACKING,758 DBG_LOUD,759 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",760 ROFDM0_XBTXIQIMBALANCE, ele_d,761 ofdm_index_old[1]);762 break;763 }764 }765 }766 767 temp_cck =768 rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;769 770 for (i = 0; i < CCK_TABLE_LENGTH; i++) {771 if (rtlpriv->dm.cck_inch14) {772 if (memcmp((void *)&temp_cck,773 (void *)&cckswing_table_ch14[i][2],774 4) == 0) {775 cck_index_old = (u8) i;776 777 rtl_dbg(rtlpriv, COMP_POWER_TRACKING,778 DBG_LOUD,779 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",780 RCCK0_TXFILTER2, temp_cck,781 cck_index_old,782 rtlpriv->dm.cck_inch14);783 break;784 }785 } else {786 if (memcmp((void *)&temp_cck,787 (void *)788 &cckswing_table_ch1ch13[i][2],789 4) == 0) {790 cck_index_old = (u8) i;791 792 rtl_dbg(rtlpriv, COMP_POWER_TRACKING,793 DBG_LOUD,794 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",795 RCCK0_TXFILTER2, temp_cck,796 cck_index_old,797 rtlpriv->dm.cck_inch14);798 break;799 }800 }801 }802 803 if (!rtlpriv->dm.thermalvalue) {804 rtlpriv->dm.thermalvalue =805 rtlefuse->eeprom_thermalmeter;806 rtlpriv->dm.thermalvalue_lck = thermalvalue;807 rtlpriv->dm.thermalvalue_iqk = thermalvalue;808 for (i = 0; i < rf; i++)809 rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];810 rtlpriv->dm.cck_index = cck_index_old;811 }812 /* Handle USB High PA boards */813 814 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?815 (thermalvalue - rtlpriv->dm.thermalvalue) :816 (rtlpriv->dm.thermalvalue - thermalvalue);817 818 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?819 (thermalvalue - rtlpriv->dm.thermalvalue_lck) :820 (rtlpriv->dm.thermalvalue_lck - thermalvalue);821 822 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?823 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :824 (rtlpriv->dm.thermalvalue_iqk - thermalvalue);825 826 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,827 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n",828 thermalvalue, rtlpriv->dm.thermalvalue,829 rtlefuse->eeprom_thermalmeter, delta, delta_lck,830 delta_iqk);831 832 if (delta_lck > 1) {833 rtlpriv->dm.thermalvalue_lck = thermalvalue;834 rtl92c_phy_lc_calibrate(hw);835 }836 837 if (delta > 0 && rtlpriv->dm.txpower_track_control) {838 if (thermalvalue > rtlpriv->dm.thermalvalue) {839 for (i = 0; i < rf; i++)840 rtlpriv->dm.ofdm_index[i] -= delta;841 rtlpriv->dm.cck_index -= delta;842 } else {843 for (i = 0; i < rf; i++)844 rtlpriv->dm.ofdm_index[i] += delta;845 rtlpriv->dm.cck_index += delta;846 }847 848 if (is2t) {849 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,850 "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",851 rtlpriv->dm.ofdm_index[0],852 rtlpriv->dm.ofdm_index[1],853 rtlpriv->dm.cck_index);854 } else {855 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,856 "temp OFDM_A_index=0x%x, cck_index=0x%x\n",857 rtlpriv->dm.ofdm_index[0],858 rtlpriv->dm.cck_index);859 }860 861 if (thermalvalue > rtlefuse->eeprom_thermalmeter) {862 for (i = 0; i < rf; i++)863 ofdm_index[i] =864 rtlpriv->dm.ofdm_index[i]865 + 1;866 cck_index = rtlpriv->dm.cck_index + 1;867 } else {868 for (i = 0; i < rf; i++)869 ofdm_index[i] =870 rtlpriv->dm.ofdm_index[i];871 cck_index = rtlpriv->dm.cck_index;872 }873 874 for (i = 0; i < rf; i++) {875 if (txpwr_level[i] >= 0 &&876 txpwr_level[i] <= 26) {877 if (thermalvalue >878 rtlefuse->eeprom_thermalmeter) {879 if (delta < 5)880 ofdm_index[i] -= 1;881 882 else883 ofdm_index[i] -= 2;884 } else if (delta > 5 && thermalvalue <885 rtlefuse->886 eeprom_thermalmeter) {887 ofdm_index[i] += 1;888 }889 } else if (txpwr_level[i] >= 27 &&890 txpwr_level[i] <= 32891 && thermalvalue >892 rtlefuse->eeprom_thermalmeter) {893 if (delta < 5)894 ofdm_index[i] -= 1;895 896 else897 ofdm_index[i] -= 2;898 } else if (txpwr_level[i] >= 32 &&899 txpwr_level[i] <= 38 &&900 thermalvalue >901 rtlefuse->eeprom_thermalmeter902 && delta > 5) {903 ofdm_index[i] -= 1;904 }905 }906 907 if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {908 if (thermalvalue >909 rtlefuse->eeprom_thermalmeter) {910 if (delta < 5)911 cck_index -= 1;912 913 else914 cck_index -= 2;915 } else if (delta > 5 && thermalvalue <916 rtlefuse->eeprom_thermalmeter) {917 cck_index += 1;918 }919 } else if (txpwr_level[i] >= 27 &&920 txpwr_level[i] <= 32 &&921 thermalvalue >922 rtlefuse->eeprom_thermalmeter) {923 if (delta < 5)924 cck_index -= 1;925 926 else927 cck_index -= 2;928 } else if (txpwr_level[i] >= 32 &&929 txpwr_level[i] <= 38 &&930 thermalvalue > rtlefuse->eeprom_thermalmeter931 && delta > 5) {932 cck_index -= 1;933 }934 935 for (i = 0; i < rf; i++) {936 if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)937 ofdm_index[i] = OFDM_TABLE_SIZE - 1;938 939 else if (ofdm_index[i] < ofdm_min_index)940 ofdm_index[i] = ofdm_min_index;941 }942 943 if (cck_index > CCK_TABLE_SIZE - 1)944 cck_index = CCK_TABLE_SIZE - 1;945 else if (cck_index < 0)946 cck_index = 0;947 948 if (is2t) {949 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,950 "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",951 ofdm_index[0], ofdm_index[1],952 cck_index);953 } else {954 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,955 "new OFDM_A_index=0x%x, cck_index=0x%x\n",956 ofdm_index[0], cck_index);957 }958 }959 960 if (rtlpriv->dm.txpower_track_control && delta != 0) {961 ele_d =962 (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;963 val_x = rtlphy->reg_e94;964 val_y = rtlphy->reg_e9c;965 966 if (val_x != 0) {967 if ((val_x & 0x00000200) != 0)968 val_x = val_x | 0xFFFFFC00;969 ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;970 971 if ((val_y & 0x00000200) != 0)972 val_y = val_y | 0xFFFFFC00;973 ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;974 975 value32 = (ele_d << 22) |976 ((ele_c & 0x3F) << 16) | ele_a;977 978 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,979 MASKDWORD, value32);980 981 value32 = (ele_c & 0x000003C0) >> 6;982 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,983 value32);984 985 value32 = ((val_x * ele_d) >> 7) & 0x01;986 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,987 BIT(31), value32);988 989 value32 = ((val_y * ele_d) >> 7) & 0x01;990 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,991 BIT(29), value32);992 } else {993 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,994 MASKDWORD,995 ofdmswing_table[ofdm_index[0]]);996 997 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,998 0x00);999 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,1000 BIT(31) | BIT(29), 0x00);1001 }1002 1003 if (!rtlpriv->dm.cck_inch14) {1004 rtl_write_byte(rtlpriv, 0xa22,1005 cckswing_table_ch1ch13[cck_index]1006 [0]);1007 rtl_write_byte(rtlpriv, 0xa23,1008 cckswing_table_ch1ch13[cck_index]1009 [1]);1010 rtl_write_byte(rtlpriv, 0xa24,1011 cckswing_table_ch1ch13[cck_index]1012 [2]);1013 rtl_write_byte(rtlpriv, 0xa25,1014 cckswing_table_ch1ch13[cck_index]1015 [3]);1016 rtl_write_byte(rtlpriv, 0xa26,1017 cckswing_table_ch1ch13[cck_index]1018 [4]);1019 rtl_write_byte(rtlpriv, 0xa27,1020 cckswing_table_ch1ch13[cck_index]1021 [5]);1022 rtl_write_byte(rtlpriv, 0xa28,1023 cckswing_table_ch1ch13[cck_index]1024 [6]);1025 rtl_write_byte(rtlpriv, 0xa29,1026 cckswing_table_ch1ch13[cck_index]1027 [7]);1028 } else {1029 rtl_write_byte(rtlpriv, 0xa22,1030 cckswing_table_ch14[cck_index]1031 [0]);1032 rtl_write_byte(rtlpriv, 0xa23,1033 cckswing_table_ch14[cck_index]1034 [1]);1035 rtl_write_byte(rtlpriv, 0xa24,1036 cckswing_table_ch14[cck_index]1037 [2]);1038 rtl_write_byte(rtlpriv, 0xa25,1039 cckswing_table_ch14[cck_index]1040 [3]);1041 rtl_write_byte(rtlpriv, 0xa26,1042 cckswing_table_ch14[cck_index]1043 [4]);1044 rtl_write_byte(rtlpriv, 0xa27,1045 cckswing_table_ch14[cck_index]1046 [5]);1047 rtl_write_byte(rtlpriv, 0xa28,1048 cckswing_table_ch14[cck_index]1049 [6]);1050 rtl_write_byte(rtlpriv, 0xa29,1051 cckswing_table_ch14[cck_index]1052 [7]);1053 }1054 1055 if (is2t) {1056 ele_d = (ofdmswing_table[ofdm_index[1]] &1057 0xFFC00000) >> 22;1058 1059 val_x = rtlphy->reg_eb4;1060 val_y = rtlphy->reg_ebc;1061 1062 if (val_x != 0) {1063 if ((val_x & 0x00000200) != 0)1064 val_x = val_x | 0xFFFFFC00;1065 ele_a = ((val_x * ele_d) >> 8) &1066 0x000003FF;1067 1068 if ((val_y & 0x00000200) != 0)1069 val_y = val_y | 0xFFFFFC00;1070 ele_c = ((val_y * ele_d) >> 8) &1071 0x00003FF;1072 1073 value32 = (ele_d << 22) |1074 ((ele_c & 0x3F) << 16) | ele_a;1075 rtl_set_bbreg(hw,1076 ROFDM0_XBTXIQIMBALANCE,1077 MASKDWORD, value32);1078 1079 value32 = (ele_c & 0x000003C0) >> 6;1080 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,1081 MASKH4BITS, value32);1082 1083 value32 = ((val_x * ele_d) >> 7) & 0x01;1084 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,1085 BIT(27), value32);1086 1087 value32 = ((val_y * ele_d) >> 7) & 0x01;1088 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,1089 BIT(25), value32);1090 } else {1091 rtl_set_bbreg(hw,1092 ROFDM0_XBTXIQIMBALANCE,1093 MASKDWORD,1094 ofdmswing_table[ofdm_index1095 [1]]);1096 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,1097 MASKH4BITS, 0x00);1098 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,1099 BIT(27) | BIT(25), 0x00);1100 }1101 1102 }1103 }1104 1105 if (delta_iqk > 3) {1106 rtlpriv->dm.thermalvalue_iqk = thermalvalue;1107 rtl92c_phy_iq_calibrate(hw, false);1108 }1109 1110 if (rtlpriv->dm.txpower_track_control)1111 rtlpriv->dm.thermalvalue = thermalvalue;1112 }1113 1114 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");1115 1116}1117 1118static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(1119 struct ieee80211_hw *hw)1120{1121 struct rtl_priv *rtlpriv = rtl_priv(hw);1122 1123 rtlpriv->dm.txpower_tracking = true;1124 rtlpriv->dm.txpower_trackinginit = false;1125 1126 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,1127 "pMgntInfo->txpower_tracking = %d\n",1128 rtlpriv->dm.txpower_tracking);1129}1130 1131static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)1132{1133 rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);1134}1135 1136static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)1137{1138 rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);1139}1140 1141static void rtl92c_dm_check_txpower_tracking_thermal_meter(1142 struct ieee80211_hw *hw)1143{1144 struct rtl_priv *rtlpriv = rtl_priv(hw);1145 1146 if (!rtlpriv->dm.txpower_tracking)1147 return;1148 1149 if (!rtlpriv->dm.tm_trigger) {1150 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,1151 0x60);1152 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,1153 "Trigger 92S Thermal Meter!!\n");1154 rtlpriv->dm.tm_trigger = 1;1155 return;1156 } else {1157 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,1158 "Schedule TxPowerTracking direct call!!\n");1159 rtl92c_dm_txpower_tracking_directcall(hw);1160 rtlpriv->dm.tm_trigger = 0;1161 }1162}1163 1164void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)1165{1166 rtl92c_dm_check_txpower_tracking_thermal_meter(hw);1167}1168EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);1169 1170void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)1171{1172 struct rtl_priv *rtlpriv = rtl_priv(hw);1173 struct rate_adaptive *p_ra = &(rtlpriv->ra);1174 1175 p_ra->ratr_state = DM_RATR_STA_INIT;1176 p_ra->pre_ratr_state = DM_RATR_STA_INIT;1177 1178 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)1179 rtlpriv->dm.useramask = true;1180 else1181 rtlpriv->dm.useramask = false;1182 1183}1184EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);1185 1186static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)1187{1188 struct rtl_priv *rtlpriv = rtl_priv(hw);1189 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;1190 1191 dm_pstable->pre_ccastate = CCA_MAX;1192 dm_pstable->cur_ccasate = CCA_MAX;1193 dm_pstable->pre_rfstate = RF_MAX;1194 dm_pstable->cur_rfstate = RF_MAX;1195 dm_pstable->rssi_val_min = 0;1196}1197 1198void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)1199{1200 struct rtl_priv *rtlpriv = rtl_priv(hw);1201 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;1202 1203 if (!rtlpriv->reg_init) {1204 rtlpriv->reg_874 = (rtl_get_bbreg(hw,1205 RFPGA0_XCD_RFINTERFACESW,1206 MASKDWORD) & 0x1CC000) >> 14;1207 1208 rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,1209 MASKDWORD) & BIT(3)) >> 3;1210 1211 rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,1212 MASKDWORD) & 0xFF000000) >> 24;1213 1214 rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &1215 0xF000) >> 12;1216 1217 rtlpriv->reg_init = true;1218 }1219 1220 if (!bforce_in_normal) {1221 if (dm_pstable->rssi_val_min != 0) {1222 if (dm_pstable->pre_rfstate == RF_NORMAL) {1223 if (dm_pstable->rssi_val_min >= 30)1224 dm_pstable->cur_rfstate = RF_SAVE;1225 else1226 dm_pstable->cur_rfstate = RF_NORMAL;1227 } else {1228 if (dm_pstable->rssi_val_min <= 25)1229 dm_pstable->cur_rfstate = RF_NORMAL;1230 else1231 dm_pstable->cur_rfstate = RF_SAVE;1232 }1233 } else {1234 dm_pstable->cur_rfstate = RF_MAX;1235 }1236 } else {1237 dm_pstable->cur_rfstate = RF_NORMAL;1238 }1239 1240 if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {1241 if (dm_pstable->cur_rfstate == RF_SAVE) {1242 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,1243 0x1C0000, 0x2);1244 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);1245 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,1246 0xFF000000, 0x63);1247 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,1248 0xC000, 0x2);1249 rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);1250 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);1251 rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);1252 } else {1253 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,1254 0x1CC000, rtlpriv->reg_874);1255 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),1256 rtlpriv->reg_c70);1257 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,1258 rtlpriv->reg_85c);1259 rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);1260 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);1261 }1262 1263 dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;1264 }1265}1266EXPORT_SYMBOL(rtl92c_dm_rf_saving);1267 1268static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)1269{1270 struct rtl_priv *rtlpriv = rtl_priv(hw);1271 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;1272 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));1273 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));1274 1275 /* Determine the minimum RSSI */1276 if (((mac->link_state == MAC80211_NOLINK)) &&1277 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {1278 dm_pstable->rssi_val_min = 0;1279 rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");1280 }1281 1282 if (mac->link_state == MAC80211_LINKED) {1283 if (mac->opmode == NL80211_IFTYPE_ADHOC) {1284 dm_pstable->rssi_val_min =1285 rtlpriv->dm.entry_min_undec_sm_pwdb;1286 rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,1287 "AP Client PWDB = 0x%lx\n",1288 dm_pstable->rssi_val_min);1289 } else {1290 dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;1291 rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,1292 "STA Default Port PWDB = 0x%lx\n",1293 dm_pstable->rssi_val_min);1294 }1295 } else {1296 dm_pstable->rssi_val_min =1297 rtlpriv->dm.entry_min_undec_sm_pwdb;1298 1299 rtl_dbg(rtlpriv, DBG_LOUD, DBG_LOUD,1300 "AP Ext Port PWDB = 0x%lx\n",1301 dm_pstable->rssi_val_min);1302 }1303 1304 /* Power Saving for 92C */1305 if (IS_92C_SERIAL(rtlhal->version))1306 ;/* rtl92c_dm_1r_cca(hw); */1307 else1308 rtl92c_dm_rf_saving(hw, false);1309}1310 1311void rtl92c_dm_init(struct ieee80211_hw *hw)1312{1313 struct rtl_priv *rtlpriv = rtl_priv(hw);1314 1315 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;1316 rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;1317 rtlpriv->dm.undec_sm_pwdb = -1;1318 rtlpriv->dm.undec_sm_cck = -1;1319 rtlpriv->dm.dm_initialgain_enable = true;1320 rtl_dm_diginit(hw, 0x20);1321 1322 rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;1323 rtl92c_dm_init_dynamic_txpower(hw);1324 1325 rtl92c_dm_init_edca_turbo(hw);1326 rtl92c_dm_init_rate_adaptive_mask(hw);1327 rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;1328 rtl92c_dm_initialize_txpower_tracking(hw);1329 rtl92c_dm_init_dynamic_bb_powersaving(hw);1330 1331 rtlpriv->dm.ofdm_pkt_cnt = 0;1332 rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;1333}1334EXPORT_SYMBOL(rtl92c_dm_init);1335 1336void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)1337{1338 struct rtl_priv *rtlpriv = rtl_priv(hw);1339 struct rtl_phy *rtlphy = &(rtlpriv->phy);1340 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));1341 long undec_sm_pwdb;1342 1343 if (!rtlpriv->dm.dynamic_txpower_enable)1344 return;1345 1346 if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {1347 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;1348 return;1349 }1350 1351 if ((mac->link_state < MAC80211_LINKED) &&1352 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {1353 rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,1354 "Not connected to any\n");1355 1356 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;1357 1358 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;1359 return;1360 }1361 1362 if (mac->link_state >= MAC80211_LINKED) {1363 if (mac->opmode == NL80211_IFTYPE_ADHOC) {1364 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;1365 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1366 "AP Client PWDB = 0x%lx\n",1367 undec_sm_pwdb);1368 } else {1369 undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;1370 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1371 "STA Default Port PWDB = 0x%lx\n",1372 undec_sm_pwdb);1373 }1374 } else {1375 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;1376 1377 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1378 "AP Ext Port PWDB = 0x%lx\n",1379 undec_sm_pwdb);1380 }1381 1382 if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {1383 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;1384 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1385 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");1386 } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&1387 (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {1388 1389 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;1390 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1391 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");1392 } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {1393 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;1394 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1395 "TXHIGHPWRLEVEL_NORMAL\n");1396 }1397 1398 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {1399 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,1400 "PHY_SetTxPowerLevel8192S() Channel = %d\n",1401 rtlphy->current_channel);1402 rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);1403 if (rtlpriv->dm.dynamic_txhighpower_lvl ==1404 TXHIGHPWRLEVEL_NORMAL)1405 dm_restorepowerindex(hw);1406 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==1407 TXHIGHPWRLEVEL_LEVEL1)1408 dm_writepowerindex(hw, 0x14);1409 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==1410 TXHIGHPWRLEVEL_LEVEL2)1411 dm_writepowerindex(hw, 0x10);1412 }1413 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;1414}1415 1416void rtl92c_dm_watchdog(struct ieee80211_hw *hw)1417{1418 struct rtl_priv *rtlpriv = rtl_priv(hw);1419 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));1420 bool fw_current_inpsmode = false;1421 bool fw_ps_awake = true;1422 1423 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,1424 (u8 *) (&fw_current_inpsmode));1425 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,1426 (u8 *) (&fw_ps_awake));1427 1428 if (ppsc->p2p_ps_info.p2p_ps_mode)1429 fw_ps_awake = false;1430 1431 if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&1432 fw_ps_awake)1433 && (!ppsc->rfchange_inprogress)) {1434 rtl92c_dm_pwdb_monitor(hw);1435 rtl92c_dm_dig(hw);1436 rtl92c_dm_false_alarm_counter_statistics(hw);1437 rtl92c_dm_dynamic_bb_powersaving(hw);1438 rtl92c_dm_dynamic_txpower(hw);1439 rtl92c_dm_check_txpower_tracking(hw);1440 /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */1441 rtl92c_dm_bt_coexist(hw);1442 rtl92c_dm_check_edca_turbo(hw);1443 }1444}1445EXPORT_SYMBOL(rtl92c_dm_watchdog);1446 1447u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)1448{1449 struct rtl_priv *rtlpriv = rtl_priv(hw);1450 long undec_sm_pwdb;1451 u8 curr_bt_rssi_state = 0x00;1452 1453 if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {1454 undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);1455 } else {1456 if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)1457 undec_sm_pwdb = 100;1458 else1459 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;1460 }1461 1462 /* Check RSSI to determine HighPower/NormalPower state for1463 * BT coexistence. */1464 if (undec_sm_pwdb >= 67)1465 curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);1466 else if (undec_sm_pwdb < 62)1467 curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;1468 1469 /* Check RSSI to determine AMPDU setting for BT coexistence. */1470 if (undec_sm_pwdb >= 40)1471 curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);1472 else if (undec_sm_pwdb <= 32)1473 curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;1474 1475 /* Marked RSSI state. It will be used to determine BT coexistence1476 * setting later. */1477 if (undec_sm_pwdb < 35)1478 curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW;1479 else1480 curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);1481 1482 /* Check BT state related to BT_Idle in B/G mode. */1483 if (undec_sm_pwdb < 15)1484 curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW;1485 else1486 curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);1487 1488 if (curr_bt_rssi_state != rtlpriv->btcoexist.bt_rssi_state) {1489 rtlpriv->btcoexist.bt_rssi_state = curr_bt_rssi_state;1490 return true;1491 } else {1492 return false;1493 }1494}1495EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);1496 1497static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)1498{1499 struct rtl_priv *rtlpriv = rtl_priv(hw);1500 1501 u32 polling, ratio_tx, ratio_pri;1502 u32 bt_tx, bt_pri;1503 u8 bt_state;1504 u8 cur_service_type;1505 1506 if (rtlpriv->mac80211.link_state < MAC80211_LINKED)1507 return false;1508 1509 bt_state = rtl_read_byte(rtlpriv, 0x4fd);1510 bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK;1511 bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK;1512 polling = rtl_read_dword(rtlpriv, 0x490);1513 1514 if (bt_tx == BT_MASK && bt_pri == BT_MASK &&1515 polling == 0xffffffff && bt_state == 0xff)1516 return false;1517 1518 bt_state &= BIT(0);1519 if (bt_state != rtlpriv->btcoexist.bt_cur_state) {1520 rtlpriv->btcoexist.bt_cur_state = bt_state;1521 1522 if (rtlpriv->btcoexist.reg_bt_sco == 3) {1523 rtlpriv->btcoexist.bt_service = BT_IDLE;1524 1525 bt_state = bt_state |1526 ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?1527 0 : BIT(1)) | BIT(2);1528 rtl_write_byte(rtlpriv, 0x4fd, bt_state);1529 }1530 return true;1531 }1532 1533 ratio_tx = bt_tx * 1000 / polling;1534 ratio_pri = bt_pri * 1000 / polling;1535 rtlpriv->btcoexist.ratio_tx = ratio_tx;1536 rtlpriv->btcoexist.ratio_pri = ratio_pri;1537 1538 if (bt_state && rtlpriv->btcoexist.reg_bt_sco == 3) {1539 1540 if ((ratio_tx < 30) && (ratio_pri < 30))1541 cur_service_type = BT_IDLE;1542 else if ((ratio_pri > 110) && (ratio_pri < 250))1543 cur_service_type = BT_SCO;1544 else if ((ratio_tx >= 200) && (ratio_pri >= 200))1545 cur_service_type = BT_BUSY;1546 else if ((ratio_tx >= 350) && (ratio_tx < 500))1547 cur_service_type = BT_OTHERBUSY;1548 else if (ratio_tx >= 500)1549 cur_service_type = BT_PAN;1550 else1551 cur_service_type = BT_OTHER_ACTION;1552 1553 if (cur_service_type != rtlpriv->btcoexist.bt_service) {1554 rtlpriv->btcoexist.bt_service = cur_service_type;1555 bt_state = bt_state |1556 ((rtlpriv->btcoexist.bt_ant_isolation == 1) ?1557 0 : BIT(1)) |1558 ((rtlpriv->btcoexist.bt_service != BT_IDLE) ?1559 0 : BIT(2));1560 1561 /* Add interrupt migration when bt is not ini1562 * idle state (no traffic). */1563 if (rtlpriv->btcoexist.bt_service != BT_IDLE) {1564 rtl_write_word(rtlpriv, 0x504, 0x0ccc);1565 rtl_write_byte(rtlpriv, 0x506, 0x54);1566 rtl_write_byte(rtlpriv, 0x507, 0x54);1567 } else {1568 rtl_write_byte(rtlpriv, 0x506, 0x00);1569 rtl_write_byte(rtlpriv, 0x507, 0x00);1570 }1571 1572 rtl_write_byte(rtlpriv, 0x4fd, bt_state);1573 return true;1574 }1575 }1576 1577 return false;1578 1579}1580 1581static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)1582{1583 struct rtl_priv *rtlpriv = rtl_priv(hw);1584 static bool media_connect;1585 1586 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {1587 media_connect = false;1588 } else {1589 if (!media_connect) {1590 media_connect = true;1591 return true;1592 }1593 media_connect = true;1594 }1595 1596 return false;1597}1598 1599static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)1600{1601 struct rtl_priv *rtlpriv = rtl_priv(hw);1602 1603 if (rtlpriv->btcoexist.bt_service == BT_OTHERBUSY) {1604 rtlpriv->btcoexist.bt_edca_ul = 0x5ea72b;1605 rtlpriv->btcoexist.bt_edca_dl = 0x5ea72b;1606 } else if (rtlpriv->btcoexist.bt_service == BT_BUSY) {1607 rtlpriv->btcoexist.bt_edca_ul = 0x5eb82f;1608 rtlpriv->btcoexist.bt_edca_dl = 0x5eb82f;1609 } else if (rtlpriv->btcoexist.bt_service == BT_SCO) {1610 if (rtlpriv->btcoexist.ratio_tx > 160) {1611 rtlpriv->btcoexist.bt_edca_ul = 0x5ea72f;1612 rtlpriv->btcoexist.bt_edca_dl = 0x5ea72f;1613 } else {1614 rtlpriv->btcoexist.bt_edca_ul = 0x5ea32b;1615 rtlpriv->btcoexist.bt_edca_dl = 0x5ea42b;1616 }1617 } else {1618 rtlpriv->btcoexist.bt_edca_ul = 0;1619 rtlpriv->btcoexist.bt_edca_dl = 0;1620 }1621 1622 if ((rtlpriv->btcoexist.bt_service != BT_IDLE) &&1623 (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||1624 (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&1625 (rtlpriv->btcoexist.bt_rssi_state &1626 BT_RSSI_STATE_BG_EDCA_LOW)) {1627 rtlpriv->btcoexist.bt_edca_ul = 0x5eb82b;1628 rtlpriv->btcoexist.bt_edca_dl = 0x5eb82b;1629 }1630}1631 1632static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)1633{1634 struct rtl_priv *rtlpriv = rtl_priv(hw);1635 1636 /* Only enable HW BT coexist when BT in "Busy" state. */1637 if (rtlpriv->mac80211.vendor == PEER_CISCO &&1638 rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {1639 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);1640 } else {1641 if ((rtlpriv->btcoexist.bt_service == BT_BUSY) &&1642 (rtlpriv->btcoexist.bt_rssi_state &1643 BT_RSSI_STATE_NORMAL_POWER)) {1644 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);1645 } else if ((rtlpriv->btcoexist.bt_service ==1646 BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <1647 WIRELESS_MODE_N_24G) &&1648 (rtlpriv->btcoexist.bt_rssi_state &1649 BT_RSSI_STATE_SPECIAL_LOW)) {1650 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);1651 } else {1652 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);1653 }1654 }1655 1656 if (rtlpriv->btcoexist.bt_service == BT_PAN)1657 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);1658 else1659 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);1660 1661 if (rtlpriv->btcoexist.bt_rssi_state &1662 BT_RSSI_STATE_NORMAL_POWER) {1663 rtl92c_bt_set_normal(hw);1664 } else {1665 rtlpriv->btcoexist.bt_edca_ul = 0;1666 rtlpriv->btcoexist.bt_edca_dl = 0;1667 }1668 1669 if (rtlpriv->btcoexist.bt_service != BT_IDLE) {1670 rtlpriv->cfg->ops->set_rfreg(hw,1671 RF90_PATH_A,1672 0x1e,1673 0xf0, 0xf);1674 } else {1675 rtlpriv->cfg->ops->set_rfreg(hw,1676 RF90_PATH_A, 0x1e, 0xf0,1677 rtlpriv->btcoexist.bt_rfreg_origin_1e);1678 }1679 1680 if (!rtlpriv->dm.dynamic_txpower_enable) {1681 if (rtlpriv->btcoexist.bt_service != BT_IDLE) {1682 if (rtlpriv->btcoexist.bt_rssi_state &1683 BT_RSSI_STATE_TXPOWER_LOW) {1684 rtlpriv->dm.dynamic_txhighpower_lvl =1685 TXHIGHPWRLEVEL_BT2;1686 } else {1687 rtlpriv->dm.dynamic_txhighpower_lvl =1688 TXHIGHPWRLEVEL_BT1;1689 }1690 } else {1691 rtlpriv->dm.dynamic_txhighpower_lvl =1692 TXHIGHPWRLEVEL_NORMAL;1693 }1694 rtl92c_phy_set_txpower_level(hw,1695 rtlpriv->phy.current_channel);1696 }1697}1698 1699static void rtl92c_check_bt_change(struct ieee80211_hw *hw)1700{1701 struct rtl_priv *rtlpriv = rtl_priv(hw);1702 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));1703 u8 tmp1byte = 0;1704 1705 if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&1706 rtlpriv->btcoexist.bt_coexistence)1707 tmp1byte |= BIT(5);1708 if (rtlpriv->btcoexist.bt_cur_state) {1709 if (rtlpriv->btcoexist.bt_ant_isolation)1710 rtl92c_bt_ant_isolation(hw, tmp1byte);1711 } else {1712 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);1713 rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,1714 rtlpriv->btcoexist.bt_rfreg_origin_1e);1715 1716 rtlpriv->btcoexist.bt_edca_ul = 0;1717 rtlpriv->btcoexist.bt_edca_dl = 0;1718 }1719}1720 1721void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)1722{1723 struct rtl_priv *rtlpriv = rtl_priv(hw);1724 bool wifi_connect_change;1725 bool bt_state_change;1726 bool rssi_state_change;1727 1728 if ((rtlpriv->btcoexist.bt_coexistence) &&1729 (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) {1730 wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);1731 bt_state_change = rtl92c_bt_state_change(hw);1732 rssi_state_change = rtl92c_bt_rssi_state_change(hw);1733 1734 if (wifi_connect_change || bt_state_change || rssi_state_change)1735 rtl92c_check_bt_change(hw);1736 }1737}1738EXPORT_SYMBOL(rtl92c_dm_bt_coexist);1739