Linux Audio

Check our new training course

Embedded Linux training

Mar 10-20, 2025, special US time zones
Register
Loading...
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2014  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../base.h"
   6#include "../pci.h"
   7#include "../core.h"
   8#include "reg.h"
   9#include "def.h"
  10#include "phy.h"
  11#include "dm.h"
  12#include "../rtl8723com/dm_common.h"
  13#include "fw.h"
  14#include "trx.h"
  15#include "../btcoexist/rtl_btc.h"
  16
  17static const u32 ofdmswing_table[] = {
  18	0x0b40002d, /* 0,  -15.0dB */
  19	0x0c000030, /* 1,  -14.5dB */
  20	0x0cc00033, /* 2,  -14.0dB */
  21	0x0d800036, /* 3,  -13.5dB */
  22	0x0e400039, /* 4,  -13.0dB */
  23	0x0f00003c, /* 5,  -12.5dB */
  24	0x10000040, /* 6,  -12.0dB */
  25	0x11000044, /* 7,  -11.5dB */
  26	0x12000048, /* 8,  -11.0dB */
  27	0x1300004c, /* 9,  -10.5dB */
  28	0x14400051, /* 10, -10.0dB */
  29	0x15800056, /* 11, -9.5dB */
  30	0x16c0005b, /* 12, -9.0dB */
  31	0x18000060, /* 13, -8.5dB */
  32	0x19800066, /* 14, -8.0dB */
  33	0x1b00006c, /* 15, -7.5dB */
  34	0x1c800072, /* 16, -7.0dB */
  35	0x1e400079, /* 17, -6.5dB */
  36	0x20000080, /* 18, -6.0dB */
  37	0x22000088, /* 19, -5.5dB */
  38	0x24000090, /* 20, -5.0dB */
  39	0x26000098, /* 21, -4.5dB */
  40	0x288000a2, /* 22, -4.0dB */
  41	0x2ac000ab, /* 23, -3.5dB */
  42	0x2d4000b5, /* 24, -3.0dB */
  43	0x300000c0, /* 25, -2.5dB */
  44	0x32c000cb, /* 26, -2.0dB */
  45	0x35c000d7, /* 27, -1.5dB */
  46	0x390000e4, /* 28, -1.0dB */
  47	0x3c8000f2, /* 29, -0.5dB */
  48	0x40000100, /* 30, +0dB */
  49	0x43c0010f, /* 31, +0.5dB */
  50	0x47c0011f, /* 32, +1.0dB */
  51	0x4c000130, /* 33, +1.5dB */
  52	0x50800142, /* 34, +2.0dB */
  53	0x55400155, /* 35, +2.5dB */
  54	0x5a400169, /* 36, +3.0dB */
  55	0x5fc0017f, /* 37, +3.5dB */
  56	0x65400195, /* 38, +4.0dB */
  57	0x6b8001ae, /* 39, +4.5dB */
  58	0x71c001c7, /* 40, +5.0dB */
  59	0x788001e2, /* 41, +5.5dB */
  60	0x7f8001fe  /* 42, +6.0dB */
  61};
  62
  63static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
  64	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /*  0, -16.0dB */
  65	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /*  1, -15.5dB */
  66	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  2, -15.0dB */
  67	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  3, -14.5dB */
  68	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  4, -14.0dB */
  69	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  5, -13.5dB */
  70	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /*  6, -13.0dB */
  71	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /*  7, -12.5dB */
  72	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /*  8, -12.0dB */
  73	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /*  9, -11.5dB */
  74	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
  75	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
  76	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
  77	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
  78	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
  79	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
  80	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
  81	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
  82	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
  83	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
  84	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
  85	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
  86	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
  87	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
  88	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
  89	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
  90	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
  91	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
  92	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
  93	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
  94	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
  95	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
  96	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}  /* 32, +0dB */
  97};
  98
  99static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 100	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /*  0, -16.0dB */
 101	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  1, -15.5dB */
 102	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  2, -15.0dB */
 103	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  3, -14.5dB */
 104	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  4, -14.0dB */
 105	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  5, -13.5dB */
 106	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  6, -13.0dB */
 107	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  7, -12.5dB */
 108	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  8, -12.0dB */
 109	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  9, -11.5dB */
 110	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
 111	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
 112	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
 113	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
 114	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
 115	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
 116	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
 117	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
 118	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
 119	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
 120	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
 121	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
 122	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
 123	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
 124	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
 125	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
 126	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
 127	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
 128	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
 129	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
 130	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
 131	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
 132	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}  /* 32, +0dB */
 133};
 134
 135static const u32 edca_setting_dl[PEER_MAX] = {
 136	0xa44f,		/* 0 UNKNOWN */
 137	0x5ea44f,	/* 1 REALTEK_90 */
 138	0x5e4322,	/* 2 REALTEK_92SE */
 139	0x5ea42b,	/* 3 BROAD */
 140	0xa44f,		/* 4 RAL */
 141	0xa630,		/* 5 ATH */
 142	0x5ea630,	/* 6 CISCO */
 143	0x5ea42b,	/* 7 MARVELL */
 144};
 145
 146static const u32 edca_setting_ul[PEER_MAX] = {
 147	0x5e4322,	/* 0 UNKNOWN */
 148	0xa44f,		/* 1 REALTEK_90 */
 149	0x5ea44f,	/* 2 REALTEK_92SE */
 150	0x5ea32b,	/* 3 BROAD */
 151	0x5ea422,	/* 4 RAL */
 152	0x5ea322,	/* 5 ATH */
 153	0x3ea430,	/* 6 CISCO */
 154	0x5ea44f,	/* 7 MARV */
 155};
 156
 157void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
 158				       u8 *pdirection, u32 *poutwrite_val)
 159{
 160	struct rtl_priv *rtlpriv = rtl_priv(hw);
 161	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 162	u8 pwr_val = 0;
 163	u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
 164	u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
 165	u8 cck_base = rtldm->swing_idx_cck_base;
 166	u8 cck_val = rtldm->swing_idx_cck;
 167
 168	if (type == 0) {
 169		if (ofdm_val <= ofdm_base) {
 170			*pdirection = 1;
 171			pwr_val = ofdm_base - ofdm_val;
 172		} else {
 173			*pdirection = 2;
 174			pwr_val = ofdm_val - ofdm_base;
 175		}
 176	} else if (type == 1) {
 177		if (cck_val <= cck_base) {
 178			*pdirection = 1;
 179			pwr_val = cck_base - cck_val;
 180		} else {
 181			*pdirection = 2;
 182			pwr_val = cck_val - cck_base;
 183		}
 184	}
 185
 186	if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 187		pwr_val = TXPWRTRACK_MAX_IDX;
 188
 189	*poutwrite_val = pwr_val | (pwr_val << 8) |
 190		(pwr_val << 16) | (pwr_val << 24);
 191}
 192
 193void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 194{
 195	struct rtl_priv *rtlpriv = rtl_priv(hw);
 196	struct rate_adaptive *p_ra = &rtlpriv->ra;
 197
 198	p_ra->ratr_state = DM_RATR_STA_INIT;
 199	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 200
 201	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 202		rtlpriv->dm.useramask = true;
 203	else
 204		rtlpriv->dm.useramask = false;
 205
 206	p_ra->high_rssi_thresh_for_ra = 50;
 207	p_ra->low_rssi_thresh_for_ra40m = 20;
 208}
 209
 210static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
 211{
 212	struct rtl_priv *rtlpriv = rtl_priv(hw);
 213
 214	rtlpriv->dm.txpower_tracking = true;
 215	rtlpriv->dm.txpower_track_control = true;
 216	rtlpriv->dm.thermalvalue = 0;
 217
 218	rtlpriv->dm.ofdm_index[0] = 30;
 219	rtlpriv->dm.cck_index = 20;
 220
 221	rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
 222
 223	rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
 224	rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
 225	rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
 226	rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
 227
 228	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 229		"rtlpriv->dm.txpower_tracking = %d\n",
 230		rtlpriv->dm.txpower_tracking);
 231}
 232
 233static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 234{
 235	struct rtl_priv *rtlpriv = rtl_priv(hw);
 236
 237	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 238
 239	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
 240	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 241}
 242
 243void rtl8723be_dm_init(struct ieee80211_hw *hw)
 244{
 245	struct rtl_priv *rtlpriv = rtl_priv(hw);
 246	u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 247
 248	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 249	rtl_dm_diginit(hw, cur_igvalue);
 250	rtl8723be_dm_init_rate_adaptive_mask(hw);
 251	rtl8723_dm_init_edca_turbo(hw);
 252	rtl8723_dm_init_dynamic_bb_powersaving(hw);
 253	rtl8723_dm_init_dynamic_txpower(hw);
 254	rtl8723be_dm_init_txpower_tracking(hw);
 255	rtl8723be_dm_init_dynamic_atc_switch(hw);
 256}
 257
 258static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 259{
 260	struct rtl_priv *rtlpriv = rtl_priv(hw);
 261	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 262	struct rtl_mac *mac = rtl_mac(rtlpriv);
 263
 264	/* Determine the minimum RSSI  */
 265	if ((mac->link_state < MAC80211_LINKED) &&
 266	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 267		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 268		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 269			"Not connected to any\n");
 270	}
 271	if (mac->link_state >= MAC80211_LINKED) {
 272		if (mac->opmode == NL80211_IFTYPE_AP ||
 273		    mac->opmode == NL80211_IFTYPE_ADHOC) {
 274			rtl_dm_dig->min_undec_pwdb_for_dm =
 275			    rtlpriv->dm.entry_min_undec_sm_pwdb;
 276			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 277				"AP Client PWDB = 0x%lx\n",
 278				rtlpriv->dm.entry_min_undec_sm_pwdb);
 279		} else {
 280			rtl_dm_dig->min_undec_pwdb_for_dm =
 281			    rtlpriv->dm.undec_sm_pwdb;
 282			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 283				"STA Default Port PWDB = 0x%x\n",
 284				rtl_dm_dig->min_undec_pwdb_for_dm);
 285		}
 286	} else {
 287		rtl_dm_dig->min_undec_pwdb_for_dm =
 288				rtlpriv->dm.entry_min_undec_sm_pwdb;
 289		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 290			"AP Ext Port or disconnect PWDB = 0x%x\n",
 291			rtl_dm_dig->min_undec_pwdb_for_dm);
 292	}
 293	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
 294		rtl_dm_dig->min_undec_pwdb_for_dm);
 295}
 296
 297static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 298{
 299	struct rtl_priv *rtlpriv = rtl_priv(hw);
 300	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 301	struct rtl_sta_info *drv_priv;
 302	u8 h2c_parameter[3] = { 0 };
 303	long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 304
 305	/* AP & ADHOC & MESH */
 306	spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 307	list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 308		if (drv_priv->rssi_stat.undec_sm_pwdb <
 309						tmp_entry_min_pwdb)
 310			tmp_entry_min_pwdb =
 311				drv_priv->rssi_stat.undec_sm_pwdb;
 312		if (drv_priv->rssi_stat.undec_sm_pwdb >
 313						tmp_entry_max_pwdb)
 314			tmp_entry_max_pwdb =
 315				drv_priv->rssi_stat.undec_sm_pwdb;
 316	}
 317	spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 318
 319	/* If associated entry is found */
 320	if (tmp_entry_max_pwdb != 0) {
 321		rtlpriv->dm.entry_max_undec_sm_pwdb =
 322							tmp_entry_max_pwdb;
 323		RTPRINT(rtlpriv, FDM, DM_PWDB,
 324			"EntryMaxPWDB = 0x%lx(%ld)\n",
 325			 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 326	} else {
 327		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 328	}
 329	/* If associated entry is found */
 330	if (tmp_entry_min_pwdb != 0xff) {
 331		rtlpriv->dm.entry_min_undec_sm_pwdb =
 332							tmp_entry_min_pwdb;
 333		RTPRINT(rtlpriv, FDM, DM_PWDB,
 334			"EntryMinPWDB = 0x%lx(%ld)\n",
 335			 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 336	} else {
 337		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 338	}
 339	/* Indicate Rx signal strength to FW. */
 340	if (rtlpriv->dm.useramask) {
 341		h2c_parameter[2] =
 342			(u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 343		h2c_parameter[1] = 0x20;
 344		h2c_parameter[0] = 0;
 345		rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
 346	} else {
 347		rtl_write_byte(rtlpriv, 0x4fe,
 348			       rtlpriv->dm.undec_sm_pwdb);
 349	}
 350	rtl8723be_dm_find_minimum_rssi(hw);
 351	dm_digtable->rssi_val_min =
 352			rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 353}
 354
 355void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 356{
 357	struct rtl_priv *rtlpriv = rtl_priv(hw);
 358	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 359
 360	if (dm_digtable->stop_dig)
 361		return;
 362
 363	if (dm_digtable->cur_igvalue != current_igi) {
 364		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
 365		if (rtlpriv->phy.rf_type != RF_1T1R)
 366			rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
 367				      0x7f, current_igi);
 368	}
 369	dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
 370	dm_digtable->cur_igvalue = current_igi;
 371}
 372
 373static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
 374{
 375	struct rtl_priv *rtlpriv = rtl_priv(hw);
 376	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 377	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 378	u8 dig_min_0, dig_maxofmin;
 379	bool bfirstconnect, bfirstdisconnect;
 380	u8 dm_dig_max, dm_dig_min;
 381	u8 current_igi = dm_digtable->cur_igvalue;
 382	u8 offset;
 383
 384	/* AP,BT */
 385	if (mac->act_scanning)
 386		return;
 387
 388	dig_min_0 = dm_digtable->dig_min_0;
 389	bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
 390			!dm_digtable->media_connect_0;
 391	bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
 392			(dm_digtable->media_connect_0);
 393
 394	dm_dig_max = 0x5a;
 395	dm_dig_min = DM_DIG_MIN;
 396	dig_maxofmin = DM_DIG_MAX_AP;
 397
 398	if (mac->link_state >= MAC80211_LINKED) {
 399		if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
 400			dm_digtable->rx_gain_max = dm_dig_max;
 401		else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
 402			dm_digtable->rx_gain_max = dm_dig_min;
 403		else
 404			dm_digtable->rx_gain_max =
 405				dm_digtable->rssi_val_min + 10;
 406
 407		if (rtlpriv->dm.one_entry_only) {
 408			offset = 12;
 409			if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 410				dig_min_0 = dm_dig_min;
 411			else if (dm_digtable->rssi_val_min - offset >
 412							dig_maxofmin)
 413				dig_min_0 = dig_maxofmin;
 414			else
 415				dig_min_0 =
 416					dm_digtable->rssi_val_min - offset;
 417		} else {
 418			dig_min_0 = dm_dig_min;
 419		}
 420
 421	} else {
 422		dm_digtable->rx_gain_max = dm_dig_max;
 423		dig_min_0 = dm_dig_min;
 424		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
 425	}
 426
 427	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 428		if (dm_digtable->large_fa_hit != 3)
 429			dm_digtable->large_fa_hit++;
 430		if (dm_digtable->forbidden_igi < current_igi) {
 431			dm_digtable->forbidden_igi = current_igi;
 432			dm_digtable->large_fa_hit = 1;
 433		}
 434
 435		if (dm_digtable->large_fa_hit >= 3) {
 436			if ((dm_digtable->forbidden_igi + 1) >
 437			     dm_digtable->rx_gain_max)
 438				dm_digtable->rx_gain_min =
 439						dm_digtable->rx_gain_max;
 440			else
 441				dm_digtable->rx_gain_min =
 442						dm_digtable->forbidden_igi + 1;
 443			dm_digtable->recover_cnt = 3600;
 444		}
 445	} else {
 446		if (dm_digtable->recover_cnt != 0) {
 447			dm_digtable->recover_cnt--;
 448		} else {
 449			if (dm_digtable->large_fa_hit < 3) {
 450				if ((dm_digtable->forbidden_igi - 1) <
 451				     dig_min_0) {
 452					dm_digtable->forbidden_igi =
 453							dig_min_0;
 454					dm_digtable->rx_gain_min =
 455							dig_min_0;
 456				} else {
 457					dm_digtable->forbidden_igi--;
 458					dm_digtable->rx_gain_min =
 459						dm_digtable->forbidden_igi + 1;
 460				}
 461			} else {
 462				dm_digtable->large_fa_hit = 0;
 463			}
 464		}
 465	}
 466	if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 467		dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 468
 469	if (mac->link_state >= MAC80211_LINKED) {
 470		if (bfirstconnect) {
 471			if (dm_digtable->rssi_val_min <= dig_maxofmin)
 472				current_igi = dm_digtable->rssi_val_min;
 473			else
 474				current_igi = dig_maxofmin;
 475
 476			dm_digtable->large_fa_hit = 0;
 477		} else {
 478			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 479				current_igi += 4;
 480			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 481				current_igi += 2;
 482			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 483				current_igi -= 2;
 484		}
 485	} else {
 486		if (bfirstdisconnect) {
 487			current_igi = dm_digtable->rx_gain_min;
 488		} else {
 489			if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 490				current_igi += 4;
 491			else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
 492				current_igi += 2;
 493			else if (rtlpriv->falsealm_cnt.cnt_all < 500)
 494				current_igi -= 2;
 495		}
 496	}
 497
 498	if (current_igi > dm_digtable->rx_gain_max)
 499		current_igi = dm_digtable->rx_gain_max;
 500	else if (current_igi < dm_digtable->rx_gain_min)
 501		current_igi = dm_digtable->rx_gain_min;
 502
 503	rtl8723be_dm_write_dig(hw, current_igi);
 504	dm_digtable->media_connect_0 =
 505		((mac->link_state >= MAC80211_LINKED) ? true : false);
 506	dm_digtable->dig_min_0 = dig_min_0;
 507}
 508
 509static void rtl8723be_dm_false_alarm_counter_statistics(
 510					struct ieee80211_hw *hw)
 511{
 512	u32 ret_value;
 513	struct rtl_priv *rtlpriv = rtl_priv(hw);
 514	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 515
 516	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
 517	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
 518
 519	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
 520	falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
 521	falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
 522
 523	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
 524	falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
 525	falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
 526
 527	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
 528	falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
 529	falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
 530
 531	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
 532	falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
 533
 534	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
 535				      falsealm_cnt->cnt_rate_illegal +
 536				      falsealm_cnt->cnt_crc8_fail +
 537				      falsealm_cnt->cnt_mcs_fail +
 538				      falsealm_cnt->cnt_fast_fsync_fail +
 539				      falsealm_cnt->cnt_sb_search_fail;
 540
 541	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
 542	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
 543
 544	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
 545	falsealm_cnt->cnt_cck_fail = ret_value;
 546
 547	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
 548	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 549
 550	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
 551	falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
 552				    ((ret_value & 0xff00) >> 8);
 553
 554	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
 555				falsealm_cnt->cnt_sb_search_fail +
 556				falsealm_cnt->cnt_parity_fail +
 557				falsealm_cnt->cnt_rate_illegal +
 558				falsealm_cnt->cnt_crc8_fail +
 559				falsealm_cnt->cnt_mcs_fail +
 560				falsealm_cnt->cnt_cck_fail;
 561
 562	falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
 563				    falsealm_cnt->cnt_cck_cca;
 564
 565	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
 566	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
 567	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
 568	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
 569
 570	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
 571	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
 572
 573	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
 574	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
 575
 576	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
 577	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
 578
 579	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
 580		"cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 581		falsealm_cnt->cnt_parity_fail,
 582		falsealm_cnt->cnt_rate_illegal,
 583		falsealm_cnt->cnt_crc8_fail,
 584		falsealm_cnt->cnt_mcs_fail);
 585
 586	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
 587		"cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 588		falsealm_cnt->cnt_ofdm_fail,
 589		falsealm_cnt->cnt_cck_fail,
 590		falsealm_cnt->cnt_all);
 591}
 592
 593static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
 594{
 595	/* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
 596	return;
 597}
 598
 599static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
 600				     u8 rfpath, long iqk_result_x,
 601				     long iqk_result_y)
 602{
 603	long ele_a = 0, ele_d, ele_c = 0, value32;
 604
 605	if (ofdm_index >= 43)
 606		ofdm_index = 43 - 1;
 607
 608	ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
 609
 610	if (iqk_result_x != 0) {
 611		if ((iqk_result_x & 0x00000200) != 0)
 612			iqk_result_x = iqk_result_x | 0xFFFFFC00;
 613		ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
 614
 615		if ((iqk_result_y & 0x00000200) != 0)
 616			iqk_result_y = iqk_result_y | 0xFFFFFC00;
 617		ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
 618
 619		switch (rfpath) {
 620		case RF90_PATH_A:
 621			value32 = (ele_d << 22) |
 622				((ele_c & 0x3F) << 16) | ele_a;
 623			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 624				      value32);
 625			value32 = (ele_c & 0x000003C0) >> 6;
 626			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
 627			value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
 628			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
 629				      value32);
 630			break;
 631		default:
 632			break;
 633		}
 634	} else {
 635		switch (rfpath) {
 636		case RF90_PATH_A:
 637			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 638				      ofdmswing_table[ofdm_index]);
 639			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
 640			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
 641			break;
 642		default:
 643			break;
 644		}
 645	}
 646}
 647
 648static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
 649					enum pwr_track_control_method method,
 650					u8 rfpath, u8 idx)
 651{
 652	struct rtl_priv *rtlpriv = rtl_priv(hw);
 653	struct rtl_phy *rtlphy = &rtlpriv->phy;
 654	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 655	u8 swing_idx_ofdm_limit = 36;
 656
 657	if (method == TXAGC) {
 658		rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
 659	} else if (method == BBSWING) {
 660		if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
 661			rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
 662
 663		if (!rtldm->cck_inch14) {
 664			rtl_write_byte(rtlpriv, 0xa22,
 665			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
 666			rtl_write_byte(rtlpriv, 0xa23,
 667			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
 668			rtl_write_byte(rtlpriv, 0xa24,
 669			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
 670			rtl_write_byte(rtlpriv, 0xa25,
 671			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
 672			rtl_write_byte(rtlpriv, 0xa26,
 673			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
 674			rtl_write_byte(rtlpriv, 0xa27,
 675			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
 676			rtl_write_byte(rtlpriv, 0xa28,
 677			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
 678			rtl_write_byte(rtlpriv, 0xa29,
 679			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
 680		} else {
 681			rtl_write_byte(rtlpriv, 0xa22,
 682			    cckswing_table_ch14[rtldm->swing_idx_cck][0]);
 683			rtl_write_byte(rtlpriv, 0xa23,
 684			    cckswing_table_ch14[rtldm->swing_idx_cck][1]);
 685			rtl_write_byte(rtlpriv, 0xa24,
 686			    cckswing_table_ch14[rtldm->swing_idx_cck][2]);
 687			rtl_write_byte(rtlpriv, 0xa25,
 688			    cckswing_table_ch14[rtldm->swing_idx_cck][3]);
 689			rtl_write_byte(rtlpriv, 0xa26,
 690			    cckswing_table_ch14[rtldm->swing_idx_cck][4]);
 691			rtl_write_byte(rtlpriv, 0xa27,
 692			    cckswing_table_ch14[rtldm->swing_idx_cck][5]);
 693			rtl_write_byte(rtlpriv, 0xa28,
 694			    cckswing_table_ch14[rtldm->swing_idx_cck][6]);
 695			rtl_write_byte(rtlpriv, 0xa29,
 696			    cckswing_table_ch14[rtldm->swing_idx_cck][7]);
 697		}
 698
 699		if (rfpath == RF90_PATH_A) {
 700			if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
 701			    swing_idx_ofdm_limit)
 702				swing_idx_ofdm_limit =
 703					rtldm->swing_idx_ofdm[RF90_PATH_A];
 704
 705			rtl8723be_set_iqk_matrix(hw,
 706				rtldm->swing_idx_ofdm[rfpath], rfpath,
 707				rtlphy->iqk_matrix[idx].value[0][0],
 708				rtlphy->iqk_matrix[idx].value[0][1]);
 709		} else if (rfpath == RF90_PATH_B) {
 710			if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
 711			    swing_idx_ofdm_limit)
 712				swing_idx_ofdm_limit =
 713					rtldm->swing_idx_ofdm[RF90_PATH_B];
 714
 715			rtl8723be_set_iqk_matrix(hw,
 716				rtldm->swing_idx_ofdm[rfpath], rfpath,
 717				rtlphy->iqk_matrix[idx].value[0][4],
 718				rtlphy->iqk_matrix[idx].value[0][5]);
 719		}
 720	} else {
 721		return;
 722	}
 723}
 724
 725static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
 726							struct ieee80211_hw *hw)
 727{
 728	struct rtl_priv *rtlpriv = rtl_priv(hw);
 729	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 730	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
 731	u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
 732	u8 thermalvalue_avg_count = 0;
 733	u32 thermalvalue_avg = 0;
 734	int i = 0;
 735
 736	u8 ofdm_min_index = 6;
 737	u8 index_for_channel = 0;
 738
 739	static const s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
 740		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 741		5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
 742		10, 11, 11, 12, 12, 13, 14, 15};
 743	static const s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
 744		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 745		5, 6, 6, 6, 6, 7, 7, 7, 8, 8,  9,
 746		9, 10, 10, 11, 12, 13, 14, 15};
 747
 748	/*Initilization ( 7 steps in total )*/
 749	rtlpriv->dm.txpower_trackinginit = true;
 750	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 751		"%s\n", __func__);
 752
 753	thermalvalue = (u8)rtl_get_rfreg(hw,
 754		RF90_PATH_A, RF_T_METER, 0xfc00);
 755	if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
 756	    rtlefuse->eeprom_thermalmeter == 0xFF)
 757		return;
 758	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 759		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
 760		thermalvalue, rtldm->thermalvalue,
 761		rtlefuse->eeprom_thermalmeter);
 762	/*3 Initialize ThermalValues of RFCalibrateInfo*/
 763	if (!rtldm->thermalvalue) {
 764		rtlpriv->dm.thermalvalue_lck = thermalvalue;
 765		rtlpriv->dm.thermalvalue_iqk = thermalvalue;
 766	}
 767
 768	/*4 Calculate average thermal meter*/
 769	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
 770	rtldm->thermalvalue_avg_index++;
 771	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
 772		rtldm->thermalvalue_avg_index = 0;
 773
 774	for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
 775		if (rtldm->thermalvalue_avg[i]) {
 776			thermalvalue_avg += rtldm->thermalvalue_avg[i];
 777			thermalvalue_avg_count++;
 778		}
 779	}
 780
 781	if (thermalvalue_avg_count)
 782		thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
 783
 784	/* 5 Calculate delta, delta_LCK, delta_IQK.*/
 785	delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
 786		(thermalvalue - rtlpriv->dm.thermalvalue) :
 787		(rtlpriv->dm.thermalvalue - thermalvalue);
 788	delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
 789		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
 790		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
 791	delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
 792		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
 793		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
 794
 795	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 796		"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",
 797		thermalvalue, rtlpriv->dm.thermalvalue,
 798		rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
 799	/* 6 If necessary, do LCK.*/
 800	if (delta_lck >= IQK_THRESHOLD) {
 801		rtlpriv->dm.thermalvalue_lck = thermalvalue;
 802		rtl8723be_phy_lc_calibrate(hw);
 803	}
 804
 805	/* 7 If necessary, move the index of
 806	 * swing table to adjust Tx power.
 807	 */
 808	if (delta > 0 && rtlpriv->dm.txpower_track_control) {
 809		delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
 810			(thermalvalue - rtlefuse->eeprom_thermalmeter) :
 811			(rtlefuse->eeprom_thermalmeter - thermalvalue);
 812
 813		if (delta >= TXSCALE_TABLE_SIZE)
 814			delta = TXSCALE_TABLE_SIZE - 1;
 815		/* 7.1 Get the final CCK_index and
 816		 * OFDM_index for each swing table.
 817		 */
 818		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
 819			rtldm->delta_power_index_last[RF90_PATH_A] =
 820					rtldm->delta_power_index[RF90_PATH_A];
 821			rtldm->delta_power_index[RF90_PATH_A] =
 822					delta_swing_table_idx_tup_a[delta];
 823		} else {
 824			rtldm->delta_power_index_last[RF90_PATH_A] =
 825					rtldm->delta_power_index[RF90_PATH_A];
 826			rtldm->delta_power_index[RF90_PATH_A] =
 827				-1 * delta_swing_table_idx_tdown_a[delta];
 828		}
 829
 830		/* 7.2 Handle boundary conditions of index.*/
 831		if (rtldm->delta_power_index[RF90_PATH_A] ==
 832		    rtldm->delta_power_index_last[RF90_PATH_A])
 833			rtldm->power_index_offset[RF90_PATH_A] = 0;
 834		else
 835			rtldm->power_index_offset[RF90_PATH_A] =
 836				rtldm->delta_power_index[RF90_PATH_A] -
 837				rtldm->delta_power_index_last[RF90_PATH_A];
 838
 839		rtldm->ofdm_index[0] =
 840			rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
 841			rtldm->power_index_offset[RF90_PATH_A];
 842		rtldm->cck_index = rtldm->swing_idx_cck_base +
 843				   rtldm->power_index_offset[RF90_PATH_A];
 844
 845		rtldm->swing_idx_cck = rtldm->cck_index;
 846		rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
 847
 848		if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
 849			rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
 850		else if (rtldm->ofdm_index[0] < ofdm_min_index)
 851			rtldm->ofdm_index[0] = ofdm_min_index;
 852
 853		if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
 854			rtldm->cck_index = CCK_TABLE_SIZE - 1;
 855		else if (rtldm->cck_index < 0)
 856			rtldm->cck_index = 0;
 857	} else {
 858		rtldm->power_index_offset[RF90_PATH_A] = 0;
 859	}
 860
 861	if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
 862	    (rtldm->txpower_track_control)) {
 863		rtldm->done_txpower = true;
 864		rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
 865						      index_for_channel);
 866
 867		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
 868		rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
 869						rtldm->swing_idx_ofdm[0];
 870		rtldm->thermalvalue = thermalvalue;
 871	}
 872
 873	if (delta_iqk >= IQK_THRESHOLD) {
 874		rtldm->thermalvalue_iqk = thermalvalue;
 875		rtl8723be_phy_iq_calibrate(hw, false);
 876	}
 877
 878	rtldm->txpowercount = 0;
 879	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
 880
 881}
 882
 883void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 884{
 885	struct rtl_priv *rtlpriv = rtl_priv(hw);
 886
 887	if (!rtlpriv->dm.txpower_tracking)
 888		return;
 889
 890	if (!rtlpriv->dm.tm_trigger) {
 891		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
 892			      0x03);
 893		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 894			"Trigger 8723be Thermal Meter!!\n");
 895		rtlpriv->dm.tm_trigger = 1;
 896		return;
 897	} else {
 898		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 899			"Schedule TxPowerTracking !!\n");
 900		rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
 901		rtlpriv->dm.tm_trigger = 0;
 902	}
 903}
 904
 905static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 906{
 907	struct rtl_priv *rtlpriv = rtl_priv(hw);
 908	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 909	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 910	struct rate_adaptive *p_ra = &rtlpriv->ra;
 911	u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
 912	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
 913	u8 go_up_gap = 5;
 914	struct ieee80211_sta *sta = NULL;
 915
 916	if (is_hal_stop(rtlhal)) {
 917		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 918			"driver is going to unload\n");
 919		return;
 920	}
 921
 922	if (!rtlpriv->dm.useramask) {
 923		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 924			"driver does not control rate adaptive mask\n");
 925		return;
 926	}
 927
 928	if (mac->link_state == MAC80211_LINKED &&
 929		mac->opmode == NL80211_IFTYPE_STATION) {
 930		switch (p_ra->pre_ratr_state) {
 931		case DM_RATR_STA_MIDDLE:
 932			high_rssithresh_for_ra += go_up_gap;
 933			break;
 934		case DM_RATR_STA_LOW:
 935			high_rssithresh_for_ra += go_up_gap;
 936			low_rssithresh_for_ra += go_up_gap;
 937			break;
 938		default:
 939			break;
 940		}
 941
 942		if (rtlpriv->dm.undec_sm_pwdb >
 943		    (long)high_rssithresh_for_ra)
 944			p_ra->ratr_state = DM_RATR_STA_HIGH;
 945		else if (rtlpriv->dm.undec_sm_pwdb >
 946			 (long)low_rssithresh_for_ra)
 947			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
 948		else
 949			p_ra->ratr_state = DM_RATR_STA_LOW;
 950
 951		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
 952			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 953				"RSSI = %ld\n",
 954				 rtlpriv->dm.undec_sm_pwdb);
 955			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 956				"RSSI_LEVEL = %d\n", p_ra->ratr_state);
 957			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
 958				"PreState = %d, CurState = %d\n",
 959				p_ra->pre_ratr_state, p_ra->ratr_state);
 960
 961			rcu_read_lock();
 962			sta = rtl_find_sta(hw, mac->bssid);
 963			if (sta)
 964				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 965							   p_ra->ratr_state,
 966							   true);
 967			rcu_read_unlock();
 968
 969			p_ra->pre_ratr_state = p_ra->ratr_state;
 970		}
 971	}
 972}
 973
 974static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
 975{
 976	struct rtl_priv *rtlpriv = rtl_priv(hw);
 977
 978	if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
 979		return true;
 980
 981	return false;
 982}
 983
 984static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
 985{
 986	struct rtl_priv *rtlpriv = rtl_priv(hw);
 987	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 988
 989	static u64 last_txok_cnt;
 990	static u64 last_rxok_cnt;
 991	u64 cur_txok_cnt = 0;
 992	u64 cur_rxok_cnt = 0;
 993	u32 edca_be_ul = 0x6ea42b;
 994	u32 edca_be_dl = 0x6ea42b;/*not sure*/
 995	u32 edca_be = 0x5ea42b;
 996	u32 iot_peer = 0;
 997	bool b_is_cur_rdlstate;
 998	bool b_bias_on_rx = false;
 999	bool b_edca_turbo_on = false;
1000
1001	cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1002	cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1003
1004	iot_peer = rtlpriv->mac80211.vendor;
1005	b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1006		       true : false;
1007	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1008			   (!rtlpriv->dm.disable_framebursting)) ?
1009			   true : false;
1010
1011	if ((iot_peer == PEER_CISCO) &&
1012	    (mac->mode == WIRELESS_MODE_N_24G)) {
1013		edca_be_dl = edca_setting_dl[iot_peer];
1014		edca_be_ul = edca_setting_ul[iot_peer];
1015	}
1016	if (rtl8723be_dm_is_edca_turbo_disable(hw))
1017		goto exit;
1018
1019	if (b_edca_turbo_on) {
1020		if (b_bias_on_rx)
1021			b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1022					    false : true;
1023		else
1024			b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1025					    true : false;
1026
1027		edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1028		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1029		rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1030		rtlpriv->dm.current_turbo_edca = true;
1031	} else {
1032		if (rtlpriv->dm.current_turbo_edca) {
1033			u8 tmp = AC0_BE;
1034			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1035						      (u8 *)(&tmp));
1036		}
1037		rtlpriv->dm.current_turbo_edca = false;
1038	}
1039
1040exit:
1041	rtlpriv->dm.is_any_nonbepkts = false;
1042	last_txok_cnt = rtlpriv->stats.txbytesunicast;
1043	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1044}
1045
1046static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1047{
1048	struct rtl_priv *rtlpriv = rtl_priv(hw);
1049	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1050	u8 cur_cck_cca_thresh;
1051
1052	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1053		if (dm_digtable->rssi_val_min > 25) {
1054			cur_cck_cca_thresh = 0xcd;
1055		} else if ((dm_digtable->rssi_val_min <= 25) &&
1056			   (dm_digtable->rssi_val_min > 10)) {
1057			cur_cck_cca_thresh = 0x83;
1058		} else {
1059			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1060				cur_cck_cca_thresh = 0x83;
1061			else
1062				cur_cck_cca_thresh = 0x40;
1063		}
1064	} else {
1065		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1066			cur_cck_cca_thresh = 0x83;
1067		else
1068			cur_cck_cca_thresh = 0x40;
1069	}
1070
1071	if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1072		rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1073
1074	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1075	dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1076	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
1077		"CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1078}
1079
1080static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1081{
1082	struct rtl_priv *rtlpriv = rtl_priv(hw);
1083	u8 reg_c50, reg_c58;
1084	bool fw_current_in_ps_mode = false;
1085
1086	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1087				      (u8 *)(&fw_current_in_ps_mode));
1088	if (fw_current_in_ps_mode)
1089		return;
1090
1091	reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1092	reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1093
1094	if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1095		if (!rtlpriv->rtlhal.pre_edcca_enable) {
1096			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1097			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1098		}
1099	} else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1100		if (rtlpriv->rtlhal.pre_edcca_enable) {
1101			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1102			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1103		}
1104	}
1105}
1106
1107static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1108{
1109	struct rtl_priv *rtlpriv = rtl_priv(hw);
1110	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1111	u8 crystal_cap;
1112	u32 packet_count;
1113	int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1114	int cfo_ave_diff;
1115
1116	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1117		if (rtldm->atc_status == ATC_STATUS_OFF) {
1118			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1119				      ATC_STATUS_ON);
1120			rtldm->atc_status = ATC_STATUS_ON;
1121		}
1122		if (rtlpriv->cfg->ops->get_btc_status()) {
1123			if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1124				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1125					"odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1126				return;
1127			}
1128		}
1129
1130		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1131			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1132			crystal_cap = rtldm->crystal_cap & 0x3f;
1133			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1134				      (crystal_cap | (crystal_cap << 6)));
1135		}
1136	} else {
1137		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1138		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1139		packet_count = rtldm->packet_count;
1140
1141		if (packet_count == rtldm->packet_count_pre)
1142			return;
1143
1144		rtldm->packet_count_pre = packet_count;
1145
1146		if (rtlpriv->phy.rf_type == RF_1T1R)
1147			cfo_ave = cfo_khz_a;
1148		else
1149			cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1150
1151		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1152			       (rtldm->cfo_ave_pre - cfo_ave) :
1153			       (cfo_ave - rtldm->cfo_ave_pre);
1154
1155		if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
1156			rtldm->large_cfo_hit = true;
1157			return;
1158		} else
1159			rtldm->large_cfo_hit = false;
1160
1161		rtldm->cfo_ave_pre = cfo_ave;
1162
1163		if (cfo_ave >= -rtldm->cfo_threshold &&
1164		    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1165			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1166				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1167				rtldm->is_freeze = 1;
1168			} else {
1169				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1170			}
1171		}
1172
1173		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1174			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1175		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1176					rtlpriv->dm.crystal_cap > 0)
1177			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1178
1179		if (adjust_xtal != 0) {
1180			rtldm->is_freeze = 0;
1181			rtldm->crystal_cap += adjust_xtal;
1182
1183			if (rtldm->crystal_cap > 0x3f)
1184				rtldm->crystal_cap = 0x3f;
1185			else if (rtldm->crystal_cap < 0)
1186				rtldm->crystal_cap = 0;
1187
1188			crystal_cap = rtldm->crystal_cap & 0x3f;
1189			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1190				      (crystal_cap | (crystal_cap << 6)));
1191		}
1192
1193		if (cfo_ave < CFO_THRESHOLD_ATC &&
1194		    cfo_ave > -CFO_THRESHOLD_ATC) {
1195			if (rtldm->atc_status == ATC_STATUS_ON) {
1196				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1197					      ATC_STATUS_OFF);
1198				rtldm->atc_status = ATC_STATUS_OFF;
1199			}
1200		} else {
1201			if (rtldm->atc_status == ATC_STATUS_OFF) {
1202				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1203					      ATC_STATUS_ON);
1204				rtldm->atc_status = ATC_STATUS_ON;
1205			}
1206		}
1207	}
1208}
1209
1210static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1211{
1212	struct rtl_priv *rtlpriv = rtl_priv(hw);
1213	u8 cnt;
1214
1215	rtlpriv->dm.one_entry_only = false;
1216
1217	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1218		rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1219		rtlpriv->dm.one_entry_only = true;
1220		return;
1221	}
1222
1223	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1224		rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1225		rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1226		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1227		cnt = list_count_nodes(&rtlpriv->entry_list);
1228		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1229
1230		if (cnt == 1)
1231			rtlpriv->dm.one_entry_only = true;
1232	}
1233}
1234
1235void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1236{
1237	struct rtl_priv *rtlpriv = rtl_priv(hw);
1238	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1239	bool fw_current_inpsmode = false;
1240	bool fw_ps_awake = true;
1241
1242	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1243				      (u8 *)(&fw_current_inpsmode));
1244
1245	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1246				      (u8 *)(&fw_ps_awake));
1247
1248	if (ppsc->p2p_ps_info.p2p_ps_mode)
1249		fw_ps_awake = false;
1250
1251	spin_lock(&rtlpriv->locks.rf_ps_lock);
1252	if ((ppsc->rfpwr_state == ERFON) &&
1253		((!fw_current_inpsmode) && fw_ps_awake) &&
1254		(!ppsc->rfchange_inprogress)) {
1255		rtl8723be_dm_common_info_self_update(hw);
1256		rtl8723be_dm_false_alarm_counter_statistics(hw);
1257		rtl8723be_dm_check_rssi_monitor(hw);
1258		rtl8723be_dm_dig(hw);
1259		rtl8723be_dm_dynamic_edcca(hw);
1260		rtl8723be_dm_cck_packet_detection_thresh(hw);
1261		rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1262		rtl8723be_dm_check_edca_turbo(hw);
1263		rtl8723be_dm_dynamic_atc_switch(hw);
1264		rtl8723be_dm_check_txpower_tracking(hw);
1265		rtl8723be_dm_dynamic_txpower(hw);
1266	}
1267	spin_unlock(&rtlpriv->locks.rf_ps_lock);
1268	rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1269}
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2014  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 "../pci.h"
  29#include "../core.h"
  30#include "reg.h"
  31#include "def.h"
  32#include "phy.h"
  33#include "dm.h"
  34#include "../rtl8723com/dm_common.h"
  35#include "fw.h"
  36#include "trx.h"
  37#include "../btcoexist/rtl_btc.h"
  38
  39static const u32 ofdmswing_table[] = {
  40	0x0b40002d, /* 0,  -15.0dB */
  41	0x0c000030, /* 1,  -14.5dB */
  42	0x0cc00033, /* 2,  -14.0dB */
  43	0x0d800036, /* 3,  -13.5dB */
  44	0x0e400039, /* 4,  -13.0dB */
  45	0x0f00003c, /* 5,  -12.5dB */
  46	0x10000040, /* 6,  -12.0dB */
  47	0x11000044, /* 7,  -11.5dB */
  48	0x12000048, /* 8,  -11.0dB */
  49	0x1300004c, /* 9,  -10.5dB */
  50	0x14400051, /* 10, -10.0dB */
  51	0x15800056, /* 11, -9.5dB */
  52	0x16c0005b, /* 12, -9.0dB */
  53	0x18000060, /* 13, -8.5dB */
  54	0x19800066, /* 14, -8.0dB */
  55	0x1b00006c, /* 15, -7.5dB */
  56	0x1c800072, /* 16, -7.0dB */
  57	0x1e400079, /* 17, -6.5dB */
  58	0x20000080, /* 18, -6.0dB */
  59	0x22000088, /* 19, -5.5dB */
  60	0x24000090, /* 20, -5.0dB */
  61	0x26000098, /* 21, -4.5dB */
  62	0x288000a2, /* 22, -4.0dB */
  63	0x2ac000ab, /* 23, -3.5dB */
  64	0x2d4000b5, /* 24, -3.0dB */
  65	0x300000c0, /* 25, -2.5dB */
  66	0x32c000cb, /* 26, -2.0dB */
  67	0x35c000d7, /* 27, -1.5dB */
  68	0x390000e4, /* 28, -1.0dB */
  69	0x3c8000f2, /* 29, -0.5dB */
  70	0x40000100, /* 30, +0dB */
  71	0x43c0010f, /* 31, +0.5dB */
  72	0x47c0011f, /* 32, +1.0dB */
  73	0x4c000130, /* 33, +1.5dB */
  74	0x50800142, /* 34, +2.0dB */
  75	0x55400155, /* 35, +2.5dB */
  76	0x5a400169, /* 36, +3.0dB */
  77	0x5fc0017f, /* 37, +3.5dB */
  78	0x65400195, /* 38, +4.0dB */
  79	0x6b8001ae, /* 39, +4.5dB */
  80	0x71c001c7, /* 40, +5.0dB */
  81	0x788001e2, /* 41, +5.5dB */
  82	0x7f8001fe  /* 42, +6.0dB */
  83};
  84
  85static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
  86	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /*  0, -16.0dB */
  87	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /*  1, -15.5dB */
  88	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  2, -15.0dB */
  89	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  3, -14.5dB */
  90	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  4, -14.0dB */
  91	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  5, -13.5dB */
  92	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /*  6, -13.0dB */
  93	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /*  7, -12.5dB */
  94	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /*  8, -12.0dB */
  95	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /*  9, -11.5dB */
  96	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
  97	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
  98	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
  99	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
 100	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
 101	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
 102	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
 103	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
 104	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
 105	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
 106	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
 107	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
 108	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
 109	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
 110	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
 111	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
 112	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
 113	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
 114	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
 115	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
 116	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
 117	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
 118	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}  /* 32, +0dB */
 119};
 120
 121static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 122	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /*  0, -16.0dB */
 123	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  1, -15.5dB */
 124	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  2, -15.0dB */
 125	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  3, -14.5dB */
 126	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  4, -14.0dB */
 127	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  5, -13.5dB */
 128	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  6, -13.0dB */
 129	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  7, -12.5dB */
 130	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  8, -12.0dB */
 131	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  9, -11.5dB */
 132	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
 133	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
 134	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
 135	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
 136	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
 137	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
 138	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
 139	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
 140	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
 141	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
 142	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
 143	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
 144	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
 145	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
 146	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
 147	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
 148	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
 149	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
 150	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
 151	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
 152	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
 153	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
 154	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}  /* 32, +0dB */
 155};
 156
 157static const u32 edca_setting_dl[PEER_MAX] = {
 158	0xa44f,		/* 0 UNKNOWN */
 159	0x5ea44f,	/* 1 REALTEK_90 */
 160	0x5e4322,	/* 2 REALTEK_92SE */
 161	0x5ea42b,	/* 3 BROAD */
 162	0xa44f,		/* 4 RAL */
 163	0xa630,		/* 5 ATH */
 164	0x5ea630,	/* 6 CISCO */
 165	0x5ea42b,	/* 7 MARVELL */
 166};
 167
 168static const u32 edca_setting_ul[PEER_MAX] = {
 169	0x5e4322,	/* 0 UNKNOWN */
 170	0xa44f,		/* 1 REALTEK_90 */
 171	0x5ea44f,	/* 2 REALTEK_92SE */
 172	0x5ea32b,	/* 3 BROAD */
 173	0x5ea422,	/* 4 RAL */
 174	0x5ea322,	/* 5 ATH */
 175	0x3ea430,	/* 6 CISCO */
 176	0x5ea44f,	/* 7 MARV */
 177};
 178
 179void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
 180				       u8 *pdirection, u32 *poutwrite_val)
 181{
 182	struct rtl_priv *rtlpriv = rtl_priv(hw);
 183	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 184	u8 pwr_val = 0;
 185	u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
 186	u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
 187	u8 cck_base = rtldm->swing_idx_cck_base;
 188	u8 cck_val = rtldm->swing_idx_cck;
 189
 190	if (type == 0) {
 191		if (ofdm_val <= ofdm_base) {
 192			*pdirection = 1;
 193			pwr_val = ofdm_base - ofdm_val;
 194		} else {
 195			*pdirection = 2;
 196			pwr_val = ofdm_val - ofdm_base;
 197		}
 198	} else if (type == 1) {
 199		if (cck_val <= cck_base) {
 200			*pdirection = 1;
 201			pwr_val = cck_base - cck_val;
 202		} else {
 203			*pdirection = 2;
 204			pwr_val = cck_val - cck_base;
 205		}
 206	}
 207
 208	if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 209		pwr_val = TXPWRTRACK_MAX_IDX;
 210
 211	*poutwrite_val = pwr_val | (pwr_val << 8) |
 212		(pwr_val << 16) | (pwr_val << 24);
 213}
 214
 215void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 216{
 217	struct rtl_priv *rtlpriv = rtl_priv(hw);
 218	struct rate_adaptive *p_ra = &rtlpriv->ra;
 219
 220	p_ra->ratr_state = DM_RATR_STA_INIT;
 221	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 222
 223	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 224		rtlpriv->dm.useramask = true;
 225	else
 226		rtlpriv->dm.useramask = false;
 227
 228	p_ra->high_rssi_thresh_for_ra = 50;
 229	p_ra->low_rssi_thresh_for_ra40m = 20;
 230}
 231
 232static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
 233{
 234	struct rtl_priv *rtlpriv = rtl_priv(hw);
 235
 236	rtlpriv->dm.txpower_tracking = true;
 237	rtlpriv->dm.txpower_track_control = true;
 238	rtlpriv->dm.thermalvalue = 0;
 239
 240	rtlpriv->dm.ofdm_index[0] = 30;
 241	rtlpriv->dm.cck_index = 20;
 242
 243	rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
 244
 245	rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
 246	rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
 247	rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
 248	rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
 249
 250	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 251		 "  rtlpriv->dm.txpower_tracking = %d\n",
 252		  rtlpriv->dm.txpower_tracking);
 253}
 254
 255static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 256{
 257	struct rtl_priv *rtlpriv = rtl_priv(hw);
 258
 259	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 260
 261	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
 262	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 263}
 264
 265void rtl8723be_dm_init(struct ieee80211_hw *hw)
 266{
 267	struct rtl_priv *rtlpriv = rtl_priv(hw);
 268	u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 269
 270	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 271	rtl_dm_diginit(hw, cur_igvalue);
 272	rtl8723be_dm_init_rate_adaptive_mask(hw);
 273	rtl8723_dm_init_edca_turbo(hw);
 274	rtl8723_dm_init_dynamic_bb_powersaving(hw);
 275	rtl8723_dm_init_dynamic_txpower(hw);
 276	rtl8723be_dm_init_txpower_tracking(hw);
 277	rtl8723be_dm_init_dynamic_atc_switch(hw);
 278}
 279
 280static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 281{
 282	struct rtl_priv *rtlpriv = rtl_priv(hw);
 283	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 284	struct rtl_mac *mac = rtl_mac(rtlpriv);
 285
 286	/* Determine the minimum RSSI  */
 287	if ((mac->link_state < MAC80211_LINKED) &&
 288	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 289		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 290		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 291			 "Not connected to any\n");
 292	}
 293	if (mac->link_state >= MAC80211_LINKED) {
 294		if (mac->opmode == NL80211_IFTYPE_AP ||
 295		    mac->opmode == NL80211_IFTYPE_ADHOC) {
 296			rtl_dm_dig->min_undec_pwdb_for_dm =
 297			    rtlpriv->dm.entry_min_undec_sm_pwdb;
 298			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 299				 "AP Client PWDB = 0x%lx\n",
 300			       rtlpriv->dm.entry_min_undec_sm_pwdb);
 301		} else {
 302			rtl_dm_dig->min_undec_pwdb_for_dm =
 303			    rtlpriv->dm.undec_sm_pwdb;
 304			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 305				 "STA Default Port PWDB = 0x%x\n",
 306				  rtl_dm_dig->min_undec_pwdb_for_dm);
 307		}
 308	} else {
 309		rtl_dm_dig->min_undec_pwdb_for_dm =
 310				rtlpriv->dm.entry_min_undec_sm_pwdb;
 311		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 312			 "AP Ext Port or disconnect PWDB = 0x%x\n",
 313			  rtl_dm_dig->min_undec_pwdb_for_dm);
 314	}
 315	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
 316		 rtl_dm_dig->min_undec_pwdb_for_dm);
 317}
 318
 319static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 320{
 321	struct rtl_priv *rtlpriv = rtl_priv(hw);
 322	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 323	struct rtl_sta_info *drv_priv;
 324	u8 h2c_parameter[3] = { 0 };
 325	long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 326
 327	/* AP & ADHOC & MESH */
 328	spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 329	list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 330		if (drv_priv->rssi_stat.undec_sm_pwdb <
 331						tmp_entry_min_pwdb)
 332			tmp_entry_min_pwdb =
 333				drv_priv->rssi_stat.undec_sm_pwdb;
 334		if (drv_priv->rssi_stat.undec_sm_pwdb >
 335						tmp_entry_max_pwdb)
 336			tmp_entry_max_pwdb =
 337				drv_priv->rssi_stat.undec_sm_pwdb;
 338	}
 339	spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 340
 341	/* If associated entry is found */
 342	if (tmp_entry_max_pwdb != 0) {
 343		rtlpriv->dm.entry_max_undec_sm_pwdb =
 344							tmp_entry_max_pwdb;
 345		RTPRINT(rtlpriv, FDM, DM_PWDB,
 346			"EntryMaxPWDB = 0x%lx(%ld)\n",
 347			 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 348	} else {
 349		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 350	}
 351	/* If associated entry is found */
 352	if (tmp_entry_min_pwdb != 0xff) {
 353		rtlpriv->dm.entry_min_undec_sm_pwdb =
 354							tmp_entry_min_pwdb;
 355		RTPRINT(rtlpriv, FDM, DM_PWDB,
 356			"EntryMinPWDB = 0x%lx(%ld)\n",
 357			 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 358	} else {
 359		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 360	}
 361	/* Indicate Rx signal strength to FW. */
 362	if (rtlpriv->dm.useramask) {
 363		h2c_parameter[2] =
 364			(u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 365		h2c_parameter[1] = 0x20;
 366		h2c_parameter[0] = 0;
 367		rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
 368	} else {
 369		rtl_write_byte(rtlpriv, 0x4fe,
 370			       rtlpriv->dm.undec_sm_pwdb);
 371	}
 372	rtl8723be_dm_find_minimum_rssi(hw);
 373	dm_digtable->rssi_val_min =
 374			rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 375}
 376
 377void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 378{
 379	struct rtl_priv *rtlpriv = rtl_priv(hw);
 380	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 381
 382	if (dm_digtable->stop_dig)
 383		return;
 384
 385	if (dm_digtable->cur_igvalue != current_igi) {
 386		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
 387		if (rtlpriv->phy.rf_type != RF_1T1R)
 388			rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
 389				      0x7f, current_igi);
 390	}
 391	dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
 392	dm_digtable->cur_igvalue = current_igi;
 393}
 394
 395static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
 396{
 397	struct rtl_priv *rtlpriv = rtl_priv(hw);
 398	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 399	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 400	u8 dig_min_0, dig_maxofmin;
 401	bool bfirstconnect, bfirstdisconnect;
 402	u8 dm_dig_max, dm_dig_min;
 403	u8 current_igi = dm_digtable->cur_igvalue;
 404	u8 offset;
 405
 406	/* AP,BT */
 407	if (mac->act_scanning)
 408		return;
 409
 410	dig_min_0 = dm_digtable->dig_min_0;
 411	bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
 412			!dm_digtable->media_connect_0;
 413	bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
 414			(dm_digtable->media_connect_0);
 415
 416	dm_dig_max = 0x5a;
 417	dm_dig_min = DM_DIG_MIN;
 418	dig_maxofmin = DM_DIG_MAX_AP;
 419
 420	if (mac->link_state >= MAC80211_LINKED) {
 421		if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
 422			dm_digtable->rx_gain_max = dm_dig_max;
 423		else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
 424			dm_digtable->rx_gain_max = dm_dig_min;
 425		else
 426			dm_digtable->rx_gain_max =
 427				dm_digtable->rssi_val_min + 10;
 428
 429		if (rtlpriv->dm.one_entry_only) {
 430			offset = 12;
 431			if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 432				dig_min_0 = dm_dig_min;
 433			else if (dm_digtable->rssi_val_min - offset >
 434							dig_maxofmin)
 435				dig_min_0 = dig_maxofmin;
 436			else
 437				dig_min_0 =
 438					dm_digtable->rssi_val_min - offset;
 439		} else {
 440			dig_min_0 = dm_dig_min;
 441		}
 442
 443	} else {
 444		dm_digtable->rx_gain_max = dm_dig_max;
 445		dig_min_0 = dm_dig_min;
 446		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
 447	}
 448
 449	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 450		if (dm_digtable->large_fa_hit != 3)
 451			dm_digtable->large_fa_hit++;
 452		if (dm_digtable->forbidden_igi < current_igi) {
 453			dm_digtable->forbidden_igi = current_igi;
 454			dm_digtable->large_fa_hit = 1;
 455		}
 456
 457		if (dm_digtable->large_fa_hit >= 3) {
 458			if ((dm_digtable->forbidden_igi + 1) >
 459			     dm_digtable->rx_gain_max)
 460				dm_digtable->rx_gain_min =
 461						dm_digtable->rx_gain_max;
 462			else
 463				dm_digtable->rx_gain_min =
 464						dm_digtable->forbidden_igi + 1;
 465			dm_digtable->recover_cnt = 3600;
 466		}
 467	} else {
 468		if (dm_digtable->recover_cnt != 0) {
 469			dm_digtable->recover_cnt--;
 470		} else {
 471			if (dm_digtable->large_fa_hit < 3) {
 472				if ((dm_digtable->forbidden_igi - 1) <
 473				     dig_min_0) {
 474					dm_digtable->forbidden_igi =
 475							dig_min_0;
 476					dm_digtable->rx_gain_min =
 477							dig_min_0;
 478				} else {
 479					dm_digtable->forbidden_igi--;
 480					dm_digtable->rx_gain_min =
 481						dm_digtable->forbidden_igi + 1;
 482				}
 483			} else {
 484				dm_digtable->large_fa_hit = 0;
 485			}
 486		}
 487	}
 488	if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 489		dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 490
 491	if (mac->link_state >= MAC80211_LINKED) {
 492		if (bfirstconnect) {
 493			if (dm_digtable->rssi_val_min <= dig_maxofmin)
 494				current_igi = dm_digtable->rssi_val_min;
 495			else
 496				current_igi = dig_maxofmin;
 497
 498			dm_digtable->large_fa_hit = 0;
 499		} else {
 500			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 501				current_igi += 4;
 502			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 503				current_igi += 2;
 504			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 505				current_igi -= 2;
 506		}
 507	} else {
 508		if (bfirstdisconnect) {
 509			current_igi = dm_digtable->rx_gain_min;
 510		} else {
 511			if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 512				current_igi += 4;
 513			else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
 514				current_igi += 2;
 515			else if (rtlpriv->falsealm_cnt.cnt_all < 500)
 516				current_igi -= 2;
 517		}
 518	}
 519
 520	if (current_igi > dm_digtable->rx_gain_max)
 521		current_igi = dm_digtable->rx_gain_max;
 522	else if (current_igi < dm_digtable->rx_gain_min)
 523		current_igi = dm_digtable->rx_gain_min;
 524
 525	rtl8723be_dm_write_dig(hw, current_igi);
 526	dm_digtable->media_connect_0 =
 527		((mac->link_state >= MAC80211_LINKED) ? true : false);
 528	dm_digtable->dig_min_0 = dig_min_0;
 529}
 530
 531static void rtl8723be_dm_false_alarm_counter_statistics(
 532					struct ieee80211_hw *hw)
 533{
 534	u32 ret_value;
 535	struct rtl_priv *rtlpriv = rtl_priv(hw);
 536	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 537
 538	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
 539	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
 540
 541	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
 542	falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
 543	falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
 544
 545	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
 546	falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
 547	falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
 548
 549	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
 550	falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
 551	falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
 552
 553	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
 554	falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
 555
 556	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
 557				      falsealm_cnt->cnt_rate_illegal +
 558				      falsealm_cnt->cnt_crc8_fail +
 559				      falsealm_cnt->cnt_mcs_fail +
 560				      falsealm_cnt->cnt_fast_fsync_fail +
 561				      falsealm_cnt->cnt_sb_search_fail;
 562
 563	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
 564	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
 565
 566	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
 567	falsealm_cnt->cnt_cck_fail = ret_value;
 568
 569	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
 570	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 571
 572	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
 573	falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
 574				    ((ret_value & 0xff00) >> 8);
 575
 576	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
 577				falsealm_cnt->cnt_sb_search_fail +
 578				falsealm_cnt->cnt_parity_fail +
 579				falsealm_cnt->cnt_rate_illegal +
 580				falsealm_cnt->cnt_crc8_fail +
 581				falsealm_cnt->cnt_mcs_fail +
 582				falsealm_cnt->cnt_cck_fail;
 583
 584	falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
 585				    falsealm_cnt->cnt_cck_cca;
 586
 587	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
 588	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
 589	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
 590	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
 591
 592	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
 593	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
 594
 595	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
 596	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
 597
 598	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
 599	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
 600
 601	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 602		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 603		 falsealm_cnt->cnt_parity_fail,
 604		 falsealm_cnt->cnt_rate_illegal,
 605		 falsealm_cnt->cnt_crc8_fail,
 606		 falsealm_cnt->cnt_mcs_fail);
 607
 608	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 609		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 610		 falsealm_cnt->cnt_ofdm_fail,
 611		 falsealm_cnt->cnt_cck_fail,
 612		 falsealm_cnt->cnt_all);
 613}
 614
 615static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
 616{
 617	/* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
 618	return;
 619}
 620
 621static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
 622				     u8 rfpath, long iqk_result_x,
 623				     long iqk_result_y)
 624{
 625	long ele_a = 0, ele_d, ele_c = 0, value32;
 626
 627	if (ofdm_index >= 43)
 628		ofdm_index = 43 - 1;
 629
 630	ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
 631
 632	if (iqk_result_x != 0) {
 633		if ((iqk_result_x & 0x00000200) != 0)
 634			iqk_result_x = iqk_result_x | 0xFFFFFC00;
 635		ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
 636
 637		if ((iqk_result_y & 0x00000200) != 0)
 638			iqk_result_y = iqk_result_y | 0xFFFFFC00;
 639		ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
 640
 641		switch (rfpath) {
 642		case RF90_PATH_A:
 643			value32 = (ele_d << 22) |
 644				((ele_c & 0x3F) << 16) | ele_a;
 645			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 646				      value32);
 647			value32 = (ele_c & 0x000003C0) >> 6;
 648			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
 649			value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
 650			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
 651				      value32);
 652			break;
 653		default:
 654			break;
 655		}
 656	} else {
 657		switch (rfpath) {
 658		case RF90_PATH_A:
 659			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
 660				      ofdmswing_table[ofdm_index]);
 661			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
 662			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
 663			break;
 664		default:
 665			break;
 666		}
 667	}
 668}
 669
 670static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
 671					enum pwr_track_control_method method,
 672					u8 rfpath, u8 idx)
 673{
 674	struct rtl_priv *rtlpriv = rtl_priv(hw);
 675	struct rtl_phy *rtlphy = &rtlpriv->phy;
 676	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 677	u8 swing_idx_ofdm_limit = 36;
 678
 679	if (method == TXAGC) {
 680		rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
 681	} else if (method == BBSWING) {
 682		if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
 683			rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
 684
 685		if (!rtldm->cck_inch14) {
 686			rtl_write_byte(rtlpriv, 0xa22,
 687			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
 688			rtl_write_byte(rtlpriv, 0xa23,
 689			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
 690			rtl_write_byte(rtlpriv, 0xa24,
 691			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
 692			rtl_write_byte(rtlpriv, 0xa25,
 693			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
 694			rtl_write_byte(rtlpriv, 0xa26,
 695			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
 696			rtl_write_byte(rtlpriv, 0xa27,
 697			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
 698			rtl_write_byte(rtlpriv, 0xa28,
 699			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
 700			rtl_write_byte(rtlpriv, 0xa29,
 701			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
 702		} else {
 703			rtl_write_byte(rtlpriv, 0xa22,
 704			    cckswing_table_ch14[rtldm->swing_idx_cck][0]);
 705			rtl_write_byte(rtlpriv, 0xa23,
 706			    cckswing_table_ch14[rtldm->swing_idx_cck][1]);
 707			rtl_write_byte(rtlpriv, 0xa24,
 708			    cckswing_table_ch14[rtldm->swing_idx_cck][2]);
 709			rtl_write_byte(rtlpriv, 0xa25,
 710			    cckswing_table_ch14[rtldm->swing_idx_cck][3]);
 711			rtl_write_byte(rtlpriv, 0xa26,
 712			    cckswing_table_ch14[rtldm->swing_idx_cck][4]);
 713			rtl_write_byte(rtlpriv, 0xa27,
 714			    cckswing_table_ch14[rtldm->swing_idx_cck][5]);
 715			rtl_write_byte(rtlpriv, 0xa28,
 716			    cckswing_table_ch14[rtldm->swing_idx_cck][6]);
 717			rtl_write_byte(rtlpriv, 0xa29,
 718			    cckswing_table_ch14[rtldm->swing_idx_cck][7]);
 719		}
 720
 721		if (rfpath == RF90_PATH_A) {
 722			if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
 723			    swing_idx_ofdm_limit)
 724				swing_idx_ofdm_limit =
 725					rtldm->swing_idx_ofdm[RF90_PATH_A];
 726
 727			rtl8723be_set_iqk_matrix(hw,
 728				rtldm->swing_idx_ofdm[rfpath], rfpath,
 729				rtlphy->iqk_matrix[idx].value[0][0],
 730				rtlphy->iqk_matrix[idx].value[0][1]);
 731		} else if (rfpath == RF90_PATH_B) {
 732			if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
 733			    swing_idx_ofdm_limit)
 734				swing_idx_ofdm_limit =
 735					rtldm->swing_idx_ofdm[RF90_PATH_B];
 736
 737			rtl8723be_set_iqk_matrix(hw,
 738				rtldm->swing_idx_ofdm[rfpath], rfpath,
 739				rtlphy->iqk_matrix[idx].value[0][4],
 740				rtlphy->iqk_matrix[idx].value[0][5]);
 741		}
 742	} else {
 743		return;
 744	}
 745}
 746
 747static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
 748							struct ieee80211_hw *hw)
 749{
 750	struct rtl_priv *rtlpriv = rtl_priv(hw);
 751	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 752	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
 753	u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
 754	u8 thermalvalue_avg_count = 0;
 755	u32 thermalvalue_avg = 0;
 756	int i = 0;
 757
 758	u8 ofdm_min_index = 6;
 759	u8 index_for_channel = 0;
 760
 761	s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
 762		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 763		5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
 764		10, 11, 11, 12, 12, 13, 14, 15};
 765	s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
 766		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
 767		5, 6, 6, 6, 6, 7, 7, 7, 8, 8,  9,
 768		9, 10, 10, 11, 12, 13, 14, 15};
 769
 770	/*Initilization ( 7 steps in total )*/
 771	rtlpriv->dm.txpower_trackinginit = true;
 772	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 773		 "rtl8723be_dm_txpower_tracking_callback_thermalmeter\n");
 774
 775	thermalvalue = (u8)rtl_get_rfreg(hw,
 776		RF90_PATH_A, RF_T_METER, 0xfc00);
 777	if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
 778	    rtlefuse->eeprom_thermalmeter == 0xFF)
 779		return;
 780	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 781		 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
 782		 thermalvalue, rtldm->thermalvalue,
 783		 rtlefuse->eeprom_thermalmeter);
 784	/*3 Initialize ThermalValues of RFCalibrateInfo*/
 785	if (!rtldm->thermalvalue) {
 786		rtlpriv->dm.thermalvalue_lck = thermalvalue;
 787		rtlpriv->dm.thermalvalue_iqk = thermalvalue;
 788	}
 789
 790	/*4 Calculate average thermal meter*/
 791	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
 792	rtldm->thermalvalue_avg_index++;
 793	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
 794		rtldm->thermalvalue_avg_index = 0;
 795
 796	for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
 797		if (rtldm->thermalvalue_avg[i]) {
 798			thermalvalue_avg += rtldm->thermalvalue_avg[i];
 799			thermalvalue_avg_count++;
 800		}
 801	}
 802
 803	if (thermalvalue_avg_count)
 804		thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
 805
 806	/* 5 Calculate delta, delta_LCK, delta_IQK.*/
 807	delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
 808		(thermalvalue - rtlpriv->dm.thermalvalue) :
 809		(rtlpriv->dm.thermalvalue - thermalvalue);
 810	delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
 811		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
 812		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
 813	delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
 814		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
 815		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
 816
 817	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 818		 "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",
 819		 thermalvalue, rtlpriv->dm.thermalvalue,
 820		 rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
 821	/* 6 If necessary, do LCK.*/
 822	if (delta_lck >= IQK_THRESHOLD) {
 823		rtlpriv->dm.thermalvalue_lck = thermalvalue;
 824		rtl8723be_phy_lc_calibrate(hw);
 825	}
 826
 827	/* 7 If necessary, move the index of
 828	 * swing table to adjust Tx power.
 829	 */
 830	if (delta > 0 && rtlpriv->dm.txpower_track_control) {
 831		delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
 832			(thermalvalue - rtlefuse->eeprom_thermalmeter) :
 833			(rtlefuse->eeprom_thermalmeter - thermalvalue);
 834
 835		if (delta >= TXSCALE_TABLE_SIZE)
 836			delta = TXSCALE_TABLE_SIZE - 1;
 837		/* 7.1 Get the final CCK_index and
 838		 * OFDM_index for each swing table.
 839		 */
 840		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
 841			rtldm->delta_power_index_last[RF90_PATH_A] =
 842					rtldm->delta_power_index[RF90_PATH_A];
 843			rtldm->delta_power_index[RF90_PATH_A] =
 844					delta_swing_table_idx_tup_a[delta];
 845		} else {
 846			rtldm->delta_power_index_last[RF90_PATH_A] =
 847					rtldm->delta_power_index[RF90_PATH_A];
 848			rtldm->delta_power_index[RF90_PATH_A] =
 849				-1 * delta_swing_table_idx_tdown_a[delta];
 850		}
 851
 852		/* 7.2 Handle boundary conditions of index.*/
 853		if (rtldm->delta_power_index[RF90_PATH_A] ==
 854		    rtldm->delta_power_index_last[RF90_PATH_A])
 855			rtldm->power_index_offset[RF90_PATH_A] = 0;
 856		else
 857			rtldm->power_index_offset[RF90_PATH_A] =
 858				rtldm->delta_power_index[RF90_PATH_A] -
 859				rtldm->delta_power_index_last[RF90_PATH_A];
 860
 861		rtldm->ofdm_index[0] =
 862			rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
 863			rtldm->power_index_offset[RF90_PATH_A];
 864		rtldm->cck_index = rtldm->swing_idx_cck_base +
 865				   rtldm->power_index_offset[RF90_PATH_A];
 866
 867		rtldm->swing_idx_cck = rtldm->cck_index;
 868		rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
 869
 870		if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
 871			rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
 872		else if (rtldm->ofdm_index[0] < ofdm_min_index)
 873			rtldm->ofdm_index[0] = ofdm_min_index;
 874
 875		if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
 876			rtldm->cck_index = CCK_TABLE_SIZE - 1;
 877		else if (rtldm->cck_index < 0)
 878			rtldm->cck_index = 0;
 879	} else {
 880		rtldm->power_index_offset[RF90_PATH_A] = 0;
 881	}
 882
 883	if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
 884	    (rtldm->txpower_track_control)) {
 885		rtldm->done_txpower = true;
 886		if (thermalvalue > rtlefuse->eeprom_thermalmeter)
 887			rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
 888							     index_for_channel);
 889		else
 890			rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
 891							     index_for_channel);
 892
 893		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
 894		rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
 895						rtldm->swing_idx_ofdm[0];
 896		rtldm->thermalvalue = thermalvalue;
 897	}
 898
 899	if (delta_iqk >= IQK_THRESHOLD) {
 900		rtldm->thermalvalue_iqk = thermalvalue;
 901		rtl8723be_phy_iq_calibrate(hw, false);
 902	}
 903
 904	rtldm->txpowercount = 0;
 905	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
 906
 907}
 908
 909void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 910{
 911	struct rtl_priv *rtlpriv = rtl_priv(hw);
 912
 913	if (!rtlpriv->dm.txpower_tracking)
 914		return;
 915
 916	if (!rtlpriv->dm.tm_trigger) {
 917		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
 918			      0x03);
 919		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 920			 "Trigger 8723be Thermal Meter!!\n");
 921		rtlpriv->dm.tm_trigger = 1;
 922		return;
 923	} else {
 924		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 925			 "Schedule TxPowerTracking !!\n");
 926		rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
 927		rtlpriv->dm.tm_trigger = 0;
 928	}
 929}
 930
 931static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 932{
 933	struct rtl_priv *rtlpriv = rtl_priv(hw);
 934	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 935	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 936	struct rate_adaptive *p_ra = &rtlpriv->ra;
 937	u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
 938	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
 939	u8 go_up_gap = 5;
 940	struct ieee80211_sta *sta = NULL;
 941
 942	if (is_hal_stop(rtlhal)) {
 943		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 944			 "driver is going to unload\n");
 945		return;
 946	}
 947
 948	if (!rtlpriv->dm.useramask) {
 949		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 950			 "driver does not control rate adaptive mask\n");
 951		return;
 952	}
 953
 954	if (mac->link_state == MAC80211_LINKED &&
 955		mac->opmode == NL80211_IFTYPE_STATION) {
 956		switch (p_ra->pre_ratr_state) {
 957		case DM_RATR_STA_MIDDLE:
 958			high_rssithresh_for_ra += go_up_gap;
 959			break;
 960		case DM_RATR_STA_LOW:
 961			high_rssithresh_for_ra += go_up_gap;
 962			low_rssithresh_for_ra += go_up_gap;
 963			break;
 964		default:
 965			break;
 966		}
 967
 968		if (rtlpriv->dm.undec_sm_pwdb >
 969		    (long)high_rssithresh_for_ra)
 970			p_ra->ratr_state = DM_RATR_STA_HIGH;
 971		else if (rtlpriv->dm.undec_sm_pwdb >
 972			 (long)low_rssithresh_for_ra)
 973			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
 974		else
 975			p_ra->ratr_state = DM_RATR_STA_LOW;
 976
 977		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
 978			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 979				 "RSSI = %ld\n",
 980				 rtlpriv->dm.undec_sm_pwdb);
 981			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 982				 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
 983			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 984				 "PreState = %d, CurState = %d\n",
 985				  p_ra->pre_ratr_state, p_ra->ratr_state);
 986
 987			rcu_read_lock();
 988			sta = rtl_find_sta(hw, mac->bssid);
 989			if (sta)
 990				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 991							   p_ra->ratr_state);
 992			rcu_read_unlock();
 993
 994			p_ra->pre_ratr_state = p_ra->ratr_state;
 995		}
 996	}
 997}
 998
 999static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
1000{
1001	struct rtl_priv *rtlpriv = rtl_priv(hw);
1002
1003	if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
1004		return true;
1005
1006	return false;
1007}
1008
1009static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
1010{
1011	struct rtl_priv *rtlpriv = rtl_priv(hw);
1012	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1013
1014	static u64 last_txok_cnt;
1015	static u64 last_rxok_cnt;
1016	u64 cur_txok_cnt = 0;
1017	u64 cur_rxok_cnt = 0;
1018	u32 edca_be_ul = 0x6ea42b;
1019	u32 edca_be_dl = 0x6ea42b;/*not sure*/
1020	u32 edca_be = 0x5ea42b;
1021	u32 iot_peer = 0;
1022	bool b_is_cur_rdlstate;
1023	bool b_last_is_cur_rdlstate = false;
1024	bool b_bias_on_rx = false;
1025	bool b_edca_turbo_on = false;
1026
1027	b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate;
1028
1029	cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1030	cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1031
1032	iot_peer = rtlpriv->mac80211.vendor;
1033	b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1034		       true : false;
1035	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1036			   (!rtlpriv->dm.disable_framebursting)) ?
1037			   true : false;
1038
1039	if ((iot_peer == PEER_CISCO) &&
1040	    (mac->mode == WIRELESS_MODE_N_24G)) {
1041		edca_be_dl = edca_setting_dl[iot_peer];
1042		edca_be_ul = edca_setting_ul[iot_peer];
1043	}
1044	if (rtl8723be_dm_is_edca_turbo_disable(hw))
1045		goto exit;
1046
1047	if (b_edca_turbo_on) {
1048		if (b_bias_on_rx)
1049			b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1050					    false : true;
1051		else
1052			b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1053					    true : false;
1054
1055		edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1056		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1057		rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1058		rtlpriv->dm.current_turbo_edca = true;
1059	} else {
1060		if (rtlpriv->dm.current_turbo_edca) {
1061			u8 tmp = AC0_BE;
1062			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1063						      (u8 *)(&tmp));
1064		}
1065		rtlpriv->dm.current_turbo_edca = false;
1066	}
1067
1068exit:
1069	rtlpriv->dm.is_any_nonbepkts = false;
1070	last_txok_cnt = rtlpriv->stats.txbytesunicast;
1071	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1072}
1073
1074static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1075{
1076	struct rtl_priv *rtlpriv = rtl_priv(hw);
1077	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1078	u8 cur_cck_cca_thresh;
1079
1080	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1081		if (dm_digtable->rssi_val_min > 25) {
1082			cur_cck_cca_thresh = 0xcd;
1083		} else if ((dm_digtable->rssi_val_min <= 25) &&
1084			   (dm_digtable->rssi_val_min > 10)) {
1085			cur_cck_cca_thresh = 0x83;
1086		} else {
1087			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1088				cur_cck_cca_thresh = 0x83;
1089			else
1090				cur_cck_cca_thresh = 0x40;
1091		}
1092	} else {
1093		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1094			cur_cck_cca_thresh = 0x83;
1095		else
1096			cur_cck_cca_thresh = 0x40;
1097	}
1098
1099	if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1100		rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1101
1102	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1103	dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1104	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
1105		 "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1106}
1107
1108static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1109{
1110	struct rtl_priv *rtlpriv = rtl_priv(hw);
1111	u8 reg_c50, reg_c58;
1112	bool fw_current_in_ps_mode = false;
1113
1114	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1115				      (u8 *)(&fw_current_in_ps_mode));
1116	if (fw_current_in_ps_mode)
1117		return;
1118
1119	reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1120	reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1121
1122	if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1123		if (!rtlpriv->rtlhal.pre_edcca_enable) {
1124			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1125			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1126		}
1127	} else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1128		if (rtlpriv->rtlhal.pre_edcca_enable) {
1129			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1130			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1131		}
1132	}
1133}
1134
1135static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1136{
1137	struct rtl_priv *rtlpriv = rtl_priv(hw);
1138	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1139	u8 crystal_cap;
1140	u32 packet_count;
1141	int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1142	int cfo_ave_diff;
1143
1144	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1145		if (rtldm->atc_status == ATC_STATUS_OFF) {
1146			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1147				      ATC_STATUS_ON);
1148			rtldm->atc_status = ATC_STATUS_ON;
1149		}
1150		if (rtlpriv->cfg->ops->get_btc_status()) {
1151			if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1152				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1153					 "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1154				return;
1155			}
1156		}
1157
1158		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1159			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1160			crystal_cap = rtldm->crystal_cap & 0x3f;
1161			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1162				      (crystal_cap | (crystal_cap << 6)));
1163		}
1164	} else {
1165		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1166		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1167		packet_count = rtldm->packet_count;
1168
1169		if (packet_count == rtldm->packet_count_pre)
1170			return;
1171
1172		rtldm->packet_count_pre = packet_count;
1173
1174		if (rtlpriv->phy.rf_type == RF_1T1R)
1175			cfo_ave = cfo_khz_a;
1176		else
1177			cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1178
1179		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1180			       (rtldm->cfo_ave_pre - cfo_ave) :
1181			       (cfo_ave - rtldm->cfo_ave_pre);
1182
1183		if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
1184			rtldm->large_cfo_hit = 1;
1185			return;
1186		} else
1187			rtldm->large_cfo_hit = 0;
1188
1189		rtldm->cfo_ave_pre = cfo_ave;
1190
1191		if (cfo_ave >= -rtldm->cfo_threshold &&
1192		    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1193			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1194				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1195				rtldm->is_freeze = 1;
1196			} else {
1197				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1198			}
1199		}
1200
1201		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1202			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1203		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1204					rtlpriv->dm.crystal_cap > 0)
1205			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1206
1207		if (adjust_xtal != 0) {
1208			rtldm->is_freeze = 0;
1209			rtldm->crystal_cap += adjust_xtal;
1210
1211			if (rtldm->crystal_cap > 0x3f)
1212				rtldm->crystal_cap = 0x3f;
1213			else if (rtldm->crystal_cap < 0)
1214				rtldm->crystal_cap = 0;
1215
1216			crystal_cap = rtldm->crystal_cap & 0x3f;
1217			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1218				      (crystal_cap | (crystal_cap << 6)));
1219		}
1220
1221		if (cfo_ave < CFO_THRESHOLD_ATC &&
1222		    cfo_ave > -CFO_THRESHOLD_ATC) {
1223			if (rtldm->atc_status == ATC_STATUS_ON) {
1224				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1225					      ATC_STATUS_OFF);
1226				rtldm->atc_status = ATC_STATUS_OFF;
1227			}
1228		} else {
1229			if (rtldm->atc_status == ATC_STATUS_OFF) {
1230				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1231					      ATC_STATUS_ON);
1232				rtldm->atc_status = ATC_STATUS_ON;
1233			}
1234		}
1235	}
1236}
1237
1238static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1239{
1240	struct rtl_priv *rtlpriv = rtl_priv(hw);
1241	u8 cnt = 0;
1242	struct rtl_sta_info *drv_priv;
1243
1244	rtlpriv->dm.one_entry_only = false;
1245
1246	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1247		rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1248		rtlpriv->dm.one_entry_only = true;
1249		return;
1250	}
1251
1252	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1253		rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1254		rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1255		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1256		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1257			cnt++;
1258		}
1259		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1260
1261		if (cnt == 1)
1262			rtlpriv->dm.one_entry_only = true;
1263	}
1264}
1265
1266void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1267{
1268	struct rtl_priv *rtlpriv = rtl_priv(hw);
1269	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1270	bool fw_current_inpsmode = false;
1271	bool fw_ps_awake = true;
1272
1273	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1274				      (u8 *)(&fw_current_inpsmode));
1275
1276	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1277				      (u8 *)(&fw_ps_awake));
1278
1279	if (ppsc->p2p_ps_info.p2p_ps_mode)
1280		fw_ps_awake = false;
1281
1282	spin_lock(&rtlpriv->locks.rf_ps_lock);
1283	if ((ppsc->rfpwr_state == ERFON) &&
1284		((!fw_current_inpsmode) && fw_ps_awake) &&
1285		(!ppsc->rfchange_inprogress)) {
1286		rtl8723be_dm_common_info_self_update(hw);
1287		rtl8723be_dm_false_alarm_counter_statistics(hw);
1288		rtl8723be_dm_check_rssi_monitor(hw);
1289		rtl8723be_dm_dig(hw);
1290		rtl8723be_dm_dynamic_edcca(hw);
1291		rtl8723be_dm_cck_packet_detection_thresh(hw);
1292		rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1293		rtl8723be_dm_check_edca_turbo(hw);
1294		rtl8723be_dm_dynamic_atc_switch(hw);
1295		rtl8723be_dm_check_txpower_tracking(hw);
1296		rtl8723be_dm_dynamic_txpower(hw);
1297	}
1298	spin_unlock(&rtlpriv->locks.rf_ps_lock);
1299	rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1300}