xref: /linux/drivers/staging/rtl8723bs/hal/HalPhyRf.c (revision 44f57d78)
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 
626 
627 
628 
629 /* 3 ============================================================ */
630 /* 3 IQ Calibration */
631 /* 3 ============================================================ */
632 
633 u8 ODM_GetRightChnlPlaceforIQK(u8 chnl)
634 {
635 	u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
636 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
637 		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
638 		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
639 		114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
640 		134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
641 		161, 163, 165
642 	};
643 	u8 place = chnl;
644 
645 
646 	if (chnl > 14) {
647 		for (place = 14; place < sizeof(channel_all); place++) {
648 			if (channel_all[place] == chnl)
649 				return place-13;
650 		}
651 	}
652 	return 0;
653 
654 }
655