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