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