xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8723ds/hal/phydm/halrf/halphyrf_win.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 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  *****************************************************************************/
15 
16 #include "mp_precomp.h"
17 #include "phydm_precomp.h"
18 
19 #define	CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _delta_thermal) \
20 	do {\
21 		for (_offset = 0; _offset < _size; _offset++) { \
22 			\
23 			if (_delta_thermal < thermal_threshold[_direction][_offset]) { \
24 				\
25 				if (_offset != 0)\
26 					_offset--;\
27 				break;\
28 			} \
29 		}			\
30 		if (_offset >= _size)\
31 			_offset = _size-1;\
32 	} while (0)
33 
configure_txpower_track(struct dm_struct * dm,struct txpwrtrack_cfg * config)34 void configure_txpower_track(
35 	struct dm_struct		*dm,
36 	struct txpwrtrack_cfg	*config
37 )
38 {
39 #if RTL8192E_SUPPORT
40 	if (dm->support_ic_type == ODM_RTL8192E)
41 		configure_txpower_track_8192e(config);
42 #endif
43 #if RTL8821A_SUPPORT
44 	if (dm->support_ic_type == ODM_RTL8821)
45 		configure_txpower_track_8821a(config);
46 #endif
47 #if RTL8812A_SUPPORT
48 	if (dm->support_ic_type == ODM_RTL8812)
49 		configure_txpower_track_8812a(config);
50 #endif
51 #if RTL8188E_SUPPORT
52 	if (dm->support_ic_type == ODM_RTL8188E)
53 		configure_txpower_track_8188e(config);
54 #endif
55 
56 #if RTL8188F_SUPPORT
57 	if (dm->support_ic_type == ODM_RTL8188F)
58 		configure_txpower_track_8188f(config);
59 #endif
60 
61 #if RTL8723B_SUPPORT
62 	if (dm->support_ic_type == ODM_RTL8723B)
63 		configure_txpower_track_8723b(config);
64 #endif
65 
66 #if RTL8814A_SUPPORT
67 	if (dm->support_ic_type == ODM_RTL8814A)
68 		configure_txpower_track_8814a(config);
69 #endif
70 
71 #if RTL8703B_SUPPORT
72 	if (dm->support_ic_type == ODM_RTL8703B)
73 		configure_txpower_track_8703b(config);
74 #endif
75 
76 #if RTL8822B_SUPPORT
77 	if (dm->support_ic_type == ODM_RTL8822B)
78 		configure_txpower_track_8822b(config);
79 #endif
80 
81 #if RTL8723D_SUPPORT
82 	if (dm->support_ic_type == ODM_RTL8723D)
83 		configure_txpower_track_8723d(config);
84 #endif
85 
86 /* JJ ADD 20161014 */
87 #if RTL8710B_SUPPORT
88 	if (dm->support_ic_type == ODM_RTL8710B)
89 		configure_txpower_track_8710b(config);
90 #endif
91 
92 #if RTL8821C_SUPPORT
93 	if (dm->support_ic_type == ODM_RTL8821C)
94 		configure_txpower_track_8821c(config);
95 #endif
96 
97 #if RTL8192F_SUPPORT
98 	if (dm->support_ic_type == ODM_RTL8192F)
99 		configure_txpower_track_8192f(config);
100 #endif
101 
102 #if RTL8822C_SUPPORT
103 	if (dm->support_ic_type == ODM_RTL8822C)
104 		configure_txpower_track_8822c(config);
105 #endif
106 
107 #if RTL8814B_SUPPORT
108 	if (dm->support_ic_type == ODM_RTL8814B)
109 		configure_txpower_track_8814b(config);
110 #endif
111 
112 #if RTL8723F_SUPPORT
113 	if (dm->support_ic_type == ODM_RTL8723F)
114 		configure_txpower_track_8723f(config);
115 #endif
116 
117 }
118 
119 /* **********************************************************************
120  * <20121113, Kordan> This function should be called when tx_agc changed.
121  * Otherwise the previous compensation is gone, because we record the
122  * delta of temperature between two TxPowerTracking watch dogs.
123  *
124  * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still
125  * need to call this function.
126  * ********************************************************************** */
127 void
odm_clear_txpowertracking_state(struct dm_struct * dm)128 odm_clear_txpowertracking_state(
129 	struct dm_struct		*dm
130 )
131 {
132 	PHAL_DATA_TYPE	hal_data = GET_HAL_DATA((PADAPTER)(dm->adapter));
133 	u8			p = 0;
134 	struct dm_rf_calibration_struct	*cali_info = &(dm->rf_calibrate_info);
135 
136 	cali_info->bb_swing_idx_cck_base = cali_info->default_cck_index;
137 	cali_info->bb_swing_idx_cck = cali_info->default_cck_index;
138 	cali_info->CCK_index = 0;
139 
140 	for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
141 		cali_info->bb_swing_idx_ofdm_base[p] = cali_info->default_ofdm_index;
142 		cali_info->bb_swing_idx_ofdm[p] = cali_info->default_ofdm_index;
143 		cali_info->OFDM_index[p] = cali_info->default_ofdm_index;
144 
145 		cali_info->power_index_offset[p] = 0;
146 		cali_info->delta_power_index[p] = 0;
147 		cali_info->delta_power_index_last[p] = 0;
148 
149 		cali_info->absolute_ofdm_swing_idx[p] = 0;    /* Initial Mix mode power tracking*/
150 		cali_info->remnant_ofdm_swing_idx[p] = 0;
151 		cali_info->kfree_offset[p] = 0;
152 	}
153 
154 	cali_info->modify_tx_agc_flag_path_a = false;       /*Initial at Modify Tx Scaling mode*/
155 	cali_info->modify_tx_agc_flag_path_b = false;       /*Initial at Modify Tx Scaling mode*/
156 	cali_info->modify_tx_agc_flag_path_c = false;       /*Initial at Modify Tx Scaling mode*/
157 	cali_info->modify_tx_agc_flag_path_d = false;       /*Initial at Modify Tx Scaling mode*/
158 	cali_info->remnant_cck_swing_idx = 0;
159 	cali_info->thermal_value = hal_data->eeprom_thermal_meter;
160 
161 	cali_info->modify_tx_agc_value_cck = 0;			/* modify by Mingzhi.Guo */
162 	cali_info->modify_tx_agc_value_ofdm = 0;		/* modify by Mingzhi.Guo */
163 
164 }
165 
166 void
odm_txpowertracking_callback_thermal_meter(struct dm_struct * dm)167 odm_txpowertracking_callback_thermal_meter(
168 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
169 	struct dm_struct		*dm
170 #else
171 	void	*adapter
172 #endif
173 )
174 {
175 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
176 	HAL_DATA_TYPE	*hal_data = GET_HAL_DATA(((PADAPTER)adapter));
177 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
178 	struct dm_struct		*dm = &hal_data->DM_OutSrc;
179 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
180 	struct dm_struct		*dm = &hal_data->odmpriv;
181 #endif
182 #endif
183 
184 	struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
185  	struct dm_iqk_info *iqk_info = &dm->IQK_info;
186 	struct _hal_rf_ *rf = &(dm->rf_table);
187 	u8			thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
188 	s8			diff_DPK[4] = {0};
189 	u8			thermal_value_avg_count = 0;
190 	u32			thermal_value_avg = 0, regc80, regcd0, regcd4, regab4, regc88, rege14, reg848,reg838, reg86c;
191 
192 	u8			OFDM_min_index = 0;  /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
193 	u8			indexforchannel = 0; /* get_right_chnl_place_for_iqk(hal_data->current_channel) */
194 	u8			power_tracking_type = hal_data->RfPowerTrackingType;
195 	u8			xtal_offset_eanble = 0;
196 	s8			thermal_value_temp = 0;
197 
198 	struct txpwrtrack_cfg	c;
199 
200 	/* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
201 	u8			*delta_swing_table_idx_tup_a = NULL;
202 	u8			*delta_swing_table_idx_tdown_a = NULL;
203 	u8			*delta_swing_table_idx_tup_b = NULL;
204 	u8			*delta_swing_table_idx_tdown_b = NULL;
205 	/*for 8814 add by Yu Chen*/
206 	u8			*delta_swing_table_idx_tup_c = NULL;
207 	u8			*delta_swing_table_idx_tdown_c = NULL;
208 	u8			*delta_swing_table_idx_tup_d = NULL;
209 	u8			*delta_swing_table_idx_tdown_d = NULL;
210 	/*for Xtal Offset by James.Tung*/
211 	s8			*delta_swing_table_xtal_up = NULL;
212 	s8			*delta_swing_table_xtal_down = NULL;
213 
214 	/* 4 2. Initilization ( 7 steps in total ) */
215 
216 	configure_txpower_track(dm, &c);
217 
218 	(*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
219 		(u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
220 
221 	if (dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8814B))	/*for 8814 path C & D*/
222 		(*c.get_delta_swing_table8814only)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
223 			(u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
224 	/* JJ ADD 20161014 */
225 	if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F))	/*for Xtal Offset*/
226 		(*c.get_delta_swing_xtal_table)(dm, (s8 **)&delta_swing_table_xtal_up, (s8 **)&delta_swing_table_xtal_down);
227 
228 
229 	cali_info->txpowertracking_callback_cnt++;	/*cosa add for debug*/
230 	cali_info->is_txpowertracking_init = true;
231 
232 	/*cali_info->txpowertrack_control = hal_data->txpowertrack_control;
233 	<Kordan> We should keep updating the control variable according to HalData.
234 	<Kordan> rf_calibrate_info.rega24 will be initialized when ODM HW configuring, but MP configures with para files. */
235 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
236 #if (MP_DRIVER == 1)
237 #ifndef RTL8723F_SUPPORT
238 	cali_info->rega24 = 0x090e1317;
239 #endif
240 #endif
241 
242 #elif (DM_ODM_SUPPORT_TYPE & ODM_CE)
243 	if (*(dm->mp_mode) == true)
244 		cali_info->rega24 = 0x090e1317;
245 #endif
246 
247 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
248 		"===>odm_txpowertracking_callback_thermal_meter\n cali_info->bb_swing_idx_cck_base: %d, cali_info->bb_swing_idx_ofdm_base[A]: %d, cali_info->default_ofdm_index: %d\n",
249 		cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
250 
251 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
252 		"cali_info->txpowertrack_control=%d,  hal_data->eeprom_thermal_meter %d\n", cali_info->txpowertrack_control,  hal_data->eeprom_thermal_meter);
253 	thermal_value = (u8)odm_get_rf_reg(dm, RF_PATH_A, c.thermal_reg_addr, 0xfc00);	/* 0x42: RF Reg[15:10] 88E */
254 
255 	thermal_value_temp = thermal_value + phydm_get_thermal_offset(dm);
256 
257 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
258 		"thermal_value_temp(%d) = thermal_value(%d) + power_time_thermal(%d)\n", thermal_value_temp, thermal_value, phydm_get_thermal_offset(dm));
259 
260 	if (thermal_value_temp > 63)
261 		thermal_value = 63;
262 	else if (thermal_value_temp < 0)
263 		thermal_value = 0;
264 	else
265 		thermal_value = thermal_value_temp;
266 
267 	/*add log by zhao he, check c80/c94/c14/ca0 value*/
268 	if (dm->support_ic_type == ODM_RTL8723D) {
269 		regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
270 		regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
271 		regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
272 		regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
273 		RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
274 	}
275 
276 	/* JJ ADD 20161014 */
277 	if (dm->support_ic_type == ODM_RTL8710B) {
278 		regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
279 		regcd0 = odm_get_bb_reg(dm, R_0xcd0, MASKDWORD);
280 		regcd4 = odm_get_bb_reg(dm, R_0xcd4, MASKDWORD);
281 		regab4 = odm_get_bb_reg(dm, R_0xab4, 0x000007FF);
282 		RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4);
283 	}
284 	/* Winnita add 20171205 */
285 	if (dm->support_ic_type == ODM_RTL8192F) {
286 		regc80 = odm_get_bb_reg(dm, R_0xc80, MASKDWORD);
287 		regc88 = odm_get_bb_reg(dm, R_0xc88, MASKDWORD);
288 		regab4 = odm_get_bb_reg(dm, R_0xab4, MASKDWORD);
289 		rege14 = odm_get_bb_reg(dm, R_0xe14, MASKDWORD);
290 		reg848 = odm_get_bb_reg(dm, R_0x848, MASKDWORD);
291 		reg838 = odm_get_bb_reg(dm, R_0x838, MASKDWORD);
292 		reg86c = odm_get_bb_reg(dm, R_0x86c, MASKDWORD);
293 		RF_DBG(dm, DBG_RF_IQK, "0xc80 = 0x%x 0xc88 = 0x%x 0xab4 = 0x%x 0xe14 = 0x%x\n", regc80, regc88, regab4, rege14);
294 		RF_DBG(dm, DBG_RF_IQK, "0x848 = 0x%x 0x838 = 0x%x 0x86c = 0x%x\n", reg848, reg838, reg86c);
295 	}
296 
297 	if (!cali_info->txpowertrack_control)
298 		return;
299 
300 	if (hal_data->eeprom_thermal_meter == 0xff) {
301 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, hal_data->eeprom_thermal_meter = 0x%x\n", hal_data->eeprom_thermal_meter);
302 		return;
303 	}
304 
305 	/*4 3. Initialize ThermalValues of rf_calibrate_info*/
306 
307 	if (cali_info->is_reloadtxpowerindex)
308 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "reload ofdm index for band switch\n");
309 
310 	/*4 4. Calculate average thermal meter*/
311 
312 	cali_info->thermal_value_avg[cali_info->thermal_value_avg_index] = thermal_value;
313 	cali_info->thermal_value_avg_index++;
314 	if (cali_info->thermal_value_avg_index == c.average_thermal_num)   /*Average times =  c.average_thermal_num*/
315 		cali_info->thermal_value_avg_index = 0;
316 
317 	for (i = 0; i < c.average_thermal_num; i++) {
318 		if (cali_info->thermal_value_avg[i]) {
319 			thermal_value_avg += cali_info->thermal_value_avg[i];
320 			thermal_value_avg_count++;
321 		}
322 	}
323 
324 	if (thermal_value_avg_count) {            /* Calculate Average thermal_value after average enough times */
325 		thermal_value = (u8)(thermal_value_avg / thermal_value_avg_count);
326 		cali_info->thermal_value_delta = thermal_value - hal_data->eeprom_thermal_meter;
327 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
328 			"AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n", thermal_value, hal_data->eeprom_thermal_meter);
329 	}
330 
331 	/* 4 5. Calculate delta, delta_LCK, delta_IQK. */
332 
333 	/* "delta" here is used to determine whether thermal value changes or not. */
334 	delta	= (thermal_value > cali_info->thermal_value) ? (thermal_value - cali_info->thermal_value) : (cali_info->thermal_value - thermal_value);
335 	delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
336 	delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
337 
338 	if (cali_info->thermal_value_iqk == 0xff) {	/*no PG, use thermal value for IQK*/
339 		cali_info->thermal_value_iqk = thermal_value;
340 		delta_IQK = (thermal_value > cali_info->thermal_value_iqk) ? (thermal_value - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value);
341 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, use thermal_value for IQK\n");
342 	}
343 
344 	for (p = RF_PATH_A; p < c.rf_path_count; p++)
345 		diff_DPK[p] = (s8)thermal_value - (s8)cali_info->dpk_thermal[p];
346 
347 	/*4 6. If necessary, do LCK.*/
348 
349 	if (!(dm->support_ic_type & ODM_RTL8821)) {	/*no PG, do LCK at initial status*/
350 		if (cali_info->thermal_value_lck == 0xff) {
351 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no PG, do LCK\n");
352 			cali_info->thermal_value_lck = thermal_value;
353 
354 			/*Use RTLCK, so close power tracking driver LCK*/
355 			if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
356 				if (c.phy_lc_calibrate)
357 					(*c.phy_lc_calibrate)(dm);
358 			}
359 
360 			delta_LCK = (thermal_value > cali_info->thermal_value_lck) ? (thermal_value - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value);
361 		}
362 
363 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", delta, delta_LCK, delta_IQK);
364 
365 		/* Wait sacn to do LCK by RF Jenyu*/
366 		if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
367 			/* Delta temperature is equal to or larger than 20 centigrade.*/
368 			if (delta_LCK >= c.threshold_iqk) {
369 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
370 				cali_info->thermal_value_lck = thermal_value;
371 
372 				/*Use RTLCK, so close power tracking driver LCK*/
373 				if ((!(dm->support_ic_type & ODM_RTL8814A)) && (!(dm->support_ic_type & ODM_RTL8822B))) {
374 					if (c.phy_lc_calibrate)
375 						(*c.phy_lc_calibrate)(dm);
376 				}
377 			}
378 		}
379 	}
380 
381 	/*3 7. If necessary, move the index of swing table to adjust Tx power.*/
382 
383 	if (delta > 0 && cali_info->txpowertrack_control) {
384 		/* "delta" here is used to record the absolute value of differrence. */
385 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
386 		delta = thermal_value > hal_data->eeprom_thermal_meter ? (thermal_value - hal_data->eeprom_thermal_meter) : (hal_data->eeprom_thermal_meter - thermal_value);
387 #else
388 		delta = (thermal_value > dm->priv->pmib->dot11RFEntry.ther) ? (thermal_value - dm->priv->pmib->dot11RFEntry.ther) : (dm->priv->pmib->dot11RFEntry.ther - thermal_value);
389 #endif
390 		if (delta >= TXPWR_TRACK_TABLE_SIZE)
391 			delta = TXPWR_TRACK_TABLE_SIZE - 1;
392 
393 		/*4 7.1 The Final Power index = BaseIndex + power_index_offset*/
394 
395 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
396 		if (thermal_value > hal_data->eeprom_thermal_meter) {
397 #else
398 		if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
399 #endif
400 
401 			for (p = RF_PATH_A; p < c.rf_path_count; p++) {
402 				cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p];	/*recording poer index offset*/
403 				switch (p) {
404 				case RF_PATH_B:
405 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
406 						"delta_swing_table_idx_tup_b[%d] = %d\n", delta, delta_swing_table_idx_tup_b[delta]);
407 
408 					cali_info->delta_power_index[p] = delta_swing_table_idx_tup_b[delta];
409 					cali_info->absolute_ofdm_swing_idx[p] =  delta_swing_table_idx_tup_b[delta];       /*Record delta swing for mix mode power tracking*/
410 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
411 						"******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
412 					break;
413 
414 				case RF_PATH_C:
415 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
416 						"delta_swing_table_idx_tup_c[%d] = %d\n", delta, delta_swing_table_idx_tup_c[delta]);
417 
418 					cali_info->delta_power_index[p] = delta_swing_table_idx_tup_c[delta];
419 					cali_info->absolute_ofdm_swing_idx[p] =  delta_swing_table_idx_tup_c[delta];       /*Record delta swing for mix mode power tracking*/
420 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
421 						"******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
422 					break;
423 
424 				case RF_PATH_D:
425 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
426 						"delta_swing_table_idx_tup_d[%d] = %d\n", delta, delta_swing_table_idx_tup_d[delta]);
427 
428 					cali_info->delta_power_index[p] = delta_swing_table_idx_tup_d[delta];
429 					cali_info->absolute_ofdm_swing_idx[p] =  delta_swing_table_idx_tup_d[delta];       /*Record delta swing for mix mode power tracking*/
430 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
431 						"******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
432 					break;
433 
434 				default:
435 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
436 						"delta_swing_table_idx_tup_a[%d] = %d\n", delta, delta_swing_table_idx_tup_a[delta]);
437 
438 					cali_info->delta_power_index[p] = delta_swing_table_idx_tup_a[delta];
439 					cali_info->absolute_ofdm_swing_idx[p] =  delta_swing_table_idx_tup_a[delta];        /*Record delta swing for mix mode power tracking*/
440 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
441 						"******Temp is higher and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
442 					break;
443 				}
444 			}
445 			/* JJ ADD 20161014 */
446 			if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
447 				/*Save xtal_offset from Xtal table*/
448 				cali_info->xtal_offset_last = cali_info->xtal_offset;	/*recording last Xtal offset*/
449 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
450 					"[Xtal] delta_swing_table_xtal_up[%d] = %d\n", delta, delta_swing_table_xtal_up[delta]);
451 				cali_info->xtal_offset = delta_swing_table_xtal_up[delta];
452 
453 				if (cali_info->xtal_offset_last == cali_info->xtal_offset)
454 					xtal_offset_eanble = 0;
455 				else
456 					xtal_offset_eanble = 1;
457 			}
458 
459 		} else {
460 			for (p = RF_PATH_A; p < c.rf_path_count; p++) {
461 				cali_info->delta_power_index_last[p] = cali_info->delta_power_index[p];	/*recording poer index offset*/
462 
463 				switch (p) {
464 				case RF_PATH_B:
465 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
466 						"delta_swing_table_idx_tdown_b[%d] = %d\n", delta, delta_swing_table_idx_tdown_b[delta]);
467 					cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_b[delta];
468 					cali_info->absolute_ofdm_swing_idx[p] =  -1 * delta_swing_table_idx_tdown_b[delta];        /*Record delta swing for mix mode power tracking*/
469 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
470 						"******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_B] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
471 					break;
472 
473 				case RF_PATH_C:
474 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
475 						"delta_swing_table_idx_tdown_c[%d] = %d\n", delta, delta_swing_table_idx_tdown_c[delta]);
476 					cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_c[delta];
477 					cali_info->absolute_ofdm_swing_idx[p] =  -1 * delta_swing_table_idx_tdown_c[delta];        /*Record delta swing for mix mode power tracking*/
478 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
479 						"******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_C] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
480 					break;
481 
482 				case RF_PATH_D:
483 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
484 						"delta_swing_table_idx_tdown_d[%d] = %d\n", delta, delta_swing_table_idx_tdown_d[delta]);
485 					cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_d[delta];
486 					cali_info->absolute_ofdm_swing_idx[p] =  -1 * delta_swing_table_idx_tdown_d[delta];        /*Record delta swing for mix mode power tracking*/
487 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
488 						"******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_D] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
489 					break;
490 
491 				default:
492 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
493 						"delta_swing_table_idx_tdown_a[%d] = %d\n", delta, delta_swing_table_idx_tdown_a[delta]);
494 					cali_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_a[delta];
495 					cali_info->absolute_ofdm_swing_idx[p] =  -1 * delta_swing_table_idx_tdown_a[delta];        /*Record delta swing for mix mode power tracking*/
496 					RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
497 						"******Temp is lower and cali_info->absolute_ofdm_swing_idx[RF_PATH_A] = %d\n", cali_info->absolute_ofdm_swing_idx[p]);
498 					break;
499 				}
500 			}
501 			/* JJ ADD 20161014 */
502 			if (dm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8710B | ODM_RTL8192F)) {
503 				/*Save xtal_offset from Xtal table*/
504 				cali_info->xtal_offset_last = cali_info->xtal_offset;	/*recording last Xtal offset*/
505 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
506 					"[Xtal] delta_swing_table_xtal_down[%d] = %d\n", delta, delta_swing_table_xtal_down[delta]);
507 				cali_info->xtal_offset = delta_swing_table_xtal_down[delta];
508 
509 				if (cali_info->xtal_offset_last == cali_info->xtal_offset)
510 					xtal_offset_eanble = 0;
511 				else
512 					xtal_offset_eanble = 1;
513 			}
514 
515 		}
516 
517 		for (p = RF_PATH_A; p < c.rf_path_count; p++) {
518 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
519 				"\n\n=========================== [path-%d] Calculating power_index_offset===========================\n", p);
520 
521 			if (cali_info->delta_power_index[p] == cali_info->delta_power_index_last[p])         /*If Thermal value changes but lookup table value still the same*/
522 				cali_info->power_index_offset[p] = 0;
523 			else
524 				cali_info->power_index_offset[p] = cali_info->delta_power_index[p] - cali_info->delta_power_index_last[p];      /*Power index diff between 2 times Power Tracking*/
525 
526 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
527 				"[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n", p, cali_info->power_index_offset[p], cali_info->delta_power_index[p], cali_info->delta_power_index_last[p]);
528 
529 			cali_info->OFDM_index[p] = cali_info->bb_swing_idx_ofdm_base[p] + cali_info->power_index_offset[p];
530 			cali_info->CCK_index = cali_info->bb_swing_idx_cck_base + cali_info->power_index_offset[p];
531 
532 			cali_info->bb_swing_idx_cck = cali_info->CCK_index;
533 			cali_info->bb_swing_idx_ofdm[p] = cali_info->OFDM_index[p];
534 
535 			/*************Print BB Swing base and index Offset*************/
536 
537 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
538 				"The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_cck, cali_info->bb_swing_idx_cck_base, cali_info->power_index_offset[p]);
539 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
540 				"The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n", cali_info->bb_swing_idx_ofdm[p], p, cali_info->bb_swing_idx_ofdm_base[p], cali_info->power_index_offset[p]);
541 
542 			/*4 7.1 Handle boundary conditions of index.*/
543 
544 			if (cali_info->OFDM_index[p] > c.swing_table_size_ofdm - 1)
545 				cali_info->OFDM_index[p] = c.swing_table_size_ofdm - 1;
546 			else if (cali_info->OFDM_index[p] <= OFDM_min_index)
547 				cali_info->OFDM_index[p] = OFDM_min_index;
548 		}
549 
550 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
551 			"\n\n========================================================================================================\n");
552 
553 		if (cali_info->CCK_index > c.swing_table_size_cck - 1)
554 			cali_info->CCK_index = c.swing_table_size_cck - 1;
555 		else if (cali_info->CCK_index <= 0)
556 			cali_info->CCK_index = 0;
557 	} else {
558 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
559 			"The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, cali_info->thermal_value: %d\n",
560 			cali_info->txpowertrack_control, thermal_value, cali_info->thermal_value);
561 
562 		for (p = RF_PATH_A; p < c.rf_path_count; p++)
563 			cali_info->power_index_offset[p] = 0;
564 	}
565 
566 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
567 		"TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n",
568 		cali_info->CCK_index, cali_info->bb_swing_idx_cck_base);       /*Print Swing base & current*/
569 
570 	for (p = RF_PATH_A; p < c.rf_path_count; p++) {
571 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
572 			"TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n",
573 			cali_info->OFDM_index[p], p, cali_info->bb_swing_idx_ofdm_base[p]);
574 	}
575 
576 	if (dm->support_ic_type & ODM_RTL8814B)
577 		power_tracking_type = TSSI_MODE;
578 
579 	if (dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8814B)) {
580 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "power_tracking_type=%d\n", power_tracking_type);
581 
582 		if (power_tracking_type == 0) {
583 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
584 			for (p = RF_PATH_A; p < c.rf_path_count; p++)
585 				(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
586 		} else if (power_tracking_type == 1) {
587 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n");
588 			for (p = RF_PATH_A; p < c.rf_path_count; p++)
589 				(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_2G_TSSI_5G_MODE, p, 0);
590 		} else if (power_tracking_type == 2) {
591 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n");
592 			for (p = RF_PATH_A; p < c.rf_path_count; p++)
593 				(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_5G_TSSI_2G_MODE, p, 0);
594 		} else if (power_tracking_type == 3) {
595 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI MODE**********\n");
596 			for (p = RF_PATH_A; p < c.rf_path_count; p++)
597 				(*c.odm_tx_pwr_track_set_pwr)(dm, TSSI_MODE, p, 0);
598 		}
599 		cali_info->thermal_value = thermal_value;         /*Record last Power Tracking Thermal value*/
600 
601 	} else if ((cali_info->power_index_offset[RF_PATH_A] != 0 ||
602 		cali_info->power_index_offset[RF_PATH_B] != 0 ||
603 		cali_info->power_index_offset[RF_PATH_C] != 0 ||
604 		cali_info->power_index_offset[RF_PATH_D] != 0) &&
605 		cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
606 		/* 4 7.2 Configure the Swing Table to adjust Tx Power. */
607 
608 		cali_info->is_tx_power_changed = true;	/*Always true after Tx Power is adjusted by power tracking.*/
609 		/*  */
610 		/* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
611 		/* to increase TX power. Otherwise, EVM will be bad. */
612 		/*  */
613 		/* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
614 		if (thermal_value > cali_info->thermal_value) {
615 			for (p = RF_PATH_A; p < c.rf_path_count; p++) {
616 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
617 					"Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
618 					p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
619 			}
620 		} else if (thermal_value < cali_info->thermal_value) {	/*Low temperature*/
621 			for (p = RF_PATH_A; p < c.rf_path_count; p++) {
622 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
623 					"Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
624 					p, cali_info->power_index_offset[p], delta, thermal_value, hal_data->eeprom_thermal_meter, cali_info->thermal_value);
625 			}
626 		}
627 
628 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
629 		if (thermal_value > hal_data->eeprom_thermal_meter)
630 #else
631 		if (thermal_value > dm->priv->pmib->dot11RFEntry.ther)
632 #endif
633 		{
634 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
635 				"Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
636 
637 			if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
638 			    dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
639 			    dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
640 			    dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
641 			    dm->support_ic_type == ODM_RTL8192F) {
642 
643 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
644 				for (p = RF_PATH_A; p < c.rf_path_count; p++)
645 					(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
646 			} else {
647 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
648 				for (p = RF_PATH_A; p < c.rf_path_count; p++)
649 					(*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
650 			}
651 		} else {
652 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
653 				"Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
654 
655 			if (dm->support_ic_type == ODM_RTL8188E || dm->support_ic_type == ODM_RTL8192E || dm->support_ic_type == ODM_RTL8821 ||
656 			    dm->support_ic_type == ODM_RTL8812 || dm->support_ic_type == ODM_RTL8723B || dm->support_ic_type == ODM_RTL8814A ||
657 			    dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8188F || dm->support_ic_type == ODM_RTL8822B ||
658 			    dm->support_ic_type == ODM_RTL8723D || dm->support_ic_type == ODM_RTL8821C || dm->support_ic_type == ODM_RTL8710B ||
659 				dm->support_ic_type == ODM_RTL8192F) {
660 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
661 				for (p = RF_PATH_A; p < c.rf_path_count; p++)
662 					(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, indexforchannel);
663 			} else {
664 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
665 				for (p = RF_PATH_A; p < c.rf_path_count; p++)
666 					(*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, indexforchannel);
667 			}
668 
669 		}
670 
671 		cali_info->bb_swing_idx_cck_base = cali_info->bb_swing_idx_cck;    /*Record last time Power Tracking result as base.*/
672 		for (p = RF_PATH_A; p < c.rf_path_count; p++)
673 			cali_info->bb_swing_idx_ofdm_base[p] = cali_info->bb_swing_idx_ofdm[p];
674 
675 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
676 			"cali_info->thermal_value = %d thermal_value= %d\n", cali_info->thermal_value, thermal_value);
677 
678 		cali_info->thermal_value = thermal_value;         /*Record last Power Tracking Thermal value*/
679 
680 	}
681 
682 
683 	if (dm->support_ic_type == ODM_RTL8703B || dm->support_ic_type == ODM_RTL8723D ||
684 		dm->support_ic_type == ODM_RTL8192F || dm->support_ic_type == ODM_RTL8710B) {/* JJ ADD 20161014 */
685 
686 		if (xtal_offset_eanble != 0 && cali_info->txpowertrack_control && (hal_data->eeprom_thermal_meter != 0xff)) {
687 
688 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter Xtal Tracking**********\n");
689 
690 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
691 			if (thermal_value > hal_data->eeprom_thermal_meter) {
692 #else
693 			if (thermal_value > dm->priv->pmib->dot11RFEntry.ther) {
694 #endif
695 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
696 					"Temperature(%d) higher than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
697 				(*c.odm_txxtaltrack_set_xtal)(dm);
698 			} else {
699 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
700 					"Temperature(%d) lower than PG value(%d)\n", thermal_value, hal_data->eeprom_thermal_meter);
701 				(*c.odm_txxtaltrack_set_xtal)(dm);
702 			}
703 		}
704 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********End Xtal Tracking**********\n");
705 	}
706 
707 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
708 
709 	/* Wait sacn to do IQK by RF Jenyu*/
710 	if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden) && dm->is_linked) {
711 		if (!IS_HARDWARE_TYPE_8723B(adapter)) {
712 			/*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
713 			if (delta_IQK >= c.threshold_iqk) {
714 				cali_info->thermal_value_iqk = thermal_value;
715 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
716 				if (!cali_info->is_iqk_in_progress)
717 					(*c.do_iqk)(dm, delta_IQK, thermal_value, 8);
718 			}
719 		}
720 	}
721 	if (cali_info->dpk_thermal[RF_PATH_A] != 0) {
722 		if (diff_DPK[RF_PATH_A] >= c.threshold_dpk) {
723 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
724 			odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_A] / c.threshold_dpk));
725 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
726 		} else if ((diff_DPK[RF_PATH_A] <= -1 * c.threshold_dpk)) {
727 			s32 value = 0x20 + (diff_DPK[RF_PATH_A] / c.threshold_dpk);
728 
729 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
730 			odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
731 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
732 		} else {
733 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
734 			odm_set_bb_reg(dm, R_0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
735 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
736 		}
737 	}
738 	if (cali_info->dpk_thermal[RF_PATH_B] != 0) {
739 		if (diff_DPK[RF_PATH_B] >= c.threshold_dpk) {
740 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
741 			odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[RF_PATH_B] / c.threshold_dpk));
742 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
743 		} else if ((diff_DPK[RF_PATH_B] <= -1 * c.threshold_dpk)) {
744 			s32 value = 0x20 + (diff_DPK[RF_PATH_B] / c.threshold_dpk);
745 
746 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
747 			odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value);
748 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
749 		} else {
750 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x1);
751 			odm_set_bb_reg(dm, R_0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0);
752 			odm_set_bb_reg(dm, R_0x82c, BIT(31), 0x0);
753 		}
754 	}
755 
756 #endif
757 
758 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===odm_txpowertracking_callback_thermal_meter\n");
759 
760 	cali_info->tx_powercount = 0;
761 }
762 
763 #if (RTL8822C_SUPPORT == 1 || RTL8814B_SUPPORT == 1  || RTL8723F_SUPPORT == 1)
764 void
765 odm_txpowertracking_new_callback_thermal_meter(void *dm_void)
766 {
767 	struct dm_struct *dm = (struct dm_struct *)dm_void;
768 	struct dm_rf_calibration_struct *cali_info = &(dm->rf_calibrate_info);
769  	struct dm_iqk_info *iqk_info = &dm->IQK_info;
770 	struct _hal_rf_ *rf = &dm->rf_table;
771 	struct _halrf_tssi_data *tssi = &rf->halrf_tssi_data;
772 	u8 thermal_value[MAX_RF_PATH] = {0}, delta[MAX_RF_PATH] = {0};
773 	u8 delta_swing_table_idx_tup[DELTA_SWINGIDX_SIZE] = {0};
774 	u8 delta_swing_table_idx_tdown[DELTA_SWINGIDX_SIZE] = {0};
775 	u8 delta_LCK = 0, delta_IQK = 0, i = 0, j = 0, p;
776 	u8 thermal_value_avg_count[MAX_RF_PATH] = {0};
777 	u32 thermal_value_avg[MAX_RF_PATH] = {0};
778 	s8 thermal_value_temp[MAX_RF_PATH] = {0};
779 	u8 tracking_method = MIX_MODE;
780 
781 	struct txpwrtrack_cfg c;
782 
783 	u8 *delta_swing_table_idx_tup_a = NULL;
784 	u8 *delta_swing_table_idx_tdown_a = NULL;
785 	u8 *delta_swing_table_idx_tup_b = NULL;
786 	u8 *delta_swing_table_idx_tdown_b = NULL;
787 	u8 *delta_swing_table_idx_tup_c = NULL;
788 	u8 *delta_swing_table_idx_tdown_c = NULL;
789 	u8 *delta_swing_table_idx_tup_d = NULL;
790 	u8 *delta_swing_table_idx_tdown_d = NULL;
791 
792 	configure_txpower_track(dm, &c);
793 
794 	(*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a,
795 		(u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b);
796 
797 	if (dm->support_ic_type == ODM_RTL8814B) {
798 		(*c.get_delta_swing_table)(dm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c,
799 			(u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d);
800 	}
801 
802 	cali_info->txpowertracking_callback_cnt++;
803 	cali_info->is_txpowertracking_init = true;
804 
805 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
806 		"===>odm_txpowertracking_callback_thermal_meter\n cali_info->bb_swing_idx_cck_base: %d, cali_info->bb_swing_idx_ofdm_base[A]: %d, cali_info->default_ofdm_index: %d\n",
807 		cali_info->bb_swing_idx_cck_base, cali_info->bb_swing_idx_ofdm_base[RF_PATH_A], cali_info->default_ofdm_index);
808 
809 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
810 		"cali_info->txpowertrack_control=%d, tssi->thermal[RF_PATH_A]=%d tssi->thermal[RF_PATH_B]=%d\n",
811 		cali_info->txpowertrack_control,  tssi->thermal[RF_PATH_A], tssi->thermal[RF_PATH_B]);
812 
813 	if (dm->support_ic_type == ODM_RTL8822C) {
814 		for (i = 0; i < c.rf_path_count; i++)
815 			thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0x7e);	/* 0x42: RF Reg[6:1] Thermal Trim*/
816 	} else {
817 		for (i = 0; i < c.rf_path_count; i++) {
818 			thermal_value[i] = (u8)odm_get_rf_reg(dm, i, c.thermal_reg_addr, 0xfc00);	/* 0x42: RF Reg[15:10] 88E */
819 
820 			if (dm->support_ic_type == ODM_RTL8814B) {
821 				thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_multi_thermal_offset(dm, i);
822 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
823 					"thermal_value_temp[%d](%d) = thermal_value[%d](%d) + multi_thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_multi_thermal_offset(dm, i));
824 			} else {
825 				thermal_value_temp[i] = (s8)thermal_value[i] + phydm_get_thermal_offset(dm);
826 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
827 					"thermal_value_temp[%d](%d) = thermal_value[%d](%d) + thermal_trim(%d)\n", i, thermal_value_temp[i], i, thermal_value[i], phydm_get_thermal_offset(dm));
828 			}
829 
830 			if (thermal_value_temp[i] > 63)
831 				thermal_value[i] = 63;
832 			else if (thermal_value_temp[i] < 0)
833 				thermal_value[i] = 0;
834 			else
835 				thermal_value[i] = thermal_value_temp[i];
836 		}
837 	}
838 
839 	if ((tssi->thermal[RF_PATH_A] == 0xff || tssi->thermal[RF_PATH_B] == 0xff)) {
840 		for (i = 0; i < c.rf_path_count; i++)
841 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "no pg, tssi->thermal[%d] = 0x%x\n",
842 				i, tssi->thermal[i]);
843 		return;
844 	}
845 
846 	for (j = 0; j < c.rf_path_count; j++) {
847 		cali_info->thermal_value_avg_path[j][cali_info->thermal_value_avg_index_path[j]] = thermal_value[j];
848 		cali_info->thermal_value_avg_index_path[j]++;
849 		if (cali_info->thermal_value_avg_index_path[j] == c.average_thermal_num)   /*Average times =  c.average_thermal_num*/
850 			cali_info->thermal_value_avg_index_path[j] = 0;
851 
852 
853 		for (i = 0; i < c.average_thermal_num; i++) {
854 			if (cali_info->thermal_value_avg_path[j][i]) {
855 				thermal_value_avg[j] += cali_info->thermal_value_avg_path[j][i];
856 				thermal_value_avg_count[j]++;
857 			}
858 		}
859 
860 		if (thermal_value_avg_count[j]) {            /* Calculate Average thermal_value after average enough times */
861 			thermal_value[j] = (u8)(thermal_value_avg[j] / thermal_value_avg_count[j]);
862 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
863 				"AVG Thermal Meter = 0x%X, tssi->thermal[%d] = 0x%x\n",
864 				thermal_value[j], j, tssi->thermal[j]);
865 		}
866 		/* 4 5. Calculate delta, delta_LCK, delta_IQK. */
867 
868 		/* "delta" here is used to determine whether thermal value changes or not. */
869 		delta[j] = (thermal_value[j] > cali_info->thermal_value_path[j]) ? (thermal_value[j] - cali_info->thermal_value_path[j]) : (cali_info->thermal_value_path[j] - thermal_value[j]);
870 		delta_LCK = (thermal_value[0] > cali_info->thermal_value_lck) ? (thermal_value[0] - cali_info->thermal_value_lck) : (cali_info->thermal_value_lck - thermal_value[0]);
871 		delta_IQK = (thermal_value[0] > cali_info->thermal_value_iqk) ? (thermal_value[0] - cali_info->thermal_value_iqk) : (cali_info->thermal_value_iqk - thermal_value[0]);
872 	}
873 
874 	/*4 6. If necessary, do LCK.*/
875 
876 	for (i = 0; i < c.rf_path_count; i++)
877 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "(delta[%d], delta_LCK, delta_IQK) = (%d, %d, %d)\n", i, delta[i], delta_LCK, delta_IQK);
878 
879 	/* Wait sacn to do LCK by RF Jenyu*/
880 	if( (*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden)) {
881 		/* Delta temperature is equal to or larger than 20 centigrade.*/
882 		if (delta_LCK >= c.threshold_iqk) {
883 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk);
884 			cali_info->thermal_value_lck = thermal_value[RF_PATH_A];
885 
886 			/*Use RTLCK, so close power tracking driver LCK*/
887 			if ((!(dm->support_ic_type & ODM_RTL8814A)) &&
888 			    (!(dm->support_ic_type & ODM_RTL8822B)) &&
889 			    (!(dm->support_ic_type & ODM_RTL8723F))) {
890 				if (c.phy_lc_calibrate)
891 					(*c.phy_lc_calibrate)(dm);
892 			} else
893 				RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do not do LCK\n");
894 		}
895 	}
896 
897 	/*3 7. If necessary, move the index of swing table to adjust Tx power.*/
898 	for (i = 0; i < c.rf_path_count; i++) {
899 		if (i == RF_PATH_B) {
900 			odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_b, DELTA_SWINGIDX_SIZE);
901 			odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_b, DELTA_SWINGIDX_SIZE);
902 		} else if (i == RF_PATH_C) {
903 			odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_c, DELTA_SWINGIDX_SIZE);
904 			odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_c, DELTA_SWINGIDX_SIZE);
905 		} else if (i == RF_PATH_D) {
906 			odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_d, DELTA_SWINGIDX_SIZE);
907 			odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_d, DELTA_SWINGIDX_SIZE);
908 		} else {
909 			odm_move_memory(dm, delta_swing_table_idx_tup, delta_swing_table_idx_tup_a, DELTA_SWINGIDX_SIZE);
910 			odm_move_memory(dm, delta_swing_table_idx_tdown, delta_swing_table_idx_tdown_a, DELTA_SWINGIDX_SIZE);
911 		}
912 
913 		cali_info->delta_power_index_last[i] = cali_info->delta_power_index[i];	/*recording poer index offset*/
914 		delta[i] = thermal_value[i] > tssi->thermal[i] ? (thermal_value[i] - tssi->thermal[i]) : (tssi->thermal[i] - thermal_value[i]);
915 
916 		if (delta[i] >= TXPWR_TRACK_TABLE_SIZE)
917 			delta[i] = TXPWR_TRACK_TABLE_SIZE - 1;
918 
919 		if (thermal_value[i] > tssi->thermal[i]) {
920 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
921 				"delta_swing_table_idx_tup[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tup[delta[i]], i);
922 
923 			cali_info->delta_power_index[i] = delta_swing_table_idx_tup[delta[i]];
924 			cali_info->absolute_ofdm_swing_idx[i] =  delta_swing_table_idx_tup[delta[i]];	    /*Record delta swing for mix mode power tracking*/
925 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
926 				"******Temp is higher and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
927 		} else {
928 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
929 				"delta_swing_table_idx_tdown[%d]=%d Path=%d\n", delta[i], delta_swing_table_idx_tdown[delta[i]], i);
930 			cali_info->delta_power_index[i] = -1 * delta_swing_table_idx_tdown[delta[i]];
931 			cali_info->absolute_ofdm_swing_idx[i] = -1 * delta_swing_table_idx_tdown[delta[i]];        /*Record delta swing for mix mode power tracking*/
932 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK,
933 				"******Temp is lower and cali_info->absolute_ofdm_swing_idx[%d]=%d Path=%d\n", delta[i], cali_info->absolute_ofdm_swing_idx[i], i);
934 		}
935 	}
936 
937 	for (p = RF_PATH_A; p < c.rf_path_count; p++) {
938 		if (cali_info->delta_power_index[p] == cali_info->delta_power_index_last[p])	     /*If Thermal value changes but lookup table value still the same*/
939 			cali_info->power_index_offset[p] = 0;
940 		else
941 			cali_info->power_index_offset[p] = cali_info->delta_power_index[p] - cali_info->delta_power_index_last[p];	/*Power index diff between 2 times Power Tracking*/
942 	}
943 
944 #if 0
945 	if (dm->support_ic_type == ODM_RTL8822C) {
946 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
947 		for (p = RF_PATH_A; p < c.rf_path_count; p++)
948 			(*c.odm_tx_pwr_track_set_pwr)(dm, MIX_MODE, p, 0);
949 	} else {
950 		RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking BBSWING_MODE**********\n");
951 		for (p = RF_PATH_A; p < c.rf_path_count; p++)
952 			(*c.odm_tx_pwr_track_set_pwr)(dm, BBSWING, p, 0);
953 	}
954 #endif
955 	if (*dm->mp_mode == 1) {
956 		if (cali_info->txpowertrack_control == 1) {
957 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
958 			tracking_method = MIX_MODE;
959 		} else if (cali_info->txpowertrack_control == 3) {
960 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
961 			tracking_method = TSSI_MODE;
962 		}
963 	} else {
964 		if (rf->power_track_type >= 0 && rf->power_track_type <= 3) {
965 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking MIX_MODE**********\n");
966 			tracking_method = MIX_MODE;
967 		} else if (rf->power_track_type >= 4 && rf->power_track_type <= 7) {
968 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "**********Enter POWER Tracking TSSI_MODE**********\n");
969 			tracking_method = TSSI_MODE;
970 		}
971 	}
972 
973 	if (dm->support_ic_type == ODM_RTL8822C || dm->support_ic_type == ODM_RTL8814B)
974 		for (p = RF_PATH_A; p < c.rf_path_count; p++)
975 			(*c.odm_tx_pwr_track_set_pwr)(dm, tracking_method, p, 0);
976 
977 	/* Wait sacn to do IQK by RF Jenyu*/
978 	if ((*dm->is_scan_in_process == false) && (!iqk_info->rfk_forbidden) && (dm->is_linked || *dm->mp_mode)) {
979 		/*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/
980 		if (delta_IQK >= c.threshold_iqk) {
981 			cali_info->thermal_value_iqk = thermal_value[RF_PATH_A];
982 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "delta_IQK(%d) >= threshold_iqk(%d)\n", delta_IQK, c.threshold_iqk);
983 			/*if (!cali_info->is_iqk_in_progress)*/
984 			/*	(*c.do_iqk)(dm, delta_IQK, thermal_value[RF_PATH_A], 8);*/
985 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do IQK\n");
986 
987 			/*if (!cali_info->is_iqk_in_progress)*/
988 			/*	(*c.do_tssi_dck)(dm, true);*/
989 			RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "Do TSSI DCK\n");
990 		}
991 	}
992 
993 	RF_DBG(dm, DBG_RF_TX_PWR_TRACK, "<===%s\n", __func__);
994 
995 	cali_info->tx_powercount = 0;
996 }
997 #endif
998 
999 /* 3============================================================
1000  * 3 IQ Calibration
1001  * 3============================================================ */
1002 
1003 void
1004 odm_reset_iqk_result(
1005 	struct dm_struct	*dm
1006 )
1007 {
1008 	return;
1009 }
1010 #if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
1011 u8 odm_get_right_chnl_place_for_iqk(u8 chnl)
1012 {
1013 	u8	channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
1014 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165
1015 	};
1016 	u8	place = chnl;
1017 
1018 
1019 	if (chnl > 14) {
1020 		for (place = 14; place < sizeof(channel_all); place++) {
1021 			if (channel_all[place] == chnl)
1022 				return place - 13;
1023 		}
1024 	}
1025 	return 0;
1026 
1027 }
1028 #endif
1029 
1030 void
1031 odm_iq_calibrate(
1032 	struct dm_struct	*dm
1033 )
1034 {
1035 	void	*adapter = dm->adapter;
1036 	struct dm_iqk_info	*iqk_info = &dm->IQK_info;
1037 
1038 	RF_DBG(dm, DBG_RF_IQK, "=>%s\n",__FUNCTION__);
1039 
1040 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
1041 	if (*dm->is_fcs_mode_enable)
1042 		return;
1043 #endif
1044 	if (dm->is_linked) {
1045 		RF_DBG(dm, DBG_RF_IQK,
1046 		       "interval=%d ch=%d prech=%d scan=%s rfk_f =%s\n",
1047 		       dm->linked_interval, *dm->channel,  dm->pre_channel,
1048 		       *dm->is_scan_in_process == TRUE ? "TRUE":"FALSE",
1049 		       iqk_info->rfk_forbidden == TRUE ? "TRUE":"FALSE");
1050 
1051 		if (iqk_info->rfk_forbidden)	{
1052 			RF_DBG(dm, DBG_RF_IQK, "return by rfk_forbidden\n");
1053 			return;
1054 		}
1055 
1056 		if (*dm->is_scan_in_process)	{
1057 			RF_DBG(dm, DBG_RF_IQK, "return by is_scan_in_process\n");
1058 			return;
1059 		}
1060 
1061 		if (*dm->channel != dm->pre_channel) {
1062 			dm->pre_channel = *dm->channel;
1063 			dm->linked_interval = 0;
1064 		}
1065 
1066 		if (dm->linked_interval < 3)
1067 			dm->linked_interval++;
1068 
1069 		if (dm->linked_interval == 2)
1070 			PHY_IQCalibrate(adapter, false);
1071 	} else {
1072 		dm->linked_interval = 0;
1073 		RF_DBG(dm, DBG_RF_IQK, "is_linked =%s, interval =%d\n",
1074 		       dm->is_linked == TRUE ? "TRUE":"FALSE",
1075 		       dm->linked_interval);
1076 	}
1077 }
1078 
1079 void phydm_rf_init(struct dm_struct		*dm)
1080 {
1081 
1082 	odm_txpowertracking_init(dm);
1083 
1084 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
1085 	odm_clear_txpowertracking_state(dm);
1086 #endif
1087 
1088 #if (DM_ODM_SUPPORT_TYPE & (ODM_AP))
1089 #if (RTL8814A_SUPPORT == 1)
1090 	if (dm->support_ic_type & ODM_RTL8814A)
1091 		phy_iq_calibrate_8814a_init(dm);
1092 #endif
1093 #endif
1094 
1095 }
1096 
1097 void phydm_rf_watchdog(struct dm_struct *dm)
1098 {
1099 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
1100 	FunctionIn(COMP_MLME);
1101 
1102 	if (*dm->mp_mode == 1) {
1103 #if (MP_DRIVER == 1)
1104 		odm_txpowertracking_check(dm);
1105 #endif
1106 	} else {
1107 		odm_txpowertracking_check(dm);
1108 
1109 		if (dm->support_ic_type & (ODM_IC_11AC_SERIES |  ODM_IC_JGR3_SERIES))
1110 			odm_iq_calibrate(dm);
1111 	}
1112 #endif
1113 }
1114