1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _RTL8188E_PHYCFG_C_
17 #include <osdep_service.h>
18 #include <drv_types.h>
20 #include <rtl8188e_hal.h>
24 #define MAX_PRECMD_CNT 16
25 #define MAX_RFDEPENDCMD_CNT 16
26 #define MAX_POSTCMD_CNT 16
28 #define MAX_DOZE_WAITING_TIMES_9x 64
30 static u32 cal_bit_shift(u32 bitmask)
34 for (i = 0; i <= 31; i++) {
35 if (((bitmask >> i) & 0x1) == 1)
41 u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
43 u32 return_value = 0, original_value, bit_shift;
45 original_value = usb_read32(adapt, regaddr);
46 bit_shift = cal_bit_shift(bitmask);
47 return_value = (original_value & bitmask) >> bit_shift;
51 void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
53 u32 original_value, bit_shift;
55 if (bitmask != bMaskDWord) { /* if not "double word" write */
56 original_value = usb_read32(adapt, regaddr);
57 bit_shift = cal_bit_shift(bitmask);
58 data = (original_value & (~bitmask)) | (data << bit_shift);
61 usb_write32(adapt, regaddr, data);
64 static u32 rf_serial_read(struct adapter *adapt,
65 enum rf_radio_path rfpath, u32 offset)
68 struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
69 u32 tmplong, tmplong2;
74 tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
75 if (rfpath == RF_PATH_A)
78 tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
81 tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
82 (offset<<23) | bLSSIReadEdge;
84 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
85 tmplong&(~bLSSIReadEdge));
88 phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
93 if (rfpath == RF_PATH_A)
94 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
95 else if (rfpath == RF_PATH_B)
96 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
99 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
102 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
107 static void rf_serial_write(struct adapter *adapt,
108 enum rf_radio_path rfpath, u32 offset,
111 u32 data_and_addr = 0;
112 struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
115 data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
116 phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
119 u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
120 u32 reg_addr, u32 bit_mask)
122 u32 original_value, readback_value, bit_shift;
124 original_value = rf_serial_read(adapt, rf_path, reg_addr);
125 bit_shift = cal_bit_shift(bit_mask);
126 readback_value = (original_value & bit_mask) >> bit_shift;
127 return readback_value;
130 void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
131 u32 reg_addr, u32 bit_mask, u32 data)
133 u32 original_value, bit_shift;
135 /* RF data is 12 bits only */
136 if (bit_mask != bRFRegOffsetMask) {
137 original_value = rf_serial_read(adapt, rf_path, reg_addr);
138 bit_shift = cal_bit_shift(bit_mask);
139 data = (original_value & (~bit_mask)) | (data << bit_shift);
142 rf_serial_write(adapt, rf_path, reg_addr, data);
145 static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
146 u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
148 struct hal_data_8188e *hal_data = adapt->HalData;
149 u8 index = (channel - 1);
150 u8 TxCount = 0, path_nums;
154 for (TxCount = 0; TxCount < path_nums; TxCount++) {
155 if (TxCount == RF_PATH_A) {
156 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
157 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
158 hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
160 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
161 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
162 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
163 } else if (TxCount == RF_PATH_B) {
164 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
165 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
166 hal_data->BW20_24G_Diff[RF_PATH_A][index]+
167 hal_data->BW20_24G_Diff[TxCount][index];
169 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
170 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
171 hal_data->BW20_24G_Diff[TxCount][index];
172 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
177 static void phy_power_index_check(struct adapter *adapt, u8 channel,
178 u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
181 struct hal_data_8188e *hal_data = adapt->HalData;
183 hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
184 hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
185 hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
186 hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
189 void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
191 u8 cck_pwr[MAX_TX_COUNT] = {0};
192 u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
193 u8 bw20_pwr[MAX_TX_COUNT] = {0};
194 u8 bw40_pwr[MAX_TX_COUNT] = {0};
196 get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
197 &bw20_pwr[0], &bw40_pwr[0]);
199 phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
200 &bw20_pwr[0], &bw40_pwr[0]);
202 rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
203 rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
204 &bw40_pwr[0], channel);
207 static void phy_set_bw_mode_callback(struct adapter *adapt)
209 struct hal_data_8188e *hal_data = adapt->HalData;
213 if (hal_data->rf_chip == RF_PSEUDO_11N)
216 /* There is no 40MHz mode in RF_8225. */
217 if (hal_data->rf_chip == RF_8225)
220 if (adapt->bDriverStopped)
223 /* Set MAC register */
225 reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
226 reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
228 switch (hal_data->CurrentChannelBW) {
229 case HT_CHANNEL_WIDTH_20:
230 reg_bw_opmode |= BW_OPMODE_20MHZ;
231 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
233 case HT_CHANNEL_WIDTH_40:
234 reg_bw_opmode &= ~BW_OPMODE_20MHZ;
235 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
236 reg_prsr_rsc = (reg_prsr_rsc&0x90) |
237 (hal_data->nCur40MhzPrimeSC<<5);
238 usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
244 /* Set PHY related register */
245 switch (hal_data->CurrentChannelBW) {
246 case HT_CHANNEL_WIDTH_20:
247 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
248 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
250 case HT_CHANNEL_WIDTH_40:
251 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
252 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
253 /* Set Control channel to upper or lower.
254 * These settings are required only for 40MHz
256 phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
257 (hal_data->nCur40MhzPrimeSC>>1));
258 phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
259 hal_data->nCur40MhzPrimeSC);
260 phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
261 (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
267 /* Set RF related register */
268 if (hal_data->rf_chip == RF_6052)
269 rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
272 void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth,
273 unsigned char offset)
275 struct hal_data_8188e *hal_data = adapt->HalData;
276 enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
278 hal_data->CurrentChannelBW = bandwidth;
279 hal_data->nCur40MhzPrimeSC = offset;
281 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
282 phy_set_bw_mode_callback(adapt);
284 hal_data->CurrentChannelBW = tmp_bw;
287 static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
291 struct hal_data_8188e *hal_data = adapt->HalData;
293 phy_set_tx_power_level(adapt, channel);
297 for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) {
298 hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] &
299 0xfffffc00) | param2;
300 phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1,
301 bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]);
305 void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
307 struct hal_data_8188e *hal_data = adapt->HalData;
308 u8 tmpchannel = hal_data->CurrentChannel;
310 if (hal_data->rf_chip == RF_PSEUDO_11N)
316 hal_data->CurrentChannel = channel;
318 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
319 phy_sw_chnl_callback(adapt, channel);
321 hal_data->CurrentChannel = tmpchannel;
324 #define ODM_TXPWRTRACK_MAX_IDX_88E 6
326 static u8 get_right_chnl_for_iqk(u8 chnl)
329 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
330 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
331 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
332 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
333 155, 157, 159, 161, 163, 165
337 for (place = 0; place < sizeof(channel_all); place++) {
338 if (channel_all[place] == chnl)
345 void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
346 u8 *direction, u32 *out_write_val)
349 /* Tx power tracking BB swing table. */
350 if (type == 0) { /* For OFDM adjust */
351 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
352 ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
353 dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
355 if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
357 pwr_value = dm_odm->BbSwingIdxOfdmBase -
358 dm_odm->BbSwingIdxOfdm;
361 pwr_value = dm_odm->BbSwingIdxOfdm -
362 dm_odm->BbSwingIdxOfdmBase;
365 } else if (type == 1) { /* For CCK adjust. */
366 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
367 ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
368 dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
370 if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
372 pwr_value = dm_odm->BbSwingIdxCckBase -
373 dm_odm->BbSwingIdxCck;
376 pwr_value = dm_odm->BbSwingIdxCck -
377 dm_odm->BbSwingIdxCckBase;
382 if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
383 pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
385 *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
389 static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
391 if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
392 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
393 ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
394 phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
395 dm_odm->BbSwingFlagOfdm = false;
396 dm_odm->BbSwingFlagCck = false;
400 void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
402 struct hal_data_8188e *hal_data = adapt->HalData;
403 u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
404 u8 thermal_avg_count = 0;
407 s8 ofdm_index[2], cck_index = 0;
408 s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
412 u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */
413 s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
414 /* 2.4G, decrease power */
415 {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
416 /* 2.4G, increase power */
417 {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
419 u8 thermal_mapping[2][index_mapping_NUM_88E] = {
420 /* 2.4G, decrease power */
421 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
422 /* 2.4G, increase power */
423 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
425 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
427 dm_txpwr_track_setpwr(dm_odm);
429 dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
430 dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
432 dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
434 thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A,
435 RF_T_METER_88E, 0xfc00);
443 /* Query OFDM path A default setting */
444 ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
445 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
446 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
447 ofdm_index_old[0] = (u8)i;
448 dm_odm->BbSwingIdxOfdmBase = (u8)i;
453 /* Query OFDM path B default setting */
455 ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D;
456 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
457 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
458 ofdm_index_old[1] = (u8)i;
464 /* Query CCK default setting From 0xa24 */
465 temp_cck = dm_odm->RFCalibrateInfo.RegA24;
467 for (i = 0; i < CCK_TABLE_SIZE; i++) {
468 if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
469 memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
470 memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
471 cck_index_old = (u8)i;
472 dm_odm->BbSwingIdxCckBase = (u8)i;
477 if (!dm_odm->RFCalibrateInfo.ThermalValue) {
478 dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
479 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
480 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
482 for (i = 0; i < rf; i++)
483 dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i];
484 dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
487 /* calculate average thermal meter */
488 dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
489 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
490 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
491 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
493 for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
494 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
495 thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
500 if (thermal_avg_count)
501 thermal_val = (u8)(thermal_avg / thermal_avg_count);
503 if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
504 !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
505 delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
507 delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
508 if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
509 dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
510 dm_odm->RFCalibrateInfo.bDoneTxpower = false;
514 delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
515 delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
517 /* Delta temperature is equal to or larger than 20 centigrade.*/
518 if ((delta_lck >= 8)) {
519 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
520 rtl88eu_phy_lc_calibrate(adapt);
523 if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
524 delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
526 /* calculate new OFDM / CCK offset */
527 if (thermal_val > hal_data->EEPROMThermalMeter)
531 for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
532 if (delta < thermal_mapping[j][offset]) {
538 if (offset >= index_mapping_NUM_88E)
539 offset = index_mapping_NUM_88E-1;
541 /* Updating ofdm_index values with new OFDM / CCK offset */
542 for (i = 0; i < rf; i++) {
543 ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
544 if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1)
545 ofdm_index[i] = OFDM_TABLE_SIZE_92D-1;
546 else if (ofdm_index[i] < ofdm_min_index)
547 ofdm_index[i] = ofdm_min_index;
550 cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
551 if (cck_index > CCK_TABLE_SIZE-1)
552 cck_index = CCK_TABLE_SIZE-1;
553 else if (cck_index < 0)
556 /* 2 temporarily remove bNOPG */
557 /* Config by SwingTable */
558 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
559 dm_odm->RFCalibrateInfo.bDoneTxpower = true;
561 /* Revse TX power table. */
562 dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
563 dm_odm->BbSwingIdxCck = (u8)cck_index;
565 if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
566 dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
567 dm_odm->BbSwingFlagOfdm = true;
570 if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
571 dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
572 dm_odm->BbSwingFlagCck = true;
577 /* Delta temperature is equal to or larger than 20 centigrade.*/
578 if (delta_iqk >= 8) {
579 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
580 rtl88eu_phy_iq_calibrate(adapt, false);
582 /* update thermal meter value */
583 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
584 dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
586 dm_odm->RFCalibrateInfo.TXPowercount = 0;
589 #define MAX_TOLERANCE 5
591 static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
593 u32 reg_eac, reg_e94, reg_e9c;
597 /* path-A IQK setting */
598 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
599 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
600 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
601 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
603 /* LO calibration setting */
604 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
606 /* One shot, path A LOK & IQK */
607 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
608 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
610 mdelay(IQK_DELAY_TIME_88E);
612 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
613 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
614 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
616 if (!(reg_eac & BIT(28)) &&
617 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
618 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
623 static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
625 u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
627 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
629 /* 1 Get TXIMR setting */
630 /* modify RXIQK mode table */
631 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
632 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
633 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
634 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
635 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
638 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
639 phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
641 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
644 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
645 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
647 /* path-A IQK setting */
648 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
649 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
650 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
651 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
653 /* LO calibration setting */
654 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
656 /* One shot, path A LOK & IQK */
657 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
658 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
661 mdelay(IQK_DELAY_TIME_88E);
664 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
665 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
666 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
668 if (!(reg_eac & BIT(28)) &&
669 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
670 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
672 else /* if Tx not OK, ignore Rx */
675 u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16);
676 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
679 /* modify RXIQK mode table */
680 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
681 ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
682 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
683 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
684 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
685 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
686 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
687 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
690 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
692 /* path-A IQK setting */
693 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
694 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
695 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
696 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
698 /* LO calibration setting */
699 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
701 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
702 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
704 mdelay(IQK_DELAY_TIME_88E);
707 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
708 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
709 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
710 reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
713 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
714 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
716 if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
717 (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
718 (((reg_eac & 0x03FF0000)>>16) != 0x36))
721 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
722 ("Path A Rx IQK fail!!\n"));
727 static u8 phy_path_b_iqk(struct adapter *adapt)
729 u32 regeac, regeb4, regebc, regec4, regecc;
731 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
733 /* One shot, path B LOK & IQK */
734 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
735 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
737 mdelay(IQK_DELAY_TIME_88E);
739 regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
740 regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
741 regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
742 regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
743 regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
745 if (!(regeac & BIT(31)) &&
746 (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
747 (((regebc & 0x03FF0000)>>16) != 0x42))
752 if (!(regeac & BIT(30)) &&
753 (((regec4 & 0x03FF0000)>>16) != 0x132) &&
754 (((regecc & 0x03FF0000)>>16) != 0x36))
757 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
758 ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n"));
762 static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
763 u8 final_candidate, bool txonly)
765 u32 oldval_0, x, tx0_a, reg;
768 if (final_candidate == 0xFF) {
771 oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
773 x = result[final_candidate][0];
774 if ((x & 0x00000200) != 0)
777 tx0_a = (x * oldval_0) >> 8;
778 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
779 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
780 ((x * oldval_0>>7) & 0x1));
782 y = result[final_candidate][1];
783 if ((y & 0x00000200) != 0)
786 tx0_c = (y * oldval_0) >> 8;
787 phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
789 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
791 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
792 ((y * oldval_0>>7) & 0x1));
797 reg = result[final_candidate][2];
798 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
800 reg = result[final_candidate][3] & 0x3F;
801 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
803 reg = (result[final_candidate][3] >> 6) & 0xF;
804 phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
808 static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
809 u8 final_candidate, bool txonly)
811 u32 oldval_1, x, tx1_a, reg;
814 if (final_candidate == 0xFF) {
817 oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
819 x = result[final_candidate][4];
820 if ((x & 0x00000200) != 0)
822 tx1_a = (x * oldval_1) >> 8;
823 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
825 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
826 ((x * oldval_1>>7) & 0x1));
828 y = result[final_candidate][5];
829 if ((y & 0x00000200) != 0)
832 tx1_c = (y * oldval_1) >> 8;
834 phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
836 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
838 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
839 ((y * oldval_1>>7) & 0x1));
844 reg = result[final_candidate][6];
845 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
847 reg = result[final_candidate][7] & 0x3F;
848 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
850 reg = (result[final_candidate][7] >> 6) & 0xF;
851 phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
855 static void save_adda_registers(struct adapter *adapt, u32 *addareg,
856 u32 *backup, u32 register_num)
860 for (i = 0; i < register_num; i++) {
861 backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
865 static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
870 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
871 backup[i] = usb_read8(adapt, mac_reg[i]);
873 backup[i] = usb_read32(adapt, mac_reg[i]);
876 static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
877 u32 *backup, u32 regiester_num)
881 for (i = 0; i < regiester_num; i++)
882 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
885 static void reload_mac_registers(struct adapter *adapt,
886 u32 *mac_reg, u32 *backup)
890 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
891 usb_write8(adapt, mac_reg[i], (u8)backup[i]);
893 usb_write32(adapt, mac_reg[i], backup[i]);
896 static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
897 bool is_path_a_on, bool is2t)
903 path_on = 0x0bdb25a0;
904 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
906 path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
907 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
910 for (i = 1; i < IQK_ADDA_REG_NUM; i++)
911 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
914 static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
918 usb_write8(adapt, mac_reg[i], 0x3F);
920 for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
921 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
923 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
926 static void path_a_standby(struct adapter *adapt)
929 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
930 phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
931 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
934 static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
938 mode = pi_mode ? 0x01000100 : 0x01000000;
939 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
940 phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
943 static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
946 u32 i, j, diff, sim_bitmap = 0, bound;
947 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
949 s32 tmp1 = 0, tmp2 = 0;
953 for (i = 0; i < bound; i++) {
954 if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
955 if ((resulta[c1][i] & 0x00000200) != 0)
956 tmp1 = resulta[c1][i] | 0xFFFFFC00;
958 tmp1 = resulta[c1][i];
960 if ((resulta[c2][i] & 0x00000200) != 0)
961 tmp2 = resulta[c2][i] | 0xFFFFFC00;
963 tmp2 = resulta[c2][i];
965 tmp1 = resulta[c1][i];
966 tmp2 = resulta[c2][i];
969 diff = abs(tmp1 - tmp2);
971 if (diff > MAX_TOLERANCE) {
972 if ((i == 2 || i == 6) && !sim_bitmap) {
973 if (resulta[c1][i] + resulta[c1][i+1] == 0)
974 final_candidate[(i/4)] = c2;
975 else if (resulta[c2][i] + resulta[c2][i+1] == 0)
976 final_candidate[(i/4)] = c1;
978 sim_bitmap = sim_bitmap | (1<<i);
980 sim_bitmap = sim_bitmap | (1<<i);
985 if (sim_bitmap == 0) {
986 for (i = 0; i < (bound/4); i++) {
987 if (final_candidate[i] != 0xFF) {
988 for (j = i*4; j < (i+1)*4-2; j++)
989 resulta[3][j] = resulta[final_candidate[i]][j];
995 if (!(sim_bitmap & 0x03)) { /* path A TX OK */
996 for (i = 0; i < 2; i++)
997 resulta[3][i] = resulta[c1][i];
999 if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
1000 for (i = 2; i < 4; i++)
1001 resulta[3][i] = resulta[c1][i];
1004 if (!(sim_bitmap & 0x30)) { /* path B TX OK */
1005 for (i = 4; i < 6; i++)
1006 resulta[3][i] = resulta[c1][i];
1009 if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
1010 for (i = 6; i < 8; i++)
1011 resulta[3][i] = resulta[c1][i];
1017 static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
1020 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1022 u8 path_a_ok, path_b_ok;
1023 u32 adda_reg[IQK_ADDA_REG_NUM] = {
1024 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
1025 rRx_Wait_CCA, rTx_CCK_RFON,
1026 rTx_CCK_BBON, rTx_OFDM_RFON,
1027 rTx_OFDM_BBON, rTx_To_Rx,
1029 rRx_OFDM, rRx_Wait_RIFS,
1030 rRx_TO_Rx, rStandby,
1031 rSleep, rPMPD_ANAEN};
1033 u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
1034 REG_TXPAUSE, REG_BCN_CTRL,
1035 REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
1037 /* since 92C & 92D have the different define in IQK_BB_REG */
1038 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1039 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
1040 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
1041 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
1042 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
1044 u32 retry_count = 9;
1045 if (*(dm_odm->mp_mode) == 1)
1052 /* Save ADDA parameters, turn Path A ADDA on */
1053 save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1055 save_mac_registers(adapt, iqk_mac_reg,
1056 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1057 save_adda_registers(adapt, iqk_bb_reg_92c,
1058 dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1061 path_adda_on(adapt, adda_reg, true, is2t);
1063 dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1066 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1067 /* Switch BB to PI mode to do IQ Calibration. */
1068 pi_mode_switch(adapt, true);
1072 phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
1073 phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1074 phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1075 phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1077 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
1078 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
1079 phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
1080 phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
1083 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1085 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1090 mac_setting_calibration(adapt, iqk_mac_reg,
1091 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1095 phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1098 phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1100 /* IQ calibration setting */
1101 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1102 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1103 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1105 for (i = 0; i < retry_count; i++) {
1106 path_a_ok = phy_path_a_iqk(adapt, is2t);
1107 if (path_a_ok == 0x01) {
1108 result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1109 bMaskDWord)&0x3FF0000)>>16;
1110 result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1111 bMaskDWord)&0x3FF0000)>>16;
1116 for (i = 0; i < retry_count; i++) {
1117 path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1118 if (path_a_ok == 0x03) {
1119 result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1120 bMaskDWord)&0x3FF0000)>>16;
1121 result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1122 bMaskDWord)&0x3FF0000)>>16;
1125 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1126 ("Path A Rx IQK Fail!!\n"));
1130 if (0x00 == path_a_ok) {
1131 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1132 ("Path A IQK failed!!\n"));
1136 path_a_standby(adapt);
1138 /* Turn Path B ADDA on */
1139 path_adda_on(adapt, adda_reg, false, is2t);
1141 for (i = 0; i < retry_count; i++) {
1142 path_b_ok = phy_path_b_iqk(adapt);
1143 if (path_b_ok == 0x03) {
1144 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1145 bMaskDWord)&0x3FF0000)>>16;
1146 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1147 bMaskDWord)&0x3FF0000)>>16;
1148 result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1149 bMaskDWord)&0x3FF0000)>>16;
1150 result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1151 bMaskDWord)&0x3FF0000)>>16;
1153 } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
1154 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1155 bMaskDWord)&0x3FF0000)>>16;
1156 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1157 bMaskDWord)&0x3FF0000)>>16;
1161 if (0x00 == path_b_ok) {
1162 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1163 ("Path B IQK failed!!\n"));
1167 /* Back to BB mode, load original value */
1168 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1171 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1172 /* Switch back BB to SI mode after
1173 * finish IQ Calibration.
1175 pi_mode_switch(adapt, false);
1178 /* Reload ADDA power saving parameters */
1179 reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1182 /* Reload MAC parameters */
1183 reload_mac_registers(adapt, iqk_mac_reg,
1184 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1186 reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1189 /* Restore RX initial gain */
1190 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1191 bMaskDWord, 0x00032ed3);
1193 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1194 bMaskDWord, 0x00032ed3);
1196 /* load 0xe30 IQC default value */
1197 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1198 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1202 static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1205 u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1207 /* Check continuous TX and Packet TX */
1208 tmpreg = usb_read8(adapt, 0xd03);
1210 if ((tmpreg&0x70) != 0)
1211 usb_write8(adapt, 0xd03, tmpreg&0x8F);
1213 usb_write8(adapt, REG_TXPAUSE, 0xFF);
1215 if ((tmpreg&0x70) != 0) {
1216 /* 1. Read original RF mode */
1218 rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC,
1223 rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC,
1226 /* 2. Set RF mode = standby mode */
1228 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1229 (rf_a_mode&0x8FFFF)|0x10000);
1233 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1234 (rf_b_mode&0x8FFFF)|0x10000);
1237 /* 3. Read RF reg18 */
1238 lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1240 /* 4. Set LC calibration begin bit15 */
1241 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1246 /* Restore original situation */
1247 if ((tmpreg&0x70) != 0) {
1248 /* Deal with continuous TX case */
1250 usb_write8(adapt, 0xd03, tmpreg);
1251 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1255 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1258 /* Deal with Packet TX case */
1259 usb_write8(adapt, REG_TXPAUSE, 0x00);
1263 void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1265 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1267 u8 i, final, chn_index;
1268 bool pathaok, pathbok;
1269 s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
1270 bool is12simular, is13simular, is23simular;
1271 bool singletone = false, carrier_sup = false;
1272 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1273 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1274 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1275 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1276 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1277 rOFDM0_RxIQExtAnta};
1282 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1285 if (singletone || carrier_sup)
1289 ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1290 ("phy_iq_calibrate: Return due to recovery!\n"));
1291 reload_adda_reg(adapt, iqk_bb_reg_92c,
1292 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1296 for (i = 0; i < 8; i++) {
1300 if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
1301 result[3][i] = 0x100;
1308 is12simular = false;
1309 is23simular = false;
1310 is13simular = false;
1312 for (i = 0; i < 3; i++) {
1313 phy_iq_calibrate(adapt, result, i, is2t);
1316 is12simular = simularity_compare(adapt, result, 0, 1);
1324 is13simular = simularity_compare(adapt, result, 0, 2);
1329 is23simular = simularity_compare(adapt, result, 1, 2);
1337 for (i = 0; i < 4; i++) {
1338 reg_e94 = result[i][0];
1339 reg_e9c = result[i][1];
1340 reg_ea4 = result[i][2];
1341 reg_eb4 = result[i][4];
1342 reg_ebc = result[i][5];
1343 reg_ec4 = result[i][6];
1346 if (final != 0xff) {
1347 reg_e94 = result[final][0];
1348 reg_e9c = result[final][1];
1349 reg_ea4 = result[final][2];
1350 reg_eb4 = result[final][4];
1351 reg_ebc = result[final][5];
1352 dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1353 dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1354 dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1355 dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1356 reg_ec4 = result[final][6];
1360 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1361 ("IQK: FAIL use default value\n"));
1362 dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1363 dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1364 dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1365 dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1368 patha_fill_iqk(adapt, pathaok, result, final,
1372 pathb_fill_iqk(adapt, pathbok, result, final,
1376 chn_index = get_right_chnl_for_iqk(adapt->HalData->CurrentChannel);
1379 for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1380 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1381 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1384 save_adda_registers(adapt, iqk_bb_reg_92c,
1385 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1388 void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1390 bool singletone = false, carrier_sup = false;
1391 u32 timeout = 2000, timecount = 0;
1392 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1394 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1396 if (singletone || carrier_sup)
1399 while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1404 dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1406 phy_lc_calibrate(adapt, false);
1408 dm_odm->RFCalibrateInfo.bLCKInProgress = false;