1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2009-2012  Realtek Corporation.*/
3
4#include "../wifi.h"
5#include "../base.h"
6#include "../core.h"
7#include "reg.h"
8#include "def.h"
9#include "phy_common.h"
10#include "dm_common.h"
11
12static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
13	0x7f8001fe,		/* 0, +6.0dB */
14	0x788001e2,		/* 1, +5.5dB */
15	0x71c001c7,		/* 2, +5.0dB */
16	0x6b8001ae,		/* 3, +4.5dB */
17	0x65400195,		/* 4, +4.0dB */
18	0x5fc0017f,		/* 5, +3.5dB */
19	0x5a400169,		/* 6, +3.0dB */
20	0x55400155,		/* 7, +2.5dB */
21	0x50800142,		/* 8, +2.0dB */
22	0x4c000130,		/* 9, +1.5dB */
23	0x47c0011f,		/* 10, +1.0dB */
24	0x43c0010f,		/* 11, +0.5dB */
25	0x40000100,		/* 12, +0dB */
26	0x3c8000f2,		/* 13, -0.5dB */
27	0x390000e4,		/* 14, -1.0dB */
28	0x35c000d7,		/* 15, -1.5dB */
29	0x32c000cb,		/* 16, -2.0dB */
30	0x300000c0,		/* 17, -2.5dB */
31	0x2d4000b5,		/* 18, -3.0dB */
32	0x2ac000ab,		/* 19, -3.5dB */
33	0x288000a2,		/* 20, -4.0dB */
34	0x26000098,		/* 21, -4.5dB */
35	0x24000090,		/* 22, -5.0dB */
36	0x22000088,		/* 23, -5.5dB */
37	0x20000080,		/* 24, -6.0dB */
38	0x1e400079,		/* 25, -6.5dB */
39	0x1c800072,		/* 26, -7.0dB */
40	0x1b00006c,		/* 27. -7.5dB */
41	0x19800066,		/* 28, -8.0dB */
42	0x18000060,		/* 29, -8.5dB */
43	0x16c0005b,		/* 30, -9.0dB */
44	0x15800056,		/* 31, -9.5dB */
45	0x14400051,		/* 32, -10.0dB */
46	0x1300004c,		/* 33, -10.5dB */
47	0x12000048,		/* 34, -11.0dB */
48	0x11000044,		/* 35, -11.5dB */
49	0x10000040,		/* 36, -12.0dB */
50	0x0f00003c,		/* 37, -12.5dB */
51	0x0e400039,		/* 38, -13.0dB */
52	0x0d800036,		/* 39, -13.5dB */
53	0x0cc00033,		/* 40, -14.0dB */
54	0x0c000030,		/* 41, -14.5dB */
55	0x0b40002d,		/* 42, -15.0dB */
56};
57
58static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
59	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},    /* 0, +0dB */
60	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},    /* 1, -0.5dB */
61	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},    /* 2, -1.0dB */
62	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},    /* 3, -1.5dB */
63	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},    /* 4, -2.0dB */
64	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},    /* 5, -2.5dB */
65	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},    /* 6, -3.0dB */
66	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},    /* 7, -3.5dB */
67	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},    /* 8, -4.0dB */
68	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},    /* 9, -4.5dB */
69	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},    /* 10, -5.0dB */
70	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},    /* 11, -5.5dB */
71	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},    /* 12, -6.0dB */
72	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},    /* 13, -6.5dB */
73	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},    /* 14, -7.0dB */
74	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},    /* 15, -7.5dB */
75	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},    /* 16, -8.0dB */
76	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},    /* 17, -8.5dB */
77	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},    /* 18, -9.0dB */
78	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 19, -9.5dB */
79	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 20, -10.0dB */
80	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 21, -10.5dB */
81	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 22, -11.0dB */
82	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},    /* 23, -11.5dB */
83	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},    /* 24, -12.0dB */
84	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},    /* 25, -12.5dB */
85	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},    /* 26, -13.0dB */
86	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 27, -13.5dB */
87	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 28, -14.0dB */
88	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 29, -14.5dB */
89	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 30, -15.0dB */
90	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},    /* 31, -15.5dB */
91	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}     /* 32, -16.0dB */
92};
93
94static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
95	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},    /* 0, +0dB */
96	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},    /* 1, -0.5dB */
97	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},    /* 2, -1.0dB */
98	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},    /* 3, -1.5dB */
99	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},    /* 4, -2.0dB */
100	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},    /* 5, -2.5dB */
101	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},    /* 6, -3.0dB */
102	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},    /* 7, -3.5dB */
103	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},    /* 8, -4.0dB */
104	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},    /* 9, -4.5dB */
105	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},    /* 10, -5.0dB */
106	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 11, -5.5dB */
107	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 12, -6.0dB */
108	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},    /* 13, -6.5dB */
109	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},    /* 14, -7.0dB */
110	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 15, -7.5dB */
111	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 16, -8.0dB */
112	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 17, -8.5dB */
113	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 18, -9.0dB */
114	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 19, -9.5dB */
115	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 20, -10.0dB */
116	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 21, -10.5dB */
117	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 22, -11.0dB */
118	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 23, -11.5dB */
119	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 24, -12.0dB */
120	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 25, -12.5dB */
121	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 26, -13.0dB */
122	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 27, -13.5dB */
123	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 28, -14.0dB */
124	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 29, -14.5dB */
125	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 30, -15.0dB */
126	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 31, -15.5dB */
127	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}     /* 32, -16.0dB */
128};
129
130static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw)
131{
132	static const u8 index_mapping[RX_INDEX_MAPPING_NUM] = {
133		0x0f, 0x0f, 0x0d, 0x0c, 0x0b,
134		0x0a, 0x09, 0x08, 0x07, 0x06,
135		0x05, 0x04, 0x04, 0x03, 0x02
136	};
137	struct rtl_priv *rtlpriv = rtl_priv(hw);
138	int i, idx;
139	u32 u4tmp;
140
141	idx = rtlpriv->efuse.eeprom_thermalmeter - rtlpriv->dm.thermalvalue_rxgain;
142	u4tmp = index_mapping[idx] << 12;
143
144	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
145		"===> Rx Gain %x\n", u4tmp);
146
147	for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++)
148		rtl_set_rfreg(hw, i, 0x3C, RFREG_OFFSET_MASK,
149			      (rtlpriv->phy.reg_rf3c[i] & ~0xF000) | u4tmp);
150}
151
152static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg,
153				 u8 *cck_index_old)
154{
155	struct rtl_priv *rtlpriv = rtl_priv(hw);
156	unsigned long flag = 0;
157	const u8 *cckswing;
158	long temp_cck;
159	int i;
160
161	/* Query CCK default setting From 0xa24 */
162	rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
163	temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2,
164				 MASKDWORD) & MASKCCK;
165	rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
166
167	for (i = 0; i < CCK_TABLE_LENGTH; i++) {
168		if (rtlpriv->dm.cck_inch14)
169			cckswing = &cckswing_table_ch14[i][2];
170		else
171			cckswing = &cckswing_table_ch1ch13[i][2];
172
173		if (temp_cck == le32_to_cpu(*((__le32 *)cckswing))) {
174			*cck_index_old = (u8)i;
175			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
176				"Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n",
177				RCCK0_TXFILTER2, temp_cck,
178				*cck_index_old,
179				rtlpriv->dm.cck_inch14);
180			break;
181		}
182	}
183	*temp_cckg = temp_cck;
184}
185
186static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index,
187			       bool *internal_pa, u8 thermalvalue, u8 delta,
188			       u8 rf, struct rtl_efuse *rtlefuse,
189			       struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy,
190			       const u8 index_mapping[5][INDEX_MAPPING_NUM],
191			       const u8 index_mapping_pa[8][INDEX_MAPPING_NUM])
192{
193	u8 offset = 0;
194	u8 index;
195	int i;
196
197	for (i = 0; i < rf; i++) {
198		if (rtlhal->macphymode == DUALMAC_DUALPHY &&
199		    rtlhal->interfaceindex == 1) /* MAC 1 5G */
200			*internal_pa = rtlefuse->internal_pa_5g[1];
201		else
202			*internal_pa = rtlefuse->internal_pa_5g[i];
203
204		if (*internal_pa) {
205			if (rtlhal->interfaceindex == 1 || i == rf)
206				offset = 4;
207			else
208				offset = 0;
209			if (rtlphy->current_channel >= 100 &&
210			    rtlphy->current_channel <= 165)
211				offset += 2;
212		} else {
213			if (rtlhal->interfaceindex == 1 || i == rf)
214				offset = 2;
215			else
216				offset = 0;
217		}
218
219		if (thermalvalue > rtlefuse->eeprom_thermalmeter)
220			offset++;
221
222		if (*internal_pa) {
223			if (delta > INDEX_MAPPING_NUM - 1)
224				index = index_mapping_pa[offset]
225						    [INDEX_MAPPING_NUM - 1];
226			else
227				index =
228				     index_mapping_pa[offset][delta];
229		} else {
230			if (delta > INDEX_MAPPING_NUM - 1)
231				index =
232				   index_mapping[offset][INDEX_MAPPING_NUM - 1];
233			else
234				index = index_mapping[offset][delta];
235		}
236
237		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
238			if (*internal_pa && thermalvalue > 0x12) {
239				ofdm_index[i] = rtlpriv->dm.ofdm_index[i] -
240						((delta / 2) * 3 + (delta % 2));
241			} else {
242				ofdm_index[i] -= index;
243			}
244		} else {
245			ofdm_index[i] += index;
246		}
247	}
248}
249
250static void
251rtl92d_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw *hw)
252{
253	static const u8 index_mapping[5][INDEX_MAPPING_NUM] = {
254		/* 5G, path A/MAC 0, decrease power  */
255		{0, 1, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
256		/* 5G, path A/MAC 0, increase power  */
257		{0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
258		/* 5G, path B/MAC 1, decrease power */
259		{0, 2, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18},
260		/* 5G, path B/MAC 1, increase power */
261		{0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
262		/* 2.4G, for decreas power */
263		{0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10},
264	};
265	static const u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = {
266		/* 5G, path A/MAC 0, ch36-64, decrease power  */
267		{0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
268		/* 5G, path A/MAC 0, ch36-64, increase power  */
269		{0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
270		/* 5G, path A/MAC 0, ch100-165, decrease power  */
271		{0, 1, 2, 3, 5, 6, 8, 10, 11, 13, 14, 15, 15},
272		/* 5G, path A/MAC 0, ch100-165, increase power  */
273		{0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18},
274		/* 5G, path B/MAC 1, ch36-64, decrease power */
275		{0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16},
276		/* 5G, path B/MAC 1, ch36-64, increase power */
277		{0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
278		/* 5G, path B/MAC 1, ch100-165, decrease power */
279		{0, 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 14},
280		/* 5G, path B/MAC 1, ch100-165, increase power */
281		{0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18},
282	};
283	struct rtl_priv *rtlpriv = rtl_priv(hw);
284	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
285	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
286	struct rtl_phy *rtlphy = &rtlpriv->phy;
287	struct rtl_dm *dm = &rtlpriv->dm;
288	u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain;
289	u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf;
290	long ele_a = 0, ele_d, temp_cck, val_x, value32;
291	bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
292	u8 offset, thermalvalue_avg_count = 0;
293	u8 ofdm_index_old[2] = {0, 0};
294	u32 thermalvalue_avg = 0;
295	bool internal_pa = false;
296	long val_y, ele_c = 0;
297	s8 cck_index_old = 0;
298	u8 indexforchannel;
299	u8 ofdm_index[2];
300	s8 cck_index = 0;
301	u8 index, swing;
302	int i;
303
304	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel);
305
306	dm->txpower_trackinginit = true;
307
308	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "\n");
309
310	thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800);
311
312	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
313		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
314		thermalvalue,
315		dm->thermalvalue, rtlefuse->eeprom_thermalmeter);
316
317	if (!thermalvalue)
318		goto exit;
319
320	if (is2t)
321		rf = 2;
322	else
323		rf = 1;
324
325	if (dm->thermalvalue && !rtlhal->reloadtxpowerindex)
326		goto old_index_done;
327
328	ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) & MASKOFDM_D;
329
330	for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
331		if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
332			ofdm_index_old[0] = (u8)i;
333
334			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
335				"Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
336				ROFDM0_XATXIQIMBALANCE,
337				ele_d, ofdm_index_old[0]);
338			break;
339		}
340	}
341
342	if (is2t) {
343		ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD);
344		ele_d &= MASKOFDM_D;
345
346		for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
347			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
348				ofdm_index_old[1] = (u8)i;
349
350				rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
351					DBG_LOUD,
352					"Initial pathB ele_d reg 0x%x = 0x%lx, ofdm_index = 0x%x\n",
353					ROFDM0_XBTXIQIMBALANCE, ele_d,
354					ofdm_index_old[1]);
355				break;
356			}
357		}
358	}
359
360	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
361		rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old);
362	} else {
363		temp_cck = 0x090e1317;
364		cck_index_old = 12;
365	}
366
367	if (!dm->thermalvalue) {
368		dm->thermalvalue = rtlefuse->eeprom_thermalmeter;
369		dm->thermalvalue_lck = thermalvalue;
370		dm->thermalvalue_iqk = thermalvalue;
371		dm->thermalvalue_rxgain = rtlefuse->eeprom_thermalmeter;
372
373		for (i = 0; i < rf; i++)
374			dm->ofdm_index[i] = ofdm_index_old[i];
375
376		dm->cck_index = cck_index_old;
377	}
378
379	if (rtlhal->reloadtxpowerindex) {
380		for (i = 0; i < rf; i++)
381			dm->ofdm_index[i] = ofdm_index_old[i];
382
383		dm->cck_index = cck_index_old;
384
385		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
386			"reload ofdm index for band switch\n");
387	}
388
389old_index_done:
390	for (i = 0; i < rf; i++)
391		ofdm_index[i] = dm->ofdm_index[i];
392
393	dm->thermalvalue_avg[dm->thermalvalue_avg_index] = thermalvalue;
394	dm->thermalvalue_avg_index++;
395
396	if (dm->thermalvalue_avg_index == AVG_THERMAL_NUM)
397		dm->thermalvalue_avg_index = 0;
398
399	for (i = 0; i < AVG_THERMAL_NUM; i++) {
400		if (dm->thermalvalue_avg[i]) {
401			thermalvalue_avg += dm->thermalvalue_avg[i];
402			thermalvalue_avg_count++;
403		}
404	}
405
406	if (thermalvalue_avg_count)
407		thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
408
409	if (rtlhal->reloadtxpowerindex) {
410		delta = abs_diff(thermalvalue, rtlefuse->eeprom_thermalmeter);
411		rtlhal->reloadtxpowerindex = false;
412		dm->done_txpower = false;
413	} else if (dm->done_txpower) {
414		delta = abs_diff(thermalvalue, dm->thermalvalue);
415	} else {
416		delta = abs_diff(thermalvalue, rtlefuse->eeprom_thermalmeter);
417	}
418
419	delta_lck = abs_diff(thermalvalue, dm->thermalvalue_lck);
420	delta_iqk = abs_diff(thermalvalue, dm->thermalvalue_iqk);
421	delta_rxgain = abs_diff(thermalvalue, dm->thermalvalue_rxgain);
422
423	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
424		"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",
425		thermalvalue, dm->thermalvalue, rtlefuse->eeprom_thermalmeter,
426		delta, delta_lck, delta_iqk);
427
428	if (delta_lck > rtlefuse->delta_lck && rtlefuse->delta_lck != 0) {
429		dm->thermalvalue_lck = thermalvalue;
430		rtlpriv->cfg->ops->phy_lc_calibrate(hw, is2t);
431	}
432
433	if (delta == 0 || !dm->txpower_track_control)
434		goto check_delta;
435
436	dm->done_txpower = true;
437	delta = abs_diff(thermalvalue, rtlefuse->eeprom_thermalmeter);
438
439	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
440		offset = 4;
441		if (delta > INDEX_MAPPING_NUM - 1)
442			index = index_mapping[offset][INDEX_MAPPING_NUM - 1];
443		else
444			index = index_mapping[offset][delta];
445
446		if (thermalvalue > dm->thermalvalue) {
447			for (i = 0; i < rf; i++)
448				ofdm_index[i] -= delta;
449
450			cck_index -= delta;
451		} else {
452			for (i = 0; i < rf; i++)
453				ofdm_index[i] += index;
454
455			cck_index += index;
456		}
457	} else if (rtlhal->current_bandtype == BAND_ON_5G) {
458		rtl92d_bandtype_5G(rtlhal, ofdm_index, &internal_pa,
459				   thermalvalue, delta, rf, rtlefuse, rtlpriv,
460				   rtlphy, index_mapping,
461				   index_mapping_internal_pa);
462	}
463
464	if (is2t) {
465		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
466			"temp OFDM_A_index=0x%x, OFDM_B_index = 0x%x, cck_index=0x%x\n",
467			dm->ofdm_index[0], dm->ofdm_index[1], dm->cck_index);
468	} else {
469		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
470			"temp OFDM_A_index=0x%x, cck_index = 0x%x\n",
471			dm->ofdm_index[0], dm->cck_index);
472	}
473
474	for (i = 0; i < rf; i++) {
475		if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1) {
476			ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1;
477		} else if (internal_pa ||
478			   rtlhal->current_bandtype == BAND_ON_2_4G) {
479			if (ofdm_index[i] < ofdm_min_index_internal_pa)
480				ofdm_index[i] = ofdm_min_index_internal_pa;
481		} else if (ofdm_index[i] < ofdm_min_index) {
482			ofdm_index[i] = ofdm_min_index;
483		}
484	}
485
486	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
487		if (cck_index > CCK_TABLE_SIZE - 1)
488			cck_index = CCK_TABLE_SIZE - 1;
489		else if (cck_index < 0)
490			cck_index = 0;
491	}
492
493	if (is2t) {
494		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
495			"new OFDM_A_index=0x%x, OFDM_B_index = 0x%x, cck_index=0x%x\n",
496			ofdm_index[0], ofdm_index[1], cck_index);
497	} else {
498		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
499			"new OFDM_A_index=0x%x, cck_index = 0x%x\n",
500			ofdm_index[0], cck_index);
501	}
502
503	ele_d = (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
504	val_x = rtlphy->iqk_matrix[indexforchannel].value[0][0];
505	val_y = rtlphy->iqk_matrix[indexforchannel].value[0][1];
506
507	if (val_x != 0) {
508		if ((val_x & 0x00000200) != 0)
509			val_x = val_x | 0xFFFFFC00;
510		ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
511
512		/* new element C = element D x Y */
513		if ((val_y & 0x00000200) != 0)
514			val_y = val_y | 0xFFFFFC00;
515		ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
516
517		/* write new elements A, C, D to regC80 and
518		 * regC94, element B is always 0
519		 */
520		value32 = (ele_d << 22) | ((ele_c & 0x3F) << 16) | ele_a;
521		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
522			      MASKDWORD, value32);
523
524		value32 = (ele_c & 0x000003C0) >> 6;
525		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
526
527		value32 = ((val_x * ele_d) >> 7) & 0x01;
528		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), value32);
529
530	} else {
531		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
532			      ofdmswing_table[ofdm_index[0]]);
533		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
534		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
535	}
536
537	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
538		"TxPwrTracking for interface %d path A: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = 0x%lx\n",
539		rtlhal->interfaceindex,
540		val_x, val_y, ele_a, ele_c, ele_d,
541		val_x, val_y);
542
543	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
544		/* Adjust CCK according to IQK result */
545		for (i = 0; i < 8; i++) {
546			if (dm->cck_inch14)
547				swing = cckswing_table_ch14[cck_index][i];
548			else
549				swing = cckswing_table_ch1ch13[cck_index][i];
550
551			rtl_write_byte(rtlpriv, 0xa22 + i, swing);
552		}
553	}
554
555	if (is2t) {
556		ele_d = (ofdmswing_table[ofdm_index[1]] & 0xFFC00000) >> 22;
557		val_x = rtlphy->iqk_matrix[indexforchannel].value[0][4];
558		val_y = rtlphy->iqk_matrix[indexforchannel].value[0][5];
559
560		if (val_x != 0) {
561			if ((val_x & 0x00000200) != 0)
562				/* consider minus */
563				val_x = val_x | 0xFFFFFC00;
564			ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
565
566			/* new element C = element D x Y */
567			if ((val_y & 0x00000200) != 0)
568				val_y = val_y | 0xFFFFFC00;
569			ele_c = ((val_y * ele_d) >> 8) & 0x00003FF;
570
571			/* write new elements A, C, D to regC88
572			 * and regC9C, element B is always 0
573			 */
574			value32 = (ele_d << 22) | ((ele_c & 0x3F) << 16) | ele_a;
575			rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
576				      MASKDWORD, value32);
577
578			value32 = (ele_c & 0x000003C0) >> 6;
579			rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32);
580
581			value32 = ((val_x * ele_d) >> 7) & 0x01;
582			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), value32);
583		} else {
584			rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
585				      MASKDWORD, ofdmswing_table[ofdm_index[1]]);
586			rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00);
587			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), 0x00);
588		}
589
590		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
591			"TxPwrTracking path B: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xeb4 = 0x%lx 0xebc = 0x%lx\n",
592			val_x, val_y, ele_a, ele_c, ele_d, val_x, val_y);
593	}
594
595	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
596		"TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n",
597		rtl_get_bbreg(hw, 0xc80, MASKDWORD),
598		rtl_get_bbreg(hw, 0xc94, MASKDWORD),
599		rtl_get_rfreg(hw, RF90_PATH_A, 0x24, RFREG_OFFSET_MASK));
600
601check_delta:
602	if (delta_iqk > rtlefuse->delta_iqk && rtlefuse->delta_iqk != 0) {
603		rtl92d_phy_reset_iqk_result(hw);
604		dm->thermalvalue_iqk = thermalvalue;
605		rtlpriv->cfg->ops->phy_iq_calibrate(hw);
606	}
607
608	if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G &&
609	    thermalvalue <= rtlefuse->eeprom_thermalmeter) {
610		dm->thermalvalue_rxgain = thermalvalue;
611		rtl92d_dm_rxgain_tracking_thermalmeter(hw);
612	}
613
614	if (dm->txpower_track_control)
615		dm->thermalvalue = thermalvalue;
616
617exit:
618	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
619}
620
621void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
622{
623	struct rtl_priv *rtlpriv = rtl_priv(hw);
624
625	rtlpriv->dm.txpower_tracking = true;
626	rtlpriv->dm.txpower_trackinginit = false;
627	rtlpriv->dm.txpower_track_control = true;
628	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
629		"pMgntInfo->txpower_tracking = %d\n",
630		rtlpriv->dm.txpower_tracking);
631}
632EXPORT_SYMBOL_GPL(rtl92d_dm_initialize_txpower_tracking);
633
634void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
635{
636	struct rtl_priv *rtlpriv = rtl_priv(hw);
637
638	if (!rtlpriv->dm.txpower_tracking)
639		return;
640
641	if (!rtlpriv->dm.tm_trigger) {
642		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
643			      BIT(16), 0x03);
644		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
645			"Trigger 92S Thermal Meter!!\n");
646		rtlpriv->dm.tm_trigger = 1;
647	} else {
648		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
649			"Schedule TxPowerTracking direct call!!\n");
650		rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
651		rtlpriv->dm.tm_trigger = 0;
652	}
653}
654EXPORT_SYMBOL_GPL(rtl92d_dm_check_txpower_tracking_thermal_meter);
655
656void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
657{
658	struct rtl_priv *rtlpriv = rtl_priv(hw);
659	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
660	unsigned long flag = 0;
661	u32 ret_value;
662
663	/* hold ofdm counter */
664	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */
665	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /* hold page D counter */
666
667	ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
668	falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
669	falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
670
671	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
672	falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
673
674	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
675	falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
676	falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
677
678	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
679	falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
680
681	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
682				      falsealm_cnt->cnt_rate_illegal +
683				      falsealm_cnt->cnt_crc8_fail +
684				      falsealm_cnt->cnt_mcs_fail +
685				      falsealm_cnt->cnt_fast_fsync_fail +
686				      falsealm_cnt->cnt_sb_search_fail;
687
688	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
689		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
690		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
691		falsealm_cnt->cnt_cck_fail = ret_value;
692		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
693		falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
694		rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
695	} else {
696		falsealm_cnt->cnt_cck_fail = 0;
697	}
698
699	falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
700				falsealm_cnt->cnt_cck_fail;
701
702	/* reset false alarm counter registers */
703	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
704	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
705
706	/* update ofdm counter */
707	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); /* update page C counter */
708	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); /* update page D counter */
709
710	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
711		/* reset cck counter */
712		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
713		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
714		/* enable cck counter */
715		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
716		rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
717	}
718
719	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
720		"Cnt_Fast_Fsync_fail = %x, Cnt_SB_Search_fail = %x\n",
721		falsealm_cnt->cnt_fast_fsync_fail,
722		falsealm_cnt->cnt_sb_search_fail);
723
724	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
725		"Cnt_Parity_Fail = %x, Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, Cnt_Mcs_fail = %x\n",
726		falsealm_cnt->cnt_parity_fail,
727		falsealm_cnt->cnt_rate_illegal,
728		falsealm_cnt->cnt_crc8_fail,
729		falsealm_cnt->cnt_mcs_fail);
730
731	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
732		"Cnt_Ofdm_fail = %x, Cnt_Cck_fail = %x, Cnt_all = %x\n",
733		falsealm_cnt->cnt_ofdm_fail,
734		falsealm_cnt->cnt_cck_fail,
735		falsealm_cnt->cnt_all);
736}
737EXPORT_SYMBOL_GPL(rtl92d_dm_false_alarm_counter_statistics);
738
739void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
740{
741	struct rtl_priv *rtlpriv = rtl_priv(hw);
742	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
743	struct rtl_mac *mac = rtl_mac(rtlpriv);
744
745	/* Determine the minimum RSSI  */
746	if (mac->link_state < MAC80211_LINKED &&
747	    rtlpriv->dm.entry_min_undec_sm_pwdb == 0) {
748		de_digtable->min_undec_pwdb_for_dm = 0;
749		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
750			"Not connected to any\n");
751	}
752	if (mac->link_state >= MAC80211_LINKED) {
753		if (mac->opmode == NL80211_IFTYPE_AP ||
754		    mac->opmode == NL80211_IFTYPE_ADHOC) {
755			de_digtable->min_undec_pwdb_for_dm =
756				rtlpriv->dm.entry_min_undec_sm_pwdb;
757			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
758				"AP Client PWDB = 0x%lx\n",
759				 rtlpriv->dm.entry_min_undec_sm_pwdb);
760		} else {
761			de_digtable->min_undec_pwdb_for_dm =
762				rtlpriv->dm.undec_sm_pwdb;
763			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
764				"STA Default Port PWDB = 0x%x\n",
765				de_digtable->min_undec_pwdb_for_dm);
766		}
767	} else {
768		de_digtable->min_undec_pwdb_for_dm =
769			rtlpriv->dm.entry_min_undec_sm_pwdb;
770		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
771			"AP Ext Port or disconnect PWDB = 0x%x\n",
772			de_digtable->min_undec_pwdb_for_dm);
773	}
774
775	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
776		de_digtable->min_undec_pwdb_for_dm);
777}
778EXPORT_SYMBOL_GPL(rtl92d_dm_find_minimum_rssi);
779
780static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
781{
782	struct rtl_priv *rtlpriv = rtl_priv(hw);
783	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
784	unsigned long flag = 0;
785
786	if (de_digtable->cursta_cstate == DIG_STA_CONNECT) {
787		if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
788			if (de_digtable->min_undec_pwdb_for_dm <= 25)
789				de_digtable->cur_cck_pd_state =
790							 CCK_PD_STAGE_LOWRSSI;
791			else
792				de_digtable->cur_cck_pd_state =
793							 CCK_PD_STAGE_HIGHRSSI;
794		} else {
795			if (de_digtable->min_undec_pwdb_for_dm <= 20)
796				de_digtable->cur_cck_pd_state =
797							 CCK_PD_STAGE_LOWRSSI;
798			else
799				de_digtable->cur_cck_pd_state =
800							 CCK_PD_STAGE_HIGHRSSI;
801		}
802	} else {
803		de_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
804	}
805	if (de_digtable->pre_cck_pd_state != de_digtable->cur_cck_pd_state) {
806		if (de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
807			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
808			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
809			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
810		} else {
811			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
812			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
813			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
814		}
815		de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state;
816	}
817	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n",
818		de_digtable->cursta_cstate == DIG_STA_CONNECT ?
819		"DIG_STA_CONNECT " : "DIG_STA_DISCONNECT");
820	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n",
821		de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
822		"Low RSSI " : "High RSSI ");
823	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "is92d single phy =%x\n",
824		IS_92D_SINGLEPHY(rtlpriv->rtlhal.version));
825}
826
827void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
828{
829	struct rtl_priv *rtlpriv = rtl_priv(hw);
830	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
831
832	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
833		"cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
834		de_digtable->cur_igvalue, de_digtable->pre_igvalue,
835		de_digtable->back_val);
836	if (!de_digtable->dig_enable_flag) {
837		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n");
838		de_digtable->pre_igvalue = 0x17;
839		return;
840	}
841	if (de_digtable->pre_igvalue != de_digtable->cur_igvalue) {
842		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
843			      de_digtable->cur_igvalue);
844		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
845			      de_digtable->cur_igvalue);
846		de_digtable->pre_igvalue = de_digtable->cur_igvalue;
847	}
848}
849EXPORT_SYMBOL_GPL(rtl92d_dm_write_dig);
850
851static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
852{
853	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
854
855	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED &&
856	    rtlpriv->mac80211.vendor == PEER_CISCO) {
857		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n");
858		if (de_digtable->last_min_undec_pwdb_for_dm >= 50 &&
859		    de_digtable->min_undec_pwdb_for_dm < 50) {
860			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
861			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
862				"Early Mode Off\n");
863		} else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 &&
864			   de_digtable->min_undec_pwdb_for_dm > 55) {
865			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
866			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
867				"Early Mode On\n");
868		}
869	} else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) {
870		rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
871		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Early Mode On\n");
872	}
873}
874
875void rtl92d_dm_dig(struct ieee80211_hw *hw)
876{
877	struct rtl_priv *rtlpriv = rtl_priv(hw);
878	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
879	u8 value_igi = de_digtable->cur_igvalue;
880	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
881
882	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n");
883	if (rtlpriv->rtlhal.earlymode_enable) {
884		rtl92d_early_mode_enabled(rtlpriv);
885		de_digtable->last_min_undec_pwdb_for_dm =
886				 de_digtable->min_undec_pwdb_for_dm;
887	}
888	if (!rtlpriv->dm.dm_initialgain_enable)
889		return;
890
891	/* because we will send data pkt when scanning
892	 * this will cause some ap like gear-3700 wep TP
893	 * lower if we return here, this is the diff of
894	 * mac80211 driver vs ieee80211 driver
895	 */
896	/* if (rtlpriv->mac80211.act_scanning)
897	 *      return;
898	 */
899
900	/* Not STA mode return tmp */
901	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
902		return;
903	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n");
904	/* Decide the current status and if modify initial gain or not */
905	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
906		de_digtable->cursta_cstate = DIG_STA_CONNECT;
907	else
908		de_digtable->cursta_cstate = DIG_STA_DISCONNECT;
909
910	/* adjust initial gain according to false alarm counter */
911	if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
912		value_igi--;
913	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1)
914		value_igi += 0;
915	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2)
916		value_igi++;
917	else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2)
918		value_igi += 2;
919	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
920		"dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n",
921		de_digtable->large_fa_hit, de_digtable->forbidden_igi);
922	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
923		"dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n",
924		de_digtable->recover_cnt, de_digtable->rx_gain_min);
925
926	/* deal with abnormally large false alarm */
927	if (falsealm_cnt->cnt_all > 10000) {
928		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
929			"dm_DIG(): Abnormally false alarm case\n");
930
931		de_digtable->large_fa_hit++;
932		if (de_digtable->forbidden_igi < de_digtable->cur_igvalue) {
933			de_digtable->forbidden_igi = de_digtable->cur_igvalue;
934			de_digtable->large_fa_hit = 1;
935		}
936		if (de_digtable->large_fa_hit >= 3) {
937			if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX)
938				de_digtable->rx_gain_min = DM_DIG_MAX;
939			else
940				de_digtable->rx_gain_min =
941				    (de_digtable->forbidden_igi + 1);
942			de_digtable->recover_cnt = 3600;	/* 3600=2hr */
943		}
944	} else {
945		/* Recovery mechanism for IGI lower bound */
946		if (de_digtable->recover_cnt != 0) {
947			de_digtable->recover_cnt--;
948		} else {
949			if (de_digtable->large_fa_hit == 0) {
950				if ((de_digtable->forbidden_igi - 1) <
951				    DM_DIG_FA_LOWER) {
952					de_digtable->forbidden_igi =
953							 DM_DIG_FA_LOWER;
954					de_digtable->rx_gain_min =
955							 DM_DIG_FA_LOWER;
956
957				} else {
958					de_digtable->forbidden_igi--;
959					de_digtable->rx_gain_min =
960					    (de_digtable->forbidden_igi + 1);
961				}
962			} else if (de_digtable->large_fa_hit == 3) {
963				de_digtable->large_fa_hit = 0;
964			}
965		}
966	}
967	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
968		"dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n",
969		de_digtable->large_fa_hit, de_digtable->forbidden_igi);
970	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
971		"dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n",
972		de_digtable->recover_cnt, de_digtable->rx_gain_min);
973
974	if (value_igi > DM_DIG_MAX)
975		value_igi = DM_DIG_MAX;
976	else if (value_igi < de_digtable->rx_gain_min)
977		value_igi = de_digtable->rx_gain_min;
978	de_digtable->cur_igvalue = value_igi;
979	rtl92d_dm_write_dig(hw);
980	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G)
981		rtl92d_dm_cck_packet_detection_thresh(hw);
982	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "<<==\n");
983}
984EXPORT_SYMBOL_GPL(rtl92d_dm_dig);
985
986void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw)
987{
988	struct rtl_priv *rtlpriv = rtl_priv(hw);
989
990	rtlpriv->dm.current_turbo_edca = false;
991	rtlpriv->dm.is_any_nonbepkts = false;
992	rtlpriv->dm.is_cur_rdlstate = false;
993}
994EXPORT_SYMBOL_GPL(rtl92d_dm_init_edca_turbo);
995
996void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw)
997{
998	struct rtl_priv *rtlpriv = rtl_priv(hw);
999	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1000	const u32 edca_be_ul = 0x5ea42b;
1001	const u32 edca_be_dl = 0x5ea42b;
1002	static u64 last_txok_cnt;
1003	static u64 last_rxok_cnt;
1004	u64 cur_txok_cnt;
1005	u64 cur_rxok_cnt;
1006
1007	if (mac->link_state != MAC80211_LINKED) {
1008		rtlpriv->dm.current_turbo_edca = false;
1009		goto exit;
1010	}
1011
1012	if (!rtlpriv->dm.is_any_nonbepkts &&
1013	    !rtlpriv->dm.disable_framebursting) {
1014		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1015		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1016		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
1017			if (!rtlpriv->dm.is_cur_rdlstate ||
1018			    !rtlpriv->dm.current_turbo_edca) {
1019				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
1020						edca_be_dl);
1021				rtlpriv->dm.is_cur_rdlstate = true;
1022			}
1023		} else {
1024			if (rtlpriv->dm.is_cur_rdlstate ||
1025			    !rtlpriv->dm.current_turbo_edca) {
1026				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
1027						edca_be_ul);
1028				rtlpriv->dm.is_cur_rdlstate = false;
1029			}
1030		}
1031		rtlpriv->dm.current_turbo_edca = true;
1032	} else {
1033		if (rtlpriv->dm.current_turbo_edca) {
1034			u8 tmp = AC0_BE;
1035
1036			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1037						      &tmp);
1038			rtlpriv->dm.current_turbo_edca = false;
1039		}
1040	}
1041
1042exit:
1043	rtlpriv->dm.is_any_nonbepkts = false;
1044	last_txok_cnt = rtlpriv->stats.txbytesunicast;
1045	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1046}
1047EXPORT_SYMBOL_GPL(rtl92d_dm_check_edca_turbo);
1048
1049void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1050{
1051	struct rtl_priv *rtlpriv = rtl_priv(hw);
1052	struct rate_adaptive *ra = &rtlpriv->ra;
1053
1054	ra->ratr_state = DM_RATR_STA_INIT;
1055	ra->pre_ratr_state = DM_RATR_STA_INIT;
1056	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1057		rtlpriv->dm.useramask = true;
1058	else
1059		rtlpriv->dm.useramask = false;
1060}
1061EXPORT_SYMBOL_GPL(rtl92d_dm_init_rate_adaptive_mask);
1062