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