1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3
4 #include "../include/drv_types.h"
5
6 /*---------------------------Define Local Constant---------------------------*/
7 /* 2010/04/25 MH Define the max tx power tracking tx agc power. */
8 #define ODM_TXPWRTRACK_MAX_IDX_88E 6
9
10 /*---------------------------Define Local Constant---------------------------*/
11
12 /* 3============================================================ */
13 /* 3 Tx Power Tracking */
14 /* 3============================================================ */
15 /*-----------------------------------------------------------------------------
16 * Function: ODM_TxPwrTrackAdjust88E()
17 *
18 * Overview: 88E we can not write 0xc80/c94/c4c/ 0xa2x. Instead of write TX agc.
19 * No matter OFDM & CCK use the same method.
20 *
21 * Input: NONE
22 *
23 * Output: NONE
24 *
25 * Return: NONE
26 *
27 * Revised History:
28 * When Who Remark
29 * 04/23/2012 MHC Create Version 0.
30 * 04/23/2012 MHC Adjust TX agc directly not throughput BB digital.
31 *
32 *---------------------------------------------------------------------------*/
ODM_TxPwrTrackAdjust88E(struct odm_dm_struct * dm_odm,u8 Type,u8 * pDirection,u32 * pOutWriteVal)33 void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *dm_odm, u8 Type,/* 0 = OFDM, 1 = CCK */
34 u8 *pDirection, /* 1 = +(increase) 2 = -(decrease) */
35 u32 *pOutWriteVal /* Tx tracking CCK/OFDM BB swing index adjust */
36 )
37 {
38 u8 pwr_value = 0;
39 /* Tx power tracking BB swing table. */
40 /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
41 if (Type == 0) { /* For OFDM afjust */
42 if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
43 *pDirection = 1;
44 pwr_value = (dm_odm->BbSwingIdxOfdmBase - dm_odm->BbSwingIdxOfdm);
45 } else {
46 *pDirection = 2;
47 pwr_value = (dm_odm->BbSwingIdxOfdm - dm_odm->BbSwingIdxOfdmBase);
48 }
49 } else if (Type == 1) { /* For CCK adjust. */
50 if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
51 *pDirection = 1;
52 pwr_value = (dm_odm->BbSwingIdxCckBase - dm_odm->BbSwingIdxCck);
53 } else {
54 *pDirection = 2;
55 pwr_value = (dm_odm->BbSwingIdxCck - dm_odm->BbSwingIdxCckBase);
56 }
57 }
58
59 /* */
60 /* 2012/04/25 MH According to Ed/Luke.Lees estimate for EVM the max tx power tracking */
61 /* need to be less than 6 power index for 88E. */
62 /* */
63 if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *pDirection == 1)
64 pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
65
66 *pOutWriteVal = pwr_value | (pwr_value << 8) | (pwr_value << 16) | (pwr_value << 24);
67 } /* ODM_TxPwrTrackAdjust88E */
68
69 /*-----------------------------------------------------------------------------
70 * Function: odm_TxPwrTrackSetPwr88E()
71 *
72 * Overview: 88E change all channel tx power accordign to flag.
73 * OFDM & CCK are all different.
74 *
75 * Input: NONE
76 *
77 * Output: NONE
78 *
79 * Return: NONE
80 *
81 * Revised History:
82 * When Who Remark
83 * 04/23/2012 MHC Create Version 0.
84 *
85 *---------------------------------------------------------------------------*/
odm_TxPwrTrackSetPwr88E(struct odm_dm_struct * dm_odm)86 static void odm_TxPwrTrackSetPwr88E(struct odm_dm_struct *dm_odm)
87 {
88 if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
89 PHY_SetTxPowerLevel8188E(dm_odm->Adapter, *dm_odm->pChannel);
90 dm_odm->BbSwingFlagOfdm = false;
91 dm_odm->BbSwingFlagCck = false;
92 }
93 } /* odm_TxPwrTrackSetPwr88E */
94
95 /* 091212 chiyokolin */
96 void
odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct adapter * Adapter)97 odm_TXPowerTrackingCallback_ThermalMeter_8188E(
98 struct adapter *Adapter
99 )
100 {
101 struct hal_data_8188e *pHalData = &Adapter->haldata;
102 u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, offset;
103 u8 ThermalValue_AVG_count = 0;
104 u32 ThermalValue_AVG = 0;
105 s32 ele_D, TempCCk;
106 s8 OFDM_index, CCK_index = 0;
107 s8 OFDM_index_old = 0, CCK_index_old = 0;
108 u32 i = 0, j = 0;
109
110 u8 OFDM_min_index = 6; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
111 s8 OFDM_index_mapping[2][index_mapping_NUM_88E] = {
112 {0, 0, 2, 3, 4, 4, /* 2.4G, decrease power */
113 5, 6, 7, 7, 8, 9,
114 10, 10, 11}, /* For lower temperature, 20120220 updated on 20120220. */
115 {0, 0, -1, -2, -3, -4, /* 2.4G, increase power */
116 -4, -4, -4, -5, -7, -8,
117 -9, -9, -10},
118 };
119 u8 Thermal_mapping[2][index_mapping_NUM_88E] = {
120 {0, 2, 4, 6, 8, 10, /* 2.4G, decrease power */
121 12, 14, 16, 18, 20, 22,
122 24, 26, 27},
123 {0, 2, 4, 6, 8, 10, /* 2.4G,, increase power */
124 12, 14, 16, 18, 20, 22,
125 25, 25, 25},
126 };
127 struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
128
129 /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
130 odm_TxPwrTrackSetPwr88E(dm_odm);
131
132 /* <Kordan> RFCalibrateInfo.RegA24 will be initialized when ODM HW configuring, but MP configures with para files. */
133 dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
134
135 ThermalValue = (u8)rtl8188e_PHY_QueryRFReg(Adapter, RF_T_METER_88E, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
136
137 if (ThermalValue) {
138 /* Query OFDM path A default setting */
139 ele_D = rtl8188e_PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord) & bMaskOFDM_D;
140 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { /* find the index */
141 if (ele_D == (OFDMSwingTable[i] & bMaskOFDM_D)) {
142 OFDM_index_old = (u8)i;
143 dm_odm->BbSwingIdxOfdmBase = (u8)i;
144 break;
145 }
146 }
147
148 /* Query CCK default setting From 0xa24 */
149 TempCCk = dm_odm->RFCalibrateInfo.RegA24;
150
151 for (i = 0; i < CCK_TABLE_SIZE; i++) {
152 if (memcmp((void *)&TempCCk, (void *)&cck_swing_table[i][2], 4)) {
153 CCK_index_old = (u8)i;
154 dm_odm->BbSwingIdxCckBase = (u8)i;
155 break;
156 }
157 }
158
159 if (!dm_odm->RFCalibrateInfo.ThermalValue) {
160 dm_odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
161 dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
162 dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
163
164 dm_odm->RFCalibrateInfo.OFDM_index = OFDM_index_old;
165 dm_odm->RFCalibrateInfo.CCK_index = CCK_index_old;
166 }
167
168 /* calculate average thermal meter */
169 dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
170 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
171 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
172 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
173
174 for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
175 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
176 ThermalValue_AVG += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
177 ThermalValue_AVG_count++;
178 }
179 }
180
181 if (ThermalValue_AVG_count)
182 ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
183
184 if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
185 delta = ThermalValue > pHalData->EEPROMThermalMeter ?
186 (ThermalValue - pHalData->EEPROMThermalMeter) :
187 (pHalData->EEPROMThermalMeter - ThermalValue);
188 dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
189 dm_odm->RFCalibrateInfo.bDoneTxpower = false;
190 } else if (dm_odm->RFCalibrateInfo.bDoneTxpower) {
191 delta = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue) ?
192 (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue) :
193 (dm_odm->RFCalibrateInfo.ThermalValue - ThermalValue);
194 } else {
195 delta = ThermalValue > pHalData->EEPROMThermalMeter ?
196 (ThermalValue - pHalData->EEPROMThermalMeter) :
197 (pHalData->EEPROMThermalMeter - ThermalValue);
198 }
199 delta_LCK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_LCK) ?
200 (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_LCK) :
201 (dm_odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
202 delta_IQK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_IQK) ?
203 (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_IQK) :
204 (dm_odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue);
205
206 if ((delta_LCK >= 8)) { /* Delta temperature is equal to or larger than 20 centigrade. */
207 dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
208 PHY_LCCalibrate_8188E(Adapter);
209 }
210
211 if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
212 delta = ThermalValue > pHalData->EEPROMThermalMeter ?
213 (ThermalValue - pHalData->EEPROMThermalMeter) :
214 (pHalData->EEPROMThermalMeter - ThermalValue);
215 /* calculate new OFDM / CCK offset */
216 if (ThermalValue > pHalData->EEPROMThermalMeter)
217 j = 1;
218 else
219 j = 0;
220 for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
221 if (delta < Thermal_mapping[j][offset]) {
222 if (offset != 0)
223 offset--;
224 break;
225 }
226 }
227 if (offset >= index_mapping_NUM_88E)
228 offset = index_mapping_NUM_88E - 1;
229 OFDM_index = dm_odm->RFCalibrateInfo.OFDM_index + OFDM_index_mapping[j][offset];
230 CCK_index = dm_odm->RFCalibrateInfo.CCK_index + OFDM_index_mapping[j][offset];
231
232 if (OFDM_index > OFDM_TABLE_SIZE_92D - 1)
233 OFDM_index = OFDM_TABLE_SIZE_92D - 1;
234 else if (OFDM_index < OFDM_min_index)
235 OFDM_index = OFDM_min_index;
236
237 if (CCK_index > CCK_TABLE_SIZE - 1)
238 CCK_index = CCK_TABLE_SIZE - 1;
239 else if (CCK_index < 0)
240 CCK_index = 0;
241
242 /* 2 temporarily remove bNOPG */
243 /* Config by SwingTable */
244 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
245 dm_odm->RFCalibrateInfo.bDoneTxpower = true;
246
247 /* Revse TX power table. */
248 dm_odm->BbSwingIdxOfdm = (u8)OFDM_index;
249 dm_odm->BbSwingIdxCck = (u8)CCK_index;
250
251 if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
252 dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
253 dm_odm->BbSwingFlagOfdm = true;
254 }
255
256 if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
257 dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
258 dm_odm->BbSwingFlagCck = true;
259 }
260 }
261 }
262
263 if (delta_IQK >= 8) { /* Delta temperature is equal to or larger than 20 centigrade. */
264 dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
265 PHY_IQCalibrate_8188E(Adapter, false);
266 }
267 /* update thermal meter value */
268 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
269 dm_odm->RFCalibrateInfo.ThermalValue = ThermalValue;
270 }
271 }
272
273 /* 1 7. IQK */
274 #define MAX_TOLERANCE 5
275 #define IQK_DELAY_TIME 1 /* ms */
276
277 static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
phy_PathA_IQK_8188E(struct adapter * adapt)278 phy_PathA_IQK_8188E(struct adapter *adapt)
279 {
280 u32 regeac, regE94, regE9C;
281 u8 result = 0x00;
282
283 /* 1 Tx IQK */
284 /* path-A IQK setting */
285 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
286 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
287 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
288 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
289
290 /* LO calibration setting */
291 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
292
293 /* One shot, path A LOK & IQK */
294 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
295 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
296
297 /* delay x ms */
298 /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
299 mdelay(IQK_DELAY_TIME_88E);
300
301 /* Check failed */
302 regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
303 regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
304 regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
305
306 if (!(regeac & BIT(28)) &&
307 (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
308 (((regE9C & 0x03FF0000) >> 16) != 0x42))
309 result |= 0x01;
310 return result;
311 }
312
313 static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
phy_PathA_RxIQK(struct adapter * adapt)314 phy_PathA_RxIQK(struct adapter *adapt)
315 {
316 u32 regeac, regE94, regE9C, regEA4, u4tmp;
317 u8 result = 0x00;
318
319 /* 1 Get TXIMR setting */
320 /* modify RXIQK mode table */
321 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
322 rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
323 rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
324 rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
325 rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
326
327 /* PA,PAD off */
328 rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x980);
329 rtl8188e_PHY_SetRFReg(adapt, 0x56, bRFRegOffsetMask, 0x51000);
330
331 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
332
333 /* IQK setting */
334 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
335 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
336
337 /* path-A IQK setting */
338 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
339 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
340 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
341 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
342
343 /* LO calibration setting */
344 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
345
346 /* One shot, path A LOK & IQK */
347 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
348 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
349
350 /* delay x ms */
351 mdelay(IQK_DELAY_TIME_88E);
352
353 /* Check failed */
354 regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
355 regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
356 regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
357
358 if (!(regeac & BIT(28)) &&
359 (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
360 (((regE9C & 0x03FF0000) >> 16) != 0x42))
361 result |= 0x01;
362 else /* if Tx not OK, ignore Rx */
363 return result;
364
365 u4tmp = 0x80007C00 | (regE94 & 0x3FF0000) | ((regE9C & 0x3FF0000) >> 16);
366 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, u4tmp);
367
368 /* 1 RX IQK */
369 /* modify RXIQK mode table */
370 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
371 rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
372 rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
373 rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
374 rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
375 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
376
377 /* IQK setting */
378 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
379
380 /* path-A IQK setting */
381 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
382 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
383 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
384 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
385
386 /* LO calibration setting */
387 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
388
389 /* One shot, path A LOK & IQK */
390 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
391 rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
392
393 /* delay x ms */
394 /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
395 mdelay(IQK_DELAY_TIME_88E);
396
397 /* Check failed */
398 regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
399 regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
400 regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
401 regEA4 = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
402
403 /* reload RF 0xdf */
404 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
405 rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x180);
406
407 if (!(regeac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
408 (((regEA4 & 0x03FF0000) >> 16) != 0x132) &&
409 (((regeac & 0x03FF0000) >> 16) != 0x36))
410 result |= 0x02;
411
412 return result;
413 }
414
patha_fill_iqk(struct adapter * adapt,bool iqkok,s32 result[][8],u8 final_candidate,bool txonly)415 static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], u8 final_candidate, bool txonly)
416 {
417 u32 Oldval_0, X, TX0_A, reg;
418 s32 Y, TX0_C;
419
420 if (final_candidate == 0xFF) {
421 return;
422 } else if (iqkok) {
423 Oldval_0 = (rtl8188e_PHY_QueryBBReg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
424
425 X = result[final_candidate][0];
426 if ((X & 0x00000200) != 0)
427 X = X | 0xFFFFFC00;
428 TX0_A = (X * Oldval_0) >> 8;
429 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
430
431 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0 >> 7) & 0x1));
432
433 Y = result[final_candidate][1];
434 if ((Y & 0x00000200) != 0)
435 Y = Y | 0xFFFFFC00;
436
437 TX0_C = (Y * Oldval_0) >> 8;
438 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C & 0x3C0) >> 6));
439 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C & 0x3F));
440
441 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0 >> 7) & 0x1));
442
443 if (txonly)
444 return;
445
446 reg = result[final_candidate][2];
447 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
448
449 reg = result[final_candidate][3] & 0x3F;
450 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
451
452 reg = (result[final_candidate][3] >> 6) & 0xF;
453 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
454 }
455 }
456
_PHY_SaveADDARegisters(struct adapter * adapt,u32 * ADDAReg,u32 * ADDABackup,u32 RegisterNum)457 void _PHY_SaveADDARegisters(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
458 {
459 u32 i;
460
461 for (i = 0; i < RegisterNum; i++) {
462 ADDABackup[i] = rtl8188e_PHY_QueryBBReg(adapt, ADDAReg[i], bMaskDWord);
463 }
464 }
465
466 /* FIXME: return an error to caller */
_PHY_SaveMACRegisters(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)467 static void _PHY_SaveMACRegisters(
468 struct adapter *adapt,
469 u32 *MACReg,
470 u32 *MACBackup
471 )
472 {
473 u32 i;
474 int res;
475
476 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
477 u8 reg;
478
479 res = rtw_read8(adapt, MACReg[i], ®);
480 if (res)
481 return;
482
483 MACBackup[i] = reg;
484 }
485
486 res = rtw_read32(adapt, MACReg[i], MACBackup + i);
487 (void)res;
488 }
489
reload_adda_reg(struct adapter * adapt,u32 * ADDAReg,u32 * ADDABackup,u32 RegiesterNum)490 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
491 {
492 u32 i;
493
494 for (i = 0; i < RegiesterNum; i++)
495 rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, ADDABackup[i]);
496 }
497
498 static void
_PHY_ReloadMACRegisters(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)499 _PHY_ReloadMACRegisters(
500 struct adapter *adapt,
501 u32 *MACReg,
502 u32 *MACBackup
503 )
504 {
505 u32 i;
506
507 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
508 rtw_write8(adapt, MACReg[i], (u8)MACBackup[i]);
509
510 rtw_write32(adapt, MACReg[i], MACBackup[i]);
511 }
512
513 static void
_PHY_PathADDAOn(struct adapter * adapt,u32 * ADDAReg)514 _PHY_PathADDAOn(
515 struct adapter *adapt,
516 u32 *ADDAReg)
517 {
518 u32 i;
519
520 rtl8188e_PHY_SetBBReg(adapt, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
521
522 for (i = 1; i < IQK_ADDA_REG_NUM; i++)
523 rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, 0x0bdb25a0);
524 }
525
526 void
_PHY_MACSettingCalibration(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)527 _PHY_MACSettingCalibration(
528 struct adapter *adapt,
529 u32 *MACReg,
530 u32 *MACBackup
531 )
532 {
533 u32 i = 0;
534
535 rtw_write8(adapt, MACReg[i], 0x3F);
536
537 for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
538 rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(3))));
539
540 rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(5))));
541 }
542
_PHY_PIModeSwitch(struct adapter * adapt,bool PIMode)543 static void _PHY_PIModeSwitch(
544 struct adapter *adapt,
545 bool PIMode
546 )
547 {
548 u32 mode;
549
550 mode = PIMode ? 0x01000100 : 0x01000000;
551 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
552 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
553 }
554
phy_SimularityCompare_8188E(struct adapter * adapt,s32 resulta[][8],u8 c1,u8 c2)555 static bool phy_SimularityCompare_8188E(
556 struct adapter *adapt,
557 s32 resulta[][8],
558 u8 c1,
559 u8 c2
560 )
561 {
562 u32 i, j, diff, sim_bitmap, bound = 0;
563 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
564 bool result = true;
565 s32 tmp1 = 0, tmp2 = 0;
566
567 bound = 4;
568 sim_bitmap = 0;
569
570 for (i = 0; i < bound; i++) {
571 if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
572 if ((resulta[c1][i] & 0x00000200) != 0)
573 tmp1 = resulta[c1][i] | 0xFFFFFC00;
574 else
575 tmp1 = resulta[c1][i];
576
577 if ((resulta[c2][i] & 0x00000200) != 0)
578 tmp2 = resulta[c2][i] | 0xFFFFFC00;
579 else
580 tmp2 = resulta[c2][i];
581 } else {
582 tmp1 = resulta[c1][i];
583 tmp2 = resulta[c2][i];
584 }
585
586 diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
587
588 if (diff > MAX_TOLERANCE) {
589 if ((i == 2 || i == 6) && !sim_bitmap) {
590 if (resulta[c1][i] + resulta[c1][i + 1] == 0)
591 final_candidate[(i / 4)] = c2;
592 else if (resulta[c2][i] + resulta[c2][i + 1] == 0)
593 final_candidate[(i / 4)] = c1;
594 else
595 sim_bitmap = sim_bitmap | (1 << i);
596 } else {
597 sim_bitmap = sim_bitmap | (1 << i);
598 }
599 }
600 }
601
602 if (sim_bitmap == 0) {
603 for (i = 0; i < (bound / 4); i++) {
604 if (final_candidate[i] != 0xFF) {
605 for (j = i * 4; j < (i + 1) * 4 - 2; j++)
606 resulta[3][j] = resulta[final_candidate[i]][j];
607 result = false;
608 }
609 }
610 return result;
611 } else {
612 if (!(sim_bitmap & 0x03)) { /* path A TX OK */
613 for (i = 0; i < 2; i++)
614 resulta[3][i] = resulta[c1][i];
615 }
616 if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
617 for (i = 2; i < 4; i++)
618 resulta[3][i] = resulta[c1][i];
619 }
620
621 if (!(sim_bitmap & 0x30)) { /* path B TX OK */
622 for (i = 4; i < 6; i++)
623 resulta[3][i] = resulta[c1][i];
624 }
625
626 if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
627 for (i = 6; i < 8; i++)
628 resulta[3][i] = resulta[c1][i];
629 }
630 return false;
631 }
632 }
633
phy_IQCalibrate_8188E(struct adapter * adapt,s32 result[][8],u8 t)634 static void phy_IQCalibrate_8188E(struct adapter *adapt, s32 result[][8], u8 t)
635 {
636 struct hal_data_8188e *pHalData = &adapt->haldata;
637 struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
638 u32 i;
639 u8 PathAOK;
640 u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
641 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
642 rRx_Wait_CCA, rTx_CCK_RFON,
643 rTx_CCK_BBON, rTx_OFDM_RFON,
644 rTx_OFDM_BBON, rTx_To_Rx,
645 rTx_To_Tx, rRx_CCK,
646 rRx_OFDM, rRx_Wait_RIFS,
647 rRx_TO_Rx, rStandby,
648 rSleep, rPMPD_ANAEN };
649 u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
650 REG_TXPAUSE, REG_BCN_CTRL,
651 REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
652
653 /* since 92C & 92D have the different define in IQK_BB_REG */
654 u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
655 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
656 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
657 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
658 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
659 };
660 u32 retryCount = 2;
661 /* Note: IQ calibration must be performed after loading */
662 /* PHY_REG.txt , and radio_a, radio_b.txt */
663
664 if (t == 0) {
665 /* Save ADDA parameters, turn Path A ADDA on */
666 _PHY_SaveADDARegisters(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
667 _PHY_SaveMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
668 _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
669 }
670
671 _PHY_PathADDAOn(adapt, ADDA_REG);
672 if (t == 0)
673 dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)rtl8188e_PHY_QueryBBReg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
674
675 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
676 /* Switch BB to PI mode to do IQ Calibration. */
677 _PHY_PIModeSwitch(adapt, true);
678 }
679
680 /* BB setting */
681 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
682 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
683 rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
684 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
685
686 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
687 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
688 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
689 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
690
691 /* MAC settings */
692 _PHY_MACSettingCalibration(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
693
694 /* Page B init */
695 /* AP or IQK */
696 rtl8188e_PHY_SetBBReg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
697
698
699 /* IQ calibration setting */
700 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
701 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
702 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
703
704 for (i = 0; i < retryCount; i++) {
705 PathAOK = phy_PathA_IQK_8188E(adapt);
706 if (PathAOK == 0x01) {
707 result[t][0] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
708 result[t][1] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
709 break;
710 }
711 }
712
713 for (i = 0; i < retryCount; i++) {
714 PathAOK = phy_PathA_RxIQK(adapt);
715 if (PathAOK == 0x03) {
716 result[t][2] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
717 result[t][3] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
718 break;
719 }
720 }
721
722 /* Back to BB mode, load original value */
723 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0);
724
725 if (t != 0) {
726 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
727 /* Switch back BB to SI mode after finish IQ Calibration. */
728 _PHY_PIModeSwitch(adapt, false);
729 }
730
731 /* Reload ADDA power saving parameters */
732 reload_adda_reg(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
733
734 /* Reload MAC parameters */
735 _PHY_ReloadMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
736
737 reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
738
739 /* Restore RX initial gain */
740 rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
741
742 /* load 0xe30 IQC default value */
743 rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
744 rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
745 }
746 }
747
phy_LCCalibrate_8188E(struct adapter * adapt)748 static void phy_LCCalibrate_8188E(struct adapter *adapt)
749 {
750 u8 tmpreg;
751 u32 RF_Amode = 0, LC_Cal;
752 int res;
753
754 /* Check continuous TX and Packet TX */
755 res = rtw_read8(adapt, 0xd03, &tmpreg);
756 if (res)
757 return;
758
759 if ((tmpreg & 0x70) != 0) /* Deal with contisuous TX case */
760 rtw_write8(adapt, 0xd03, tmpreg & 0x8F); /* disable all continuous TX */
761 else /* Deal with Packet TX case */
762 rtw_write8(adapt, REG_TXPAUSE, 0xFF); /* block all queues */
763
764 if ((tmpreg & 0x70) != 0) {
765 /* 1. Read original RF mode */
766 /* Path-A */
767 RF_Amode = rtl8188e_PHY_QueryRFReg(adapt, RF_AC, bMask12Bits);
768
769 /* 2. Set RF mode = standby mode */
770 /* Path-A */
771 rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, (RF_Amode & 0x8FFFF) | 0x10000);
772 }
773
774 /* 3. Read RF reg18 */
775 LC_Cal = rtl8188e_PHY_QueryRFReg(adapt, RF_CHNLBW, bMask12Bits);
776
777 /* 4. Set LC calibration begin bit15 */
778 rtl8188e_PHY_SetRFReg(adapt, RF_CHNLBW, bMask12Bits, LC_Cal | 0x08000);
779
780 msleep(100);
781
782 /* Restore original situation */
783 if ((tmpreg & 0x70) != 0) {
784 /* Deal with continuous TX case */
785 /* Path-A */
786 rtw_write8(adapt, 0xd03, tmpreg);
787 rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, RF_Amode);
788 } else {
789 /* Deal with Packet TX case */
790 rtw_write8(adapt, REG_TXPAUSE, 0x00);
791 }
792 }
793
PHY_IQCalibrate_8188E(struct adapter * adapt,bool recovery)794 void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery)
795 {
796 struct hal_data_8188e *pHalData = &adapt->haldata;
797 struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
798 s32 result[4][8]; /* last is final result */
799 u8 i, final_candidate;
800 bool pathaok;
801 s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC;
802 bool is12simular, is13simular, is23simular;
803 u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
804 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
805 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
806 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
807 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
808 rOFDM0_RxIQExtAnta};
809
810 if (recovery) {
811 reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
812 return;
813 }
814
815 for (i = 0; i < 8; i++) {
816 result[0][i] = 0;
817 result[1][i] = 0;
818 result[2][i] = 0;
819 if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
820 result[3][i] = 0x100;
821 else
822 result[3][i] = 0;
823 }
824 final_candidate = 0xff;
825 pathaok = false;
826 is12simular = false;
827 is23simular = false;
828 is13simular = false;
829
830 for (i = 0; i < 3; i++) {
831 phy_IQCalibrate_8188E(adapt, result, i);
832
833 if (i == 1) {
834 is12simular = phy_SimularityCompare_8188E(adapt, result, 0, 1);
835 if (is12simular) {
836 final_candidate = 0;
837 break;
838 }
839 }
840
841 if (i == 2) {
842 is13simular = phy_SimularityCompare_8188E(adapt, result, 0, 2);
843 if (is13simular) {
844 final_candidate = 0;
845
846 break;
847 }
848 is23simular = phy_SimularityCompare_8188E(adapt, result, 1, 2);
849 if (is23simular) {
850 final_candidate = 1;
851 } else {
852 final_candidate = 3;
853 }
854 }
855 }
856
857 for (i = 0; i < 4; i++) {
858 RegE94 = result[i][0];
859 RegE9C = result[i][1];
860 RegEA4 = result[i][2];
861 RegEB4 = result[i][4];
862 RegEBC = result[i][5];
863 }
864
865 if (final_candidate != 0xff) {
866 RegE94 = result[final_candidate][0];
867 RegE9C = result[final_candidate][1];
868 RegEA4 = result[final_candidate][2];
869 RegEB4 = result[final_candidate][4];
870 RegEBC = result[final_candidate][5];
871 dm_odm->RFCalibrateInfo.RegE94 = RegE94;
872 dm_odm->RFCalibrateInfo.RegE9C = RegE9C;
873 dm_odm->RFCalibrateInfo.RegEB4 = RegEB4;
874 dm_odm->RFCalibrateInfo.RegEBC = RegEBC;
875 pathaok = true;
876 } else {
877 dm_odm->RFCalibrateInfo.RegE94 = 0x100;
878 dm_odm->RFCalibrateInfo.RegEB4 = 0x100; /* X default value */
879 dm_odm->RFCalibrateInfo.RegE9C = 0x0;
880 dm_odm->RFCalibrateInfo.RegEBC = 0x0; /* Y default value */
881 }
882 if (RegE94 != 0)
883 patha_fill_iqk(adapt, pathaok, result, final_candidate, (RegEA4 == 0));
884
885 /* To Fix BSOD when final_candidate is 0xff */
886 /* by sherry 20120321 */
887 if (final_candidate < 4) {
888 for (i = 0; i < IQK_Matrix_REG_NUM; i++)
889 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting.Value[0][i] = result[final_candidate][i];
890 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting.bIQKDone = true;
891 }
892
893 _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
894 }
895
PHY_LCCalibrate_8188E(struct adapter * adapt)896 void PHY_LCCalibrate_8188E(struct adapter *adapt)
897 {
898 u32 timeout = 2000, timecount = 0;
899 struct hal_data_8188e *pHalData = &adapt->haldata;
900 struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
901
902 while (*dm_odm->pbScanInProcess && timecount < timeout) {
903 mdelay(50);
904 timecount += 50;
905 }
906
907 phy_LCCalibrate_8188E(adapt);
908 }
909