xref: /linux/drivers/staging/rtl8723bs/hal/HalPhyRf.c (revision f86fd32d)
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 
8 /* include "Mp_Precomp.h" */
9 #include "odm_precomp.h"
10 
11 
12 #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _deltaThermal) \
13 	do {\
14 		for (_offset = 0; _offset < _size; _offset++) {\
15 			if (_deltaThermal < thermalThreshold[_direction][_offset]) {\
16 				if (_offset != 0)\
17 					_offset--;\
18 				break;\
19 			} \
20 		} \
21 		if (_offset >= _size)\
22 			_offset = _size-1;\
23 	} while (0)
24 
25 
26 void ConfigureTxpowerTrack(PDM_ODM_T pDM_Odm, PTXPWRTRACK_CFG pConfig)
27 {
28 	ConfigureTxpowerTrack_8723B(pConfig);
29 }
30 
31 /*  */
32 /*  <20121113, Kordan> This function should be called when TxAGC changed. */
33 /*  Otherwise the previous compensation is gone, because we record the */
34 /*  delta of temperature between two TxPowerTracking watch dogs. */
35 /*  */
36 /*  NOTE: If Tx BB swing or Tx scaling is varified during run-time, still */
37 /*        need to call this function. */
38 /*  */
39 void ODM_ClearTxPowerTrackingState(PDM_ODM_T pDM_Odm)
40 {
41 	struct hal_com_data *pHalData = GET_HAL_DATA(pDM_Odm->Adapter);
42 	u8 p = 0;
43 
44 	pDM_Odm->BbSwingIdxCckBase = pDM_Odm->DefaultCckIndex;
45 	pDM_Odm->BbSwingIdxCck = pDM_Odm->DefaultCckIndex;
46 	pDM_Odm->RFCalibrateInfo.CCK_index = 0;
47 
48 	for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) {
49 		pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
50 		pDM_Odm->BbSwingIdxOfdm[p] = pDM_Odm->DefaultOfdmIndex;
51 		pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
52 
53 		pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
54 		pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] = 0;
55 		pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] = 0;
56 		pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
57 
58 		/*  Initial Mix mode power tracking */
59 		pDM_Odm->Absolute_OFDMSwingIdx[p] = 0;
60 		pDM_Odm->Remnant_OFDMSwingIdx[p] = 0;
61 	}
62 
63 	/* Initial at Modify Tx Scaling Mode */
64 	pDM_Odm->Modify_TxAGC_Flag_PathA = false;
65 	/* Initial at Modify Tx Scaling Mode */
66 	pDM_Odm->Modify_TxAGC_Flag_PathB = false;
67 	pDM_Odm->Remnant_CCKSwingIdx = 0;
68 	pDM_Odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
69 	pDM_Odm->RFCalibrateInfo.ThermalValue_IQK = pHalData->EEPROMThermalMeter;
70 	pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = pHalData->EEPROMThermalMeter;
71 }
72 
73 void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
74 {
75 
76 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
77 	PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
78 
79 	u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0;
80 	u8 ThermalValue_AVG_count = 0;
81 	u32 ThermalValue_AVG = 0;
82 
83 	u8 OFDM_min_index = 0;  /*  OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
84 	u8 Indexforchannel = 0; /*  GetRightChnlPlaceforIQK(pHalData->CurrentChannel) */
85 
86 	TXPWRTRACK_CFG c;
87 
88 
89 	/* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */
90 	u8 *deltaSwingTableIdx_TUP_A;
91 	u8 *deltaSwingTableIdx_TDOWN_A;
92 	u8 *deltaSwingTableIdx_TUP_B;
93 	u8 *deltaSwingTableIdx_TDOWN_B;
94 
95 	/* 4 2. Initilization (7 steps in total) */
96 
97 	ConfigureTxpowerTrack(pDM_Odm, &c);
98 
99 	(*c.GetDeltaSwingTable)(
100 		pDM_Odm,
101 		(u8 **)&deltaSwingTableIdx_TUP_A,
102 		(u8 **)&deltaSwingTableIdx_TDOWN_A,
103 		(u8 **)&deltaSwingTableIdx_TUP_B,
104 		(u8 **)&deltaSwingTableIdx_TDOWN_B
105 	);
106 
107 	/* cosa add for debug */
108 	pDM_Odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
109 	pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
110 
111 	ODM_RT_TRACE(
112 		pDM_Odm,
113 		ODM_COMP_TX_PWR_TRACK,
114 		ODM_DBG_LOUD,
115 		(
116 			"===>ODM_TXPowerTrackingCallback_ThermalMeter,\npDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]: %d, pDM_Odm->DefaultOfdmIndex: %d\n",
117 			pDM_Odm->BbSwingIdxCckBase,
118 			pDM_Odm->BbSwingIdxOfdmBase[ODM_RF_PATH_A],
119 			pDM_Odm->DefaultOfdmIndex
120 		)
121 	);
122 
123 	ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00);	/* 0x42: RF Reg[15:10] 88E */
124 	if (
125 		!pDM_Odm->RFCalibrateInfo.TxPowerTrackControl ||
126 		pHalData->EEPROMThermalMeter == 0 ||
127 		pHalData->EEPROMThermalMeter == 0xFF
128 	)
129 		return;
130 
131 	/* 4 3. Initialize ThermalValues of RFCalibrateInfo */
132 
133 	if (pDM_Odm->RFCalibrateInfo.bReloadtxpowerindex)
134 		ODM_RT_TRACE(
135 			pDM_Odm,
136 			ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
137 			("reload ofdm index for band switch\n")
138 		);
139 
140 	/* 4 4. Calculate average thermal meter */
141 
142 	pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
143 	pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index++;
144 	if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index == c.AverageThermalNum)   /* Average times =  c.AverageThermalNum */
145 		pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
146 
147 	for (i = 0; i < c.AverageThermalNum; i++) {
148 		if (pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
149 			ThermalValue_AVG += pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[i];
150 			ThermalValue_AVG_count++;
151 		}
152 	}
153 
154 	/* Calculate Average ThermalValue after average enough times */
155 	if (ThermalValue_AVG_count) {
156 		ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
157 		ODM_RT_TRACE(
158 			pDM_Odm,
159 			ODM_COMP_TX_PWR_TRACK,
160 			ODM_DBG_LOUD,
161 			(
162 				"AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
163 				ThermalValue,
164 				pHalData->EEPROMThermalMeter
165 			)
166 		);
167 	}
168 
169 	/* 4 5. Calculate delta, delta_LCK, delta_IQK. */
170 	/* delta" here is used to determine whether thermal value changes or not. */
171 	delta =
172 		(ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) ?
173 		(ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue) :
174 		(pDM_Odm->RFCalibrateInfo.ThermalValue - ThermalValue);
175 	delta_LCK =
176 		(ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) ?
177 		(ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) :
178 		(pDM_Odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
179 	delta_IQK =
180 		(ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_IQK) ?
181 		(ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_IQK) :
182 		(pDM_Odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue);
183 
184 	ODM_RT_TRACE(
185 		pDM_Odm,
186 		ODM_COMP_TX_PWR_TRACK,
187 		ODM_DBG_LOUD,
188 		(
189 			"(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
190 			delta,
191 			delta_LCK,
192 			delta_IQK
193 		)
194 	);
195 
196 	/* 4 6. If necessary, do LCK. */
197 	/*  Delta temperature is equal to or larger than 20 centigrade. */
198 	if (delta_LCK >= c.Threshold_IQK) {
199 		ODM_RT_TRACE(
200 			pDM_Odm,
201 			ODM_COMP_TX_PWR_TRACK,
202 			ODM_DBG_LOUD,
203 			(
204 				"delta_LCK(%d) >= Threshold_IQK(%d)\n",
205 				delta_LCK,
206 				c.Threshold_IQK
207 			)
208 		);
209 		pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
210 		if (c.PHY_LCCalibrate)
211 			(*c.PHY_LCCalibrate)(pDM_Odm);
212 	}
213 
214 	/* 3 7. If necessary, move the index of swing table to adjust Tx power. */
215 	if (delta > 0 && pDM_Odm->RFCalibrateInfo.TxPowerTrackControl) {
216 		/* delta" here is used to record the absolute value of differrence. */
217 		delta =
218 			ThermalValue > pHalData->EEPROMThermalMeter ?
219 			(ThermalValue - pHalData->EEPROMThermalMeter) :
220 			(pHalData->EEPROMThermalMeter - ThermalValue);
221 
222 		if (delta >= TXPWR_TRACK_TABLE_SIZE)
223 			delta = TXPWR_TRACK_TABLE_SIZE - 1;
224 
225 		/* 4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset */
226 		if (ThermalValue > pHalData->EEPROMThermalMeter) {
227 			ODM_RT_TRACE(
228 				pDM_Odm,
229 				ODM_COMP_TX_PWR_TRACK,
230 				ODM_DBG_LOUD,
231 				(
232 					"deltaSwingTableIdx_TUP_A[%d] = %d\n",
233 					delta,
234 					deltaSwingTableIdx_TUP_A[delta]
235 				)
236 			);
237 			pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] =
238 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A];
239 			pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] =
240 				deltaSwingTableIdx_TUP_A[delta];
241 
242 			/*  Record delta swing for mix mode power tracking */
243 			pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] =
244 				deltaSwingTableIdx_TUP_A[delta];
245 
246 			ODM_RT_TRACE(
247 				pDM_Odm,
248 				ODM_COMP_TX_PWR_TRACK,
249 				ODM_DBG_LOUD,
250 				(
251 					"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
252 					pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A]
253 				)
254 			);
255 
256 			if (c.RfPathCount > 1) {
257 				ODM_RT_TRACE(
258 					pDM_Odm,
259 					ODM_COMP_TX_PWR_TRACK,
260 					ODM_DBG_LOUD,
261 					(
262 						"deltaSwingTableIdx_TUP_B[%d] = %d\n",
263 						delta,
264 						deltaSwingTableIdx_TUP_B[delta]
265 					)
266 				);
267 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] =
268 					pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B];
269 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] =
270 					deltaSwingTableIdx_TUP_B[delta];
271 
272 				/*  Record delta swing for mix mode power tracking */
273 				pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] =
274 					deltaSwingTableIdx_TUP_B[delta];
275 				ODM_RT_TRACE(
276 					pDM_Odm,
277 					ODM_COMP_TX_PWR_TRACK,
278 					ODM_DBG_LOUD,
279 					(
280 						"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
281 						pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B]
282 					)
283 				);
284 			}
285 
286 		} else {
287 			ODM_RT_TRACE(
288 				pDM_Odm,
289 				ODM_COMP_TX_PWR_TRACK,
290 				ODM_DBG_LOUD,
291 				(
292 					"deltaSwingTableIdx_TDOWN_A[%d] = %d\n",
293 					delta,
294 					deltaSwingTableIdx_TDOWN_A[delta]
295 				)
296 			);
297 
298 			pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] =
299 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A];
300 			pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] =
301 				-1 * deltaSwingTableIdx_TDOWN_A[delta];
302 
303 			/*  Record delta swing for mix mode power tracking */
304 			pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] =
305 				-1 * deltaSwingTableIdx_TDOWN_A[delta];
306 
307 			ODM_RT_TRACE(
308 				pDM_Odm,
309 				ODM_COMP_TX_PWR_TRACK,
310 				ODM_DBG_LOUD,
311 				(
312 					"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
313 					pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A]
314 				)
315 			);
316 
317 			if (c.RfPathCount > 1) {
318 				ODM_RT_TRACE(
319 					pDM_Odm,
320 					ODM_COMP_TX_PWR_TRACK,
321 					ODM_DBG_LOUD,
322 					(
323 						"deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
324 						delta,
325 						deltaSwingTableIdx_TDOWN_B[delta]
326 					)
327 				);
328 
329 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] =
330 					pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B];
331 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] =
332 					-1 * deltaSwingTableIdx_TDOWN_B[delta];
333 
334 				 /*  Record delta swing for mix mode power tracking */
335 				pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] =
336 					-1 * deltaSwingTableIdx_TDOWN_B[delta];
337 
338 				ODM_RT_TRACE(
339 					pDM_Odm,
340 					ODM_COMP_TX_PWR_TRACK,
341 					ODM_DBG_LOUD,
342 					(
343 						"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
344 						pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B]
345 					)
346 				);
347 			}
348 		}
349 
350 		for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) {
351 			ODM_RT_TRACE(
352 				pDM_Odm,
353 				ODM_COMP_TX_PWR_TRACK,
354 				ODM_DBG_LOUD,
355 				(
356 					"\n\n ================================ [Path-%c] Calculating PowerIndexOffset ================================\n",
357 					(p == ODM_RF_PATH_A ? 'A' : 'B')
358 				)
359 			);
360 
361 			if (
362 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] ==
363 				pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]
364 			) /*  If Thermal value changes but lookup table value still the same */
365 				pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
366 			else
367 				pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p];      /*  Power Index Diff between 2 times Power Tracking */
368 
369 			ODM_RT_TRACE(
370 				pDM_Odm,
371 				ODM_COMP_TX_PWR_TRACK,
372 				ODM_DBG_LOUD,
373 				(
374 					"[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
375 					(
376 						p == ODM_RF_PATH_A ? 'A' : 'B'),
377 						pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p],
378 						pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p],
379 						pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]
380 					)
381 				);
382 
383 			pDM_Odm->RFCalibrateInfo.OFDM_index[p] =
384 				pDM_Odm->BbSwingIdxOfdmBase[p] +
385 				pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
386 
387 			pDM_Odm->RFCalibrateInfo.CCK_index =
388 				pDM_Odm->BbSwingIdxCckBase +
389 				pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p];
390 
391 			pDM_Odm->BbSwingIdxCck =
392 				pDM_Odm->RFCalibrateInfo.CCK_index;
393 
394 			pDM_Odm->BbSwingIdxOfdm[p] =
395 				pDM_Odm->RFCalibrateInfo.OFDM_index[p];
396 
397 			/*  *************Print BB Swing Base and Index Offset************* */
398 			ODM_RT_TRACE(
399 				pDM_Odm,
400 				ODM_COMP_TX_PWR_TRACK,
401 				ODM_DBG_LOUD,
402 				(
403 					"The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
404 					pDM_Odm->BbSwingIdxCck,
405 					pDM_Odm->BbSwingIdxCckBase,
406 					pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p]
407 				)
408 			);
409 			ODM_RT_TRACE(
410 				pDM_Odm,
411 				ODM_COMP_TX_PWR_TRACK,
412 				ODM_DBG_LOUD,
413 				(
414 					"The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
415 					pDM_Odm->BbSwingIdxOfdm[p],
416 					(p == ODM_RF_PATH_A ? 'A' : 'B'),
417 					pDM_Odm->BbSwingIdxOfdmBase[p],
418 					pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p]
419 				)
420 			);
421 
422 			/* 4 7.1 Handle boundary conditions of index. */
423 			if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] > c.SwingTableSize_OFDM-1)
424 				pDM_Odm->RFCalibrateInfo.OFDM_index[p] = c.SwingTableSize_OFDM-1;
425 			else if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] < OFDM_min_index)
426 				pDM_Odm->RFCalibrateInfo.OFDM_index[p] = OFDM_min_index;
427 		}
428 		ODM_RT_TRACE(
429 			pDM_Odm,
430 			ODM_COMP_TX_PWR_TRACK,
431 			ODM_DBG_LOUD,
432 			("\n\n ========================================================================================================\n")
433 		);
434 		if (pDM_Odm->RFCalibrateInfo.CCK_index > c.SwingTableSize_CCK-1)
435 			pDM_Odm->RFCalibrateInfo.CCK_index = c.SwingTableSize_CCK-1;
436 		/* else if (pDM_Odm->RFCalibrateInfo.CCK_index < 0) */
437 			/* pDM_Odm->RFCalibrateInfo.CCK_index = 0; */
438 	} else {
439 		ODM_RT_TRACE(
440 			pDM_Odm,
441 			ODM_COMP_TX_PWR_TRACK,
442 			ODM_DBG_LOUD,
443 			(
444 				"The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
445 				pDM_Odm->RFCalibrateInfo.TxPowerTrackControl,
446 				ThermalValue,
447 				pDM_Odm->RFCalibrateInfo.ThermalValue
448 			)
449 		);
450 
451 			for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
452 				pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
453 	}
454 	ODM_RT_TRACE(
455 		pDM_Odm,
456 		ODM_COMP_TX_PWR_TRACK,
457 		ODM_DBG_LOUD,
458 		(
459 			"TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
460 			pDM_Odm->RFCalibrateInfo.CCK_index,
461 			pDM_Odm->BbSwingIdxCckBase
462 		)
463 	);
464 
465 	/* Print Swing base & current */
466 	for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) {
467 		ODM_RT_TRACE(
468 			pDM_Odm,
469 			ODM_COMP_TX_PWR_TRACK,
470 			ODM_DBG_LOUD,
471 			(
472 				"TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
473 				pDM_Odm->RFCalibrateInfo.OFDM_index[p],
474 				(p == ODM_RF_PATH_A ? 'A' : 'B'),
475 				pDM_Odm->BbSwingIdxOfdmBase[p]
476 			)
477 		);
478 	}
479 
480 	if (
481 		(pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A] != 0 ||
482 		 pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B] != 0) &&
483 		 pDM_Odm->RFCalibrateInfo.TxPowerTrackControl
484 	 ) {
485 		/* 4 7.2 Configure the Swing Table to adjust Tx Power. */
486 
487 		pDM_Odm->RFCalibrateInfo.bTxPowerChanged = true; /*  Always true after Tx Power is adjusted by power tracking. */
488 		/*  */
489 		/*  2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
490 		/*  to increase TX power. Otherwise, EVM will be bad. */
491 		/*  */
492 		/*  2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
493 		if (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) {
494 			ODM_RT_TRACE(
495 				pDM_Odm,
496 				ODM_COMP_TX_PWR_TRACK,
497 				ODM_DBG_LOUD,
498 				(
499 					"Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
500 					pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A],
501 					delta,
502 					ThermalValue,
503 					pHalData->EEPROMThermalMeter,
504 					pDM_Odm->RFCalibrateInfo.ThermalValue
505 				)
506 			);
507 
508 			if (c.RfPathCount > 1)
509 				ODM_RT_TRACE(
510 					pDM_Odm,
511 					ODM_COMP_TX_PWR_TRACK,
512 					ODM_DBG_LOUD,
513 					(
514 						"Temperature Increasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
515 						pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B],
516 						delta,
517 						ThermalValue,
518 						pHalData->EEPROMThermalMeter,
519 						pDM_Odm->RFCalibrateInfo.ThermalValue
520 					)
521 				);
522 
523 		} else if (ThermalValue < pDM_Odm->RFCalibrateInfo.ThermalValue) { /*  Low temperature */
524 			ODM_RT_TRACE(
525 				pDM_Odm,
526 				ODM_COMP_TX_PWR_TRACK,
527 				ODM_DBG_LOUD,
528 				(
529 					"Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
530 					pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A],
531 					delta,
532 					ThermalValue,
533 					pHalData->EEPROMThermalMeter,
534 					pDM_Odm->RFCalibrateInfo.ThermalValue
535 				)
536 			);
537 
538 			if (c.RfPathCount > 1)
539 				ODM_RT_TRACE(
540 					pDM_Odm,
541 					ODM_COMP_TX_PWR_TRACK,
542 					ODM_DBG_LOUD,
543 					(
544 						"Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
545 						pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B],
546 						delta,
547 						ThermalValue,
548 						pHalData->EEPROMThermalMeter,
549 						pDM_Odm->RFCalibrateInfo.ThermalValue
550 					)
551 				);
552 
553 		}
554 
555 		if (ThermalValue > pHalData->EEPROMThermalMeter) {
556 			ODM_RT_TRACE(
557 				pDM_Odm,
558 				ODM_COMP_TX_PWR_TRACK,
559 				ODM_DBG_LOUD,
560 				(
561 					"Temperature(%d) higher than PG value(%d)\n",
562 					ThermalValue,
563 					pHalData->EEPROMThermalMeter
564 				)
565 			);
566 
567 			ODM_RT_TRACE(
568 				pDM_Odm,
569 				ODM_COMP_TX_PWR_TRACK,
570 				ODM_DBG_LOUD,
571 				("**********Enter POWER Tracking MIX_MODE**********\n")
572 			);
573 			for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
574 					(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0);
575 		} else {
576 			ODM_RT_TRACE(
577 				pDM_Odm,
578 				ODM_COMP_TX_PWR_TRACK,
579 				ODM_DBG_LOUD,
580 				(
581 					"Temperature(%d) lower than PG value(%d)\n",
582 					ThermalValue,
583 					pHalData->EEPROMThermalMeter
584 				)
585 			);
586 
587 			ODM_RT_TRACE(
588 				pDM_Odm,
589 				ODM_COMP_TX_PWR_TRACK,
590 				ODM_DBG_LOUD,
591 				("**********Enter POWER Tracking MIX_MODE**********\n")
592 			);
593 			for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
594 				(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel);
595 		}
596 
597 		/*  Record last time Power Tracking result as base. */
598 		pDM_Odm->BbSwingIdxCckBase = pDM_Odm->BbSwingIdxCck;
599 		for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
600 			pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->BbSwingIdxOfdm[p];
601 
602 		ODM_RT_TRACE(
603 			pDM_Odm,
604 			ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
605 			(
606 				"pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue = %d\n",
607 				pDM_Odm->RFCalibrateInfo.ThermalValue,
608 				ThermalValue
609 			)
610 		);
611 
612 		/* Record last Power Tracking Thermal Value */
613 		pDM_Odm->RFCalibrateInfo.ThermalValue = ThermalValue;
614 	}
615 
616 	ODM_RT_TRACE(
617 		pDM_Odm,
618 		ODM_COMP_TX_PWR_TRACK,
619 		ODM_DBG_LOUD,
620 		("<===ODM_TXPowerTrackingCallback_ThermalMeter\n")
621 	);
622 
623 	pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
624 }
625