1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
6 ******************************************************************************/
7 #define _RTL8188E_PHYCFG_C_
9 #include <osdep_service.h>
10 #include <drv_types.h>
11 #include <rtl8188e_hal.h>
15 #define MAX_PRECMD_CNT 16
16 #define MAX_RFDEPENDCMD_CNT 16
17 #define MAX_POSTCMD_CNT 16
19 #define MAX_DOZE_WAITING_TIMES_9x 64
21 static u32 cal_bit_shift(u32 bitmask)
25 for (i = 0; i <= 31; i++) {
26 if (((bitmask >> i) & 0x1) == 1)
32 u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
34 u32 original_value, bit_shift;
36 original_value = usb_read32(adapt, regaddr);
37 bit_shift = cal_bit_shift(bitmask);
38 return (original_value & bitmask) >> bit_shift;
41 void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
43 u32 original_value, bit_shift;
45 if (bitmask != bMaskDWord) { /* if not "double word" write */
46 original_value = usb_read32(adapt, regaddr);
47 bit_shift = cal_bit_shift(bitmask);
48 data = (original_value & (~bitmask)) | (data << bit_shift);
51 usb_write32(adapt, regaddr, data);
54 static u32 rf_serial_read(struct adapter *adapt,
55 enum rf_radio_path rfpath, u32 offset)
58 struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
59 u32 tmplong, tmplong2;
64 tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
65 if (rfpath == RF_PATH_A)
68 tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
71 tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
72 (offset<<23) | bLSSIReadEdge;
74 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
75 tmplong&(~bLSSIReadEdge));
78 phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
83 if (rfpath == RF_PATH_A)
84 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
85 else if (rfpath == RF_PATH_B)
86 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
89 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
92 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
97 static void rf_serial_write(struct adapter *adapt,
98 enum rf_radio_path rfpath, u32 offset,
101 u32 data_and_addr = 0;
102 struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
105 data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
106 phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
109 u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
110 u32 reg_addr, u32 bit_mask)
112 u32 original_value, bit_shift;
114 original_value = rf_serial_read(adapt, rf_path, reg_addr);
115 bit_shift = cal_bit_shift(bit_mask);
116 return (original_value & bit_mask) >> bit_shift;
119 void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
120 u32 reg_addr, u32 bit_mask, u32 data)
122 u32 original_value, bit_shift;
124 /* RF data is 12 bits only */
125 if (bit_mask != bRFRegOffsetMask) {
126 original_value = rf_serial_read(adapt, rf_path, reg_addr);
127 bit_shift = cal_bit_shift(bit_mask);
128 data = (original_value & (~bit_mask)) | (data << bit_shift);
131 rf_serial_write(adapt, rf_path, reg_addr, data);
134 static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
135 u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
137 struct hal_data_8188e *hal_data = adapt->HalData;
138 u8 index = (channel - 1);
139 u8 TxCount = 0, path_nums;
143 for (TxCount = 0; TxCount < path_nums; TxCount++) {
144 if (TxCount == RF_PATH_A) {
145 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
146 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
147 hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
149 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
150 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
151 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
152 } else if (TxCount == RF_PATH_B) {
153 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
154 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
155 hal_data->BW20_24G_Diff[RF_PATH_A][index]+
156 hal_data->BW20_24G_Diff[TxCount][index];
158 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
159 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
160 hal_data->BW20_24G_Diff[TxCount][index];
161 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
166 static void phy_power_index_check(struct adapter *adapt, u8 channel,
167 u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
170 struct hal_data_8188e *hal_data = adapt->HalData;
172 hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
173 hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
174 hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
175 hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
178 void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
180 u8 cck_pwr[MAX_TX_COUNT] = {0};
181 u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
182 u8 bw20_pwr[MAX_TX_COUNT] = {0};
183 u8 bw40_pwr[MAX_TX_COUNT] = {0};
185 get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
186 &bw20_pwr[0], &bw40_pwr[0]);
188 phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
189 &bw20_pwr[0], &bw40_pwr[0]);
191 rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
192 rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
193 &bw40_pwr[0], channel);
196 static void phy_set_bw_mode_callback(struct adapter *adapt)
198 struct hal_data_8188e *hal_data = adapt->HalData;
202 if (adapt->bDriverStopped)
205 /* Set MAC register */
207 reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
208 reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
210 switch (hal_data->CurrentChannelBW) {
211 case HT_CHANNEL_WIDTH_20:
212 reg_bw_opmode |= BW_OPMODE_20MHZ;
213 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
215 case HT_CHANNEL_WIDTH_40:
216 reg_bw_opmode &= ~BW_OPMODE_20MHZ;
217 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
218 reg_prsr_rsc = (reg_prsr_rsc&0x90) |
219 (hal_data->nCur40MhzPrimeSC<<5);
220 usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
226 /* Set PHY related register */
227 switch (hal_data->CurrentChannelBW) {
228 case HT_CHANNEL_WIDTH_20:
229 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
230 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
232 case HT_CHANNEL_WIDTH_40:
233 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
234 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
235 /* Set Control channel to upper or lower.
236 * These settings are required only for 40MHz
238 phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
239 (hal_data->nCur40MhzPrimeSC>>1));
240 phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
241 hal_data->nCur40MhzPrimeSC);
242 phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
243 (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
249 /* Set RF related register */
250 rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
253 void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth,
254 unsigned char offset)
256 struct hal_data_8188e *hal_data = adapt->HalData;
257 enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
259 hal_data->CurrentChannelBW = bandwidth;
260 hal_data->nCur40MhzPrimeSC = offset;
262 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
263 phy_set_bw_mode_callback(adapt);
265 hal_data->CurrentChannelBW = tmp_bw;
268 static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
271 struct hal_data_8188e *hal_data = adapt->HalData;
273 phy_set_tx_power_level(adapt, channel);
277 hal_data->RfRegChnlVal[0] = (hal_data->RfRegChnlVal[0] &
278 0xfffffc00) | param2;
279 phy_set_rf_reg(adapt, 0, param1,
280 bRFRegOffsetMask, hal_data->RfRegChnlVal[0]);
283 void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
285 struct hal_data_8188e *hal_data = adapt->HalData;
286 u8 tmpchannel = hal_data->CurrentChannel;
291 hal_data->CurrentChannel = channel;
293 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
294 phy_sw_chnl_callback(adapt, channel);
296 hal_data->CurrentChannel = tmpchannel;
299 #define ODM_TXPWRTRACK_MAX_IDX_88E 6
301 static u8 get_right_chnl_for_iqk(u8 chnl)
304 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
305 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
306 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
307 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
308 155, 157, 159, 161, 163, 165
312 for (place = 0; place < sizeof(channel_all); place++) {
313 if (channel_all[place] == chnl)
320 void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
321 u8 *direction, u32 *out_write_val)
324 /* Tx power tracking BB swing table. */
325 if (type == 0) { /* For OFDM adjust */
326 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
327 ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
328 dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
330 if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
332 pwr_value = dm_odm->BbSwingIdxOfdmBase -
333 dm_odm->BbSwingIdxOfdm;
336 pwr_value = dm_odm->BbSwingIdxOfdm -
337 dm_odm->BbSwingIdxOfdmBase;
340 } else if (type == 1) { /* For CCK adjust. */
341 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
342 ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
343 dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
345 if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
347 pwr_value = dm_odm->BbSwingIdxCckBase -
348 dm_odm->BbSwingIdxCck;
351 pwr_value = dm_odm->BbSwingIdxCck -
352 dm_odm->BbSwingIdxCckBase;
356 if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
357 pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
359 *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
363 static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
365 if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
366 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
367 ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
368 phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
369 dm_odm->BbSwingFlagOfdm = false;
370 dm_odm->BbSwingFlagCck = false;
374 void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
376 struct hal_data_8188e *hal_data = adapt->HalData;
377 u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
378 u8 thermal_avg_count = 0;
381 s8 ofdm_index[2], cck_index = 0;
382 s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
385 u8 ofdm_min_index = 6; /* OFDM BB Swing should be less than +3.0dB */
386 s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
387 /* 2.4G, decrease power */
388 {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
389 /* 2.4G, increase power */
390 {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
392 u8 thermal_mapping[2][index_mapping_NUM_88E] = {
393 /* 2.4G, decrease power */
394 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
395 /* 2.4G, increase power */
396 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
398 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
400 dm_txpwr_track_setpwr(dm_odm);
402 dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
404 dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
406 thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A,
407 RF_T_METER_88E, 0xfc00);
410 /* Query OFDM path A default setting */
411 ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
412 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
413 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
414 ofdm_index_old[0] = (u8)i;
415 dm_odm->BbSwingIdxOfdmBase = (u8)i;
420 /* Query CCK default setting From 0xa24 */
421 temp_cck = dm_odm->RFCalibrateInfo.RegA24;
423 for (i = 0; i < CCK_TABLE_SIZE; i++) {
424 if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
425 memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
426 memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
427 cck_index_old = (u8)i;
428 dm_odm->BbSwingIdxCckBase = (u8)i;
433 if (!dm_odm->RFCalibrateInfo.ThermalValue) {
434 dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
435 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
436 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
438 dm_odm->RFCalibrateInfo.OFDM_index[0] = ofdm_index_old[0];
439 dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
442 /* calculate average thermal meter */
443 dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
444 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
445 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
446 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
448 for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
449 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
450 thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
455 if (thermal_avg_count)
456 thermal_val = (u8)(thermal_avg / thermal_avg_count);
458 if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
459 !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
460 delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
462 delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
463 if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
464 dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
465 dm_odm->RFCalibrateInfo.bDoneTxpower = false;
469 delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
470 delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
472 /* Delta temperature is equal to or larger than 20 centigrade.*/
473 if ((delta_lck >= 8)) {
474 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
475 rtl88eu_phy_lc_calibrate(adapt);
478 if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
479 delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
481 /* calculate new OFDM / CCK offset */
482 if (thermal_val > hal_data->EEPROMThermalMeter)
486 for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
487 if (delta < thermal_mapping[j][offset]) {
493 if (offset >= index_mapping_NUM_88E)
494 offset = index_mapping_NUM_88E-1;
496 /* Updating ofdm_index values with new OFDM / CCK offset */
497 ofdm_index[0] = dm_odm->RFCalibrateInfo.OFDM_index[0] + ofdm_index_mapping[j][offset];
498 if (ofdm_index[0] > OFDM_TABLE_SIZE_92D-1)
499 ofdm_index[0] = OFDM_TABLE_SIZE_92D-1;
500 else if (ofdm_index[0] < ofdm_min_index)
501 ofdm_index[0] = ofdm_min_index;
503 cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
504 if (cck_index > CCK_TABLE_SIZE-1)
505 cck_index = CCK_TABLE_SIZE-1;
506 else if (cck_index < 0)
509 /* 2 temporarily remove bNOPG */
510 /* Config by SwingTable */
511 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
512 dm_odm->RFCalibrateInfo.bDoneTxpower = true;
514 /* Revse TX power table. */
515 dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
516 dm_odm->BbSwingIdxCck = (u8)cck_index;
518 if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
519 dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
520 dm_odm->BbSwingFlagOfdm = true;
523 if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
524 dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
525 dm_odm->BbSwingFlagCck = true;
530 /* Delta temperature is equal to or larger than 20 centigrade.*/
531 if (delta_iqk >= 8) {
532 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
533 rtl88eu_phy_iq_calibrate(adapt, false);
535 /* update thermal meter value */
536 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
537 dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
539 dm_odm->RFCalibrateInfo.TXPowercount = 0;
542 #define MAX_TOLERANCE 5
544 static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
546 u32 reg_eac, reg_e94, reg_e9c;
550 /* path-A IQK setting */
551 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
552 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
553 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
554 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
556 /* LO calibration setting */
557 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
559 /* One shot, path A LOK & IQK */
560 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
561 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
563 mdelay(IQK_DELAY_TIME_88E);
565 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
566 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
567 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
569 if (!(reg_eac & BIT(28)) &&
570 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
571 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
576 static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
578 u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
580 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
582 /* 1 Get TXIMR setting */
583 /* modify RXIQK mode table */
584 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
585 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
586 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
587 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
588 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
591 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
592 phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
594 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
597 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
598 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
600 /* path-A IQK setting */
601 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
602 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
603 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
604 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
606 /* LO calibration setting */
607 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
609 /* One shot, path A LOK & IQK */
610 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
611 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
614 mdelay(IQK_DELAY_TIME_88E);
617 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
618 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
619 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
621 if (!(reg_eac & BIT(28)) &&
622 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
623 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
625 else /* if Tx not OK, ignore Rx */
628 u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16);
629 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
632 /* modify RXIQK mode table */
633 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
634 ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
635 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
636 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
637 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
638 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
639 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
640 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
643 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
645 /* path-A IQK setting */
646 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
647 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
648 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
649 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
651 /* LO calibration setting */
652 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
654 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
655 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
657 mdelay(IQK_DELAY_TIME_88E);
660 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
661 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
662 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
663 reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
666 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
667 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
669 if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
670 (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
671 (((reg_eac & 0x03FF0000)>>16) != 0x36))
674 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
675 ("Path A Rx IQK fail!!\n"));
680 static u8 phy_path_b_iqk(struct adapter *adapt)
682 u32 regeac, regeb4, regebc, regec4, regecc;
684 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
686 /* One shot, path B LOK & IQK */
687 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
688 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
690 mdelay(IQK_DELAY_TIME_88E);
692 regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
693 regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
694 regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
695 regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
696 regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
698 if (!(regeac & BIT(31)) &&
699 (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
700 (((regebc & 0x03FF0000)>>16) != 0x42))
705 if (!(regeac & BIT(30)) &&
706 (((regec4 & 0x03FF0000)>>16) != 0x132) &&
707 (((regecc & 0x03FF0000)>>16) != 0x36))
710 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
711 ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n"));
715 static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
716 u8 final_candidate, bool txonly)
718 u32 oldval_0, x, tx0_a, reg;
721 if (final_candidate == 0xFF) {
724 oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
726 x = result[final_candidate][0];
727 if ((x & 0x00000200) != 0)
730 tx0_a = (x * oldval_0) >> 8;
731 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
732 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
733 ((x * oldval_0>>7) & 0x1));
735 y = result[final_candidate][1];
736 if ((y & 0x00000200) != 0)
739 tx0_c = (y * oldval_0) >> 8;
740 phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
742 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
744 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
745 ((y * oldval_0>>7) & 0x1));
750 reg = result[final_candidate][2];
751 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
753 reg = result[final_candidate][3] & 0x3F;
754 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
756 reg = (result[final_candidate][3] >> 6) & 0xF;
757 phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
761 static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
762 u8 final_candidate, bool txonly)
764 u32 oldval_1, x, tx1_a, reg;
767 if (final_candidate == 0xFF) {
770 oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
772 x = result[final_candidate][4];
773 if ((x & 0x00000200) != 0)
775 tx1_a = (x * oldval_1) >> 8;
776 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
778 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
779 ((x * oldval_1>>7) & 0x1));
781 y = result[final_candidate][5];
782 if ((y & 0x00000200) != 0)
785 tx1_c = (y * oldval_1) >> 8;
787 phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
789 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
791 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
792 ((y * oldval_1>>7) & 0x1));
797 reg = result[final_candidate][6];
798 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
800 reg = result[final_candidate][7] & 0x3F;
801 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
803 reg = (result[final_candidate][7] >> 6) & 0xF;
804 phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
808 static void save_adda_registers(struct adapter *adapt, u32 *addareg,
809 u32 *backup, u32 register_num)
813 for (i = 0; i < register_num; i++)
814 backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
817 static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
822 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
823 backup[i] = usb_read8(adapt, mac_reg[i]);
825 backup[i] = usb_read32(adapt, mac_reg[i]);
828 static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
829 u32 *backup, u32 regiester_num)
833 for (i = 0; i < regiester_num; i++)
834 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
837 static void reload_mac_registers(struct adapter *adapt,
838 u32 *mac_reg, u32 *backup)
842 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
843 usb_write8(adapt, mac_reg[i], (u8)backup[i]);
845 usb_write32(adapt, mac_reg[i], backup[i]);
848 static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
849 bool is_path_a_on, bool is2t)
855 path_on = 0x0bdb25a0;
856 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
858 path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
859 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
862 for (i = 1; i < IQK_ADDA_REG_NUM; i++)
863 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
866 static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
870 usb_write8(adapt, mac_reg[i], 0x3F);
872 for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
873 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
875 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
878 static void path_a_standby(struct adapter *adapt)
880 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
881 phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
882 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
885 static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
889 mode = pi_mode ? 0x01000100 : 0x01000000;
890 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
891 phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
894 static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
897 u32 i, j, diff, sim_bitmap = 0, bound;
898 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
900 s32 tmp1 = 0, tmp2 = 0;
904 for (i = 0; i < bound; i++) {
905 if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
906 if ((resulta[c1][i] & 0x00000200) != 0)
907 tmp1 = resulta[c1][i] | 0xFFFFFC00;
909 tmp1 = resulta[c1][i];
911 if ((resulta[c2][i] & 0x00000200) != 0)
912 tmp2 = resulta[c2][i] | 0xFFFFFC00;
914 tmp2 = resulta[c2][i];
916 tmp1 = resulta[c1][i];
917 tmp2 = resulta[c2][i];
920 diff = abs(tmp1 - tmp2);
922 if (diff > MAX_TOLERANCE) {
923 if ((i == 2 || i == 6) && !sim_bitmap) {
924 if (resulta[c1][i] + resulta[c1][i+1] == 0)
925 final_candidate[(i/4)] = c2;
926 else if (resulta[c2][i] + resulta[c2][i+1] == 0)
927 final_candidate[(i/4)] = c1;
929 sim_bitmap = sim_bitmap | (1<<i);
931 sim_bitmap = sim_bitmap | (1<<i);
936 if (sim_bitmap == 0) {
937 for (i = 0; i < (bound/4); i++) {
938 if (final_candidate[i] != 0xFF) {
939 for (j = i*4; j < (i+1)*4-2; j++)
940 resulta[3][j] = resulta[final_candidate[i]][j];
946 if (!(sim_bitmap & 0x03)) { /* path A TX OK */
947 for (i = 0; i < 2; i++)
948 resulta[3][i] = resulta[c1][i];
950 if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
951 for (i = 2; i < 4; i++)
952 resulta[3][i] = resulta[c1][i];
955 if (!(sim_bitmap & 0x30)) { /* path B TX OK */
956 for (i = 4; i < 6; i++)
957 resulta[3][i] = resulta[c1][i];
960 if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
961 for (i = 6; i < 8; i++)
962 resulta[3][i] = resulta[c1][i];
968 static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
971 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
973 u8 path_a_ok, path_b_ok;
974 u32 adda_reg[IQK_ADDA_REG_NUM] = {
975 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
976 rRx_Wait_CCA, rTx_CCK_RFON,
977 rTx_CCK_BBON, rTx_OFDM_RFON,
978 rTx_OFDM_BBON, rTx_To_Rx,
980 rRx_OFDM, rRx_Wait_RIFS,
982 rSleep, rPMPD_ANAEN};
984 u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
985 REG_TXPAUSE, REG_BCN_CTRL,
986 REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
988 /* since 92C & 92D have the different define in IQK_BB_REG */
989 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
990 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
991 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
992 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
993 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
997 if (*(dm_odm->mp_mode) == 1)
1003 /* Save ADDA parameters, turn Path A ADDA on */
1004 save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1006 save_mac_registers(adapt, iqk_mac_reg,
1007 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1008 save_adda_registers(adapt, iqk_bb_reg_92c,
1009 dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1012 path_adda_on(adapt, adda_reg, true, is2t);
1014 dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1017 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1018 /* Switch BB to PI mode to do IQ Calibration. */
1019 pi_mode_switch(adapt, true);
1023 phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
1024 phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1025 phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1026 phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1028 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
1029 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
1030 phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
1031 phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
1034 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1036 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1041 mac_setting_calibration(adapt, iqk_mac_reg,
1042 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1046 phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1049 phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1051 /* IQ calibration setting */
1052 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1053 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1054 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1056 for (i = 0; i < retry_count; i++) {
1057 path_a_ok = phy_path_a_iqk(adapt, is2t);
1058 if (path_a_ok == 0x01) {
1059 result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1060 bMaskDWord)&0x3FF0000)>>16;
1061 result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1062 bMaskDWord)&0x3FF0000)>>16;
1067 for (i = 0; i < retry_count; i++) {
1068 path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1069 if (path_a_ok == 0x03) {
1070 result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1071 bMaskDWord)&0x3FF0000)>>16;
1072 result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1073 bMaskDWord)&0x3FF0000)>>16;
1076 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1077 ("Path A Rx IQK Fail!!\n"));
1081 if (path_a_ok == 0x00) {
1082 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1083 ("Path A IQK failed!!\n"));
1087 path_a_standby(adapt);
1089 /* Turn Path B ADDA on */
1090 path_adda_on(adapt, adda_reg, false, is2t);
1092 for (i = 0; i < retry_count; i++) {
1093 path_b_ok = phy_path_b_iqk(adapt);
1094 if (path_b_ok == 0x03) {
1095 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1096 bMaskDWord)&0x3FF0000)>>16;
1097 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1098 bMaskDWord)&0x3FF0000)>>16;
1099 result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1100 bMaskDWord)&0x3FF0000)>>16;
1101 result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1102 bMaskDWord)&0x3FF0000)>>16;
1104 } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
1105 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1106 bMaskDWord)&0x3FF0000)>>16;
1107 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1108 bMaskDWord)&0x3FF0000)>>16;
1112 if (path_b_ok == 0x00) {
1113 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1114 ("Path B IQK failed!!\n"));
1118 /* Back to BB mode, load original value */
1119 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1122 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1123 /* Switch back BB to SI mode after
1124 * finish IQ Calibration.
1126 pi_mode_switch(adapt, false);
1129 /* Reload ADDA power saving parameters */
1130 reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1133 /* Reload MAC parameters */
1134 reload_mac_registers(adapt, iqk_mac_reg,
1135 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1137 reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1140 /* Restore RX initial gain */
1141 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1142 bMaskDWord, 0x00032ed3);
1144 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1145 bMaskDWord, 0x00032ed3);
1147 /* load 0xe30 IQC default value */
1148 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1149 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1153 static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1156 u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1158 /* Check continuous TX and Packet TX */
1159 tmpreg = usb_read8(adapt, 0xd03);
1161 if ((tmpreg&0x70) != 0)
1162 usb_write8(adapt, 0xd03, tmpreg&0x8F);
1164 usb_write8(adapt, REG_TXPAUSE, 0xFF);
1166 if ((tmpreg&0x70) != 0) {
1167 /* 1. Read original RF mode */
1169 rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC,
1174 rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC,
1177 /* 2. Set RF mode = standby mode */
1179 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1180 (rf_a_mode&0x8FFFF)|0x10000);
1184 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1185 (rf_b_mode&0x8FFFF)|0x10000);
1188 /* 3. Read RF reg18 */
1189 lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1191 /* 4. Set LC calibration begin bit15 */
1192 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1197 /* Restore original situation */
1198 if ((tmpreg&0x70) != 0) {
1199 /* Deal with continuous TX case */
1201 usb_write8(adapt, 0xd03, tmpreg);
1202 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1206 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1209 /* Deal with Packet TX case */
1210 usb_write8(adapt, REG_TXPAUSE, 0x00);
1214 void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1216 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1218 u8 i, final, chn_index;
1219 bool pathaok, pathbok;
1220 s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
1221 bool is12simular, is13simular, is23simular;
1222 bool singletone = false, carrier_sup = false;
1223 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1224 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1225 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1226 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1227 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1228 rOFDM0_RxIQExtAnta};
1233 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1236 if (singletone || carrier_sup)
1240 ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1241 ("phy_iq_calibrate: Return due to recovery!\n"));
1242 reload_adda_reg(adapt, iqk_bb_reg_92c,
1243 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1247 for (i = 0; i < 8; i++) {
1251 if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
1252 result[3][i] = 0x100;
1259 is12simular = false;
1260 is23simular = false;
1261 is13simular = false;
1263 for (i = 0; i < 3; i++) {
1264 phy_iq_calibrate(adapt, result, i, is2t);
1267 is12simular = simularity_compare(adapt, result, 0, 1);
1275 is13simular = simularity_compare(adapt, result, 0, 2);
1280 is23simular = simularity_compare(adapt, result, 1, 2);
1288 for (i = 0; i < 4; i++) {
1289 reg_e94 = result[i][0];
1290 reg_e9c = result[i][1];
1291 reg_ea4 = result[i][2];
1292 reg_eb4 = result[i][4];
1293 reg_ebc = result[i][5];
1294 reg_ec4 = result[i][6];
1297 if (final != 0xff) {
1298 reg_e94 = result[final][0];
1299 reg_e9c = result[final][1];
1300 reg_ea4 = result[final][2];
1301 reg_eb4 = result[final][4];
1302 reg_ebc = result[final][5];
1303 dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1304 dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1305 dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1306 dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1307 reg_ec4 = result[final][6];
1311 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1312 ("IQK: FAIL use default value\n"));
1313 dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1314 dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1315 dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1316 dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1319 patha_fill_iqk(adapt, pathaok, result, final,
1323 pathb_fill_iqk(adapt, pathbok, result, final,
1327 chn_index = get_right_chnl_for_iqk(adapt->HalData->CurrentChannel);
1330 for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1331 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1332 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1335 save_adda_registers(adapt, iqk_bb_reg_92c,
1336 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1339 void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1341 bool singletone = false, carrier_sup = false;
1342 u32 timeout = 2000, timecount = 0;
1343 struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1345 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1347 if (singletone || carrier_sup)
1350 while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1355 dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1357 phy_lc_calibrate(adapt, false);
1359 dm_odm->RFCalibrateInfo.bLCKInProgress = false;