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