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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTL8188E_PHYCFG_C_
22 #include <osdep_service.h>
23 #include <drv_types.h>
25 #include <rtl8188e_hal.h>
29 #define MAX_PRECMD_CNT 16
30 #define MAX_RFDEPENDCMD_CNT 16
31 #define MAX_POSTCMD_CNT 16
33 #define MAX_DOZE_WAITING_TIMES_9x 64
35 static u32 cal_bit_shift(u32 bitmask)
39 for (i = 0; i <= 31; i++) {
40 if (((bitmask >> i) & 0x1) == 1)
46 u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
48 u32 return_value = 0, original_value, bit_shift;
50 original_value = usb_read32(adapt, regaddr);
51 bit_shift = cal_bit_shift(bitmask);
52 return_value = (original_value & bitmask) >> bit_shift;
56 void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
58 u32 original_value, bit_shift;
60 if (bitmask != bMaskDWord) { /* if not "double word" write */
61 original_value = usb_read32(adapt, regaddr);
62 bit_shift = cal_bit_shift(bitmask);
63 data = (original_value & (~bitmask)) | (data << bit_shift);
66 usb_write32(adapt, regaddr, data);
69 static u32 rf_serial_read(struct adapter *adapt,
70 enum rf_radio_path rfpath, u32 offset)
73 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
74 struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
75 u32 tmplong, tmplong2;
80 tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
81 if (rfpath == RF_PATH_A)
84 tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
87 tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
88 (offset<<23) | bLSSIReadEdge;
90 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
91 tmplong&(~bLSSIReadEdge));
94 phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
99 if (rfpath == RF_PATH_A)
100 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
101 else if (rfpath == RF_PATH_B)
102 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
105 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
108 ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
113 static void rf_serial_write(struct adapter *adapt,
114 enum rf_radio_path rfpath, u32 offset,
117 u32 data_and_addr = 0;
118 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
119 struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
122 data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
123 phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
126 u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
127 u32 reg_addr, u32 bit_mask)
129 u32 original_value, readback_value, bit_shift;
131 original_value = rf_serial_read(adapt, rf_path, reg_addr);
132 bit_shift = cal_bit_shift(bit_mask);
133 readback_value = (original_value & bit_mask) >> bit_shift;
134 return readback_value;
137 void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
138 u32 reg_addr, u32 bit_mask, u32 data)
140 u32 original_value, bit_shift;
142 /* RF data is 12 bits only */
143 if (bit_mask != bRFRegOffsetMask) {
144 original_value = rf_serial_read(adapt, rf_path, reg_addr);
145 bit_shift = cal_bit_shift(bit_mask);
146 data = (original_value & (~bit_mask)) | (data << bit_shift);
149 rf_serial_write(adapt, rf_path, reg_addr, data);
152 static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
153 u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
155 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
156 u8 index = (channel - 1);
157 u8 TxCount = 0, path_nums;
159 if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type))
164 for (TxCount = 0; TxCount < path_nums; TxCount++) {
165 if (TxCount == RF_PATH_A) {
166 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
167 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
168 hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
170 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
171 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
172 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
173 } else if (TxCount == RF_PATH_B) {
174 cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
175 ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
176 hal_data->BW20_24G_Diff[RF_PATH_A][index]+
177 hal_data->BW20_24G_Diff[TxCount][index];
179 bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
180 hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
181 hal_data->BW20_24G_Diff[TxCount][index];
182 bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
187 static void phy_power_index_check(struct adapter *adapt, u8 channel,
188 u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
191 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
193 hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
194 hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
195 hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
196 hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
199 void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
201 u8 cck_pwr[MAX_TX_COUNT] = {0};
202 u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
203 u8 bw20_pwr[MAX_TX_COUNT] = {0};
204 u8 bw40_pwr[MAX_TX_COUNT] = {0};
206 get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
207 &bw20_pwr[0], &bw40_pwr[0]);
209 phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
210 &bw20_pwr[0], &bw40_pwr[0]);
212 rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
213 rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
214 &bw40_pwr[0], channel);
217 static void phy_set_bw_mode_callback(struct adapter *adapt)
219 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
223 if (hal_data->rf_chip == RF_PSEUDO_11N)
226 /* There is no 40MHz mode in RF_8225. */
227 if (hal_data->rf_chip == RF_8225)
230 if (adapt->bDriverStopped)
233 /* Set MAC register */
235 reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
236 reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
238 switch (hal_data->CurrentChannelBW) {
239 case HT_CHANNEL_WIDTH_20:
240 reg_bw_opmode |= BW_OPMODE_20MHZ;
241 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
243 case HT_CHANNEL_WIDTH_40:
244 reg_bw_opmode &= ~BW_OPMODE_20MHZ;
245 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
246 reg_prsr_rsc = (reg_prsr_rsc&0x90) |
247 (hal_data->nCur40MhzPrimeSC<<5);
248 usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
254 /* Set PHY related register */
255 switch (hal_data->CurrentChannelBW) {
256 case HT_CHANNEL_WIDTH_20:
257 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
258 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
260 case HT_CHANNEL_WIDTH_40:
261 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
262 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
263 /* Set Control channel to upper or lower.
264 * These settings are required only for 40MHz
266 phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
267 (hal_data->nCur40MhzPrimeSC>>1));
268 phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
269 hal_data->nCur40MhzPrimeSC);
270 phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
271 (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
277 /* Set RF related register */
278 if (hal_data->rf_chip == RF_6052)
279 rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
282 void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth,
283 unsigned char offset)
285 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
286 enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
288 hal_data->CurrentChannelBW = bandwidth;
289 hal_data->nCur40MhzPrimeSC = offset;
291 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
292 phy_set_bw_mode_callback(adapt);
294 hal_data->CurrentChannelBW = tmp_bw;
297 static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
301 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
303 if (adapt->bNotifyChannelChange)
304 DBG_88E("[%s] ch = %d\n", __func__, channel);
306 phy_set_tx_power_level(adapt, channel);
310 for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) {
311 hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] &
312 0xfffffc00) | param2;
313 phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1,
314 bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]);
318 void phy_sw_chnl(struct adapter *adapt, u8 channel)
320 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
321 u8 tmpchannel = hal_data->CurrentChannel;
323 if (hal_data->rf_chip == RF_PSEUDO_11N)
329 hal_data->CurrentChannel = channel;
331 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
332 phy_sw_chnl_callback(adapt, channel);
334 hal_data->CurrentChannel = tmpchannel;
337 #define ODM_TXPWRTRACK_MAX_IDX_88E 6
339 static u8 get_right_chnl_for_iqk(u8 chnl)
342 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
343 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
344 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
345 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
346 155, 157, 159, 161, 163, 165
350 for (place = 0; place < sizeof(channel_all); place++) {
351 if (channel_all[place] == chnl)
358 void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
359 u8 *direction, u32 *out_write_val)
362 /* Tx power tracking BB swing table. */
363 if (type == 0) { /* For OFDM adjust */
364 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
365 ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
366 dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
368 if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
370 pwr_value = dm_odm->BbSwingIdxOfdmBase -
371 dm_odm->BbSwingIdxOfdm;
374 pwr_value = dm_odm->BbSwingIdxOfdm -
375 dm_odm->BbSwingIdxOfdmBase;
378 } else if (type == 1) { /* For CCK adjust. */
379 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
380 ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
381 dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
383 if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
385 pwr_value = dm_odm->BbSwingIdxCckBase -
386 dm_odm->BbSwingIdxCck;
389 pwr_value = dm_odm->BbSwingIdxCck -
390 dm_odm->BbSwingIdxCckBase;
395 if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
396 pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
398 *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
402 static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
404 if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
405 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
406 ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
407 phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
408 dm_odm->BbSwingFlagOfdm = false;
409 dm_odm->BbSwingFlagCck = false;
413 void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
415 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
416 u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
417 u8 thermal_avg_count = 0;
420 s8 ofdm_index[2], cck_index = 0;
421 s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
425 u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */
426 s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
427 /* 2.4G, decrease power */
428 {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
429 /* 2.4G, increase power */
430 {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
432 u8 thermal_mapping[2][index_mapping_NUM_88E] = {
433 /* 2.4G, decrease power */
434 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
435 /* 2.4G, increase power */
436 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
438 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
440 dm_txpwr_track_setpwr(dm_odm);
442 dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
443 dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
445 dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
447 thermal_val = (u8)phy_query_rf_reg(adapt, RF_PATH_A,
448 RF_T_METER_88E, 0xfc00);
456 /* Query OFDM path A default setting */
457 ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
458 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
459 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
460 ofdm_index_old[0] = (u8)i;
461 dm_odm->BbSwingIdxOfdmBase = (u8)i;
466 /* Query OFDM path B default setting */
468 ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D;
469 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
470 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
471 ofdm_index_old[1] = (u8)i;
477 /* Query CCK default setting From 0xa24 */
478 temp_cck = dm_odm->RFCalibrateInfo.RegA24;
480 for (i = 0; i < CCK_TABLE_SIZE; i++) {
481 if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
482 memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
483 memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
484 cck_index_old = (u8)i;
485 dm_odm->BbSwingIdxCckBase = (u8)i;
490 if (!dm_odm->RFCalibrateInfo.ThermalValue) {
491 dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
492 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
493 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
495 for (i = 0; i < rf; i++)
496 dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i];
497 dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
500 /* calculate average thermal meter */
501 dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
502 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
503 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
504 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
506 for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
507 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
508 thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
513 if (thermal_avg_count)
514 thermal_val = (u8)(thermal_avg / thermal_avg_count);
516 if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
517 !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
518 delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
520 delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
521 if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
522 dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
523 dm_odm->RFCalibrateInfo.bDoneTxpower = false;
527 delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
528 delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
530 /* Delta temperature is equal to or larger than 20 centigrade.*/
531 if ((delta_lck >= 8)) {
532 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
533 rtl88eu_phy_lc_calibrate(adapt);
536 if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
537 delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
539 /* calculate new OFDM / CCK offset */
540 if (thermal_val > hal_data->EEPROMThermalMeter)
544 for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
545 if (delta < thermal_mapping[j][offset]) {
551 if (offset >= index_mapping_NUM_88E)
552 offset = index_mapping_NUM_88E-1;
554 /* Updating ofdm_index values with new OFDM / CCK offset */
555 for (i = 0; i < rf; i++) {
556 ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
557 if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1)
558 ofdm_index[i] = OFDM_TABLE_SIZE_92D-1;
559 else if (ofdm_index[i] < ofdm_min_index)
560 ofdm_index[i] = ofdm_min_index;
563 cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
564 if (cck_index > CCK_TABLE_SIZE-1)
565 cck_index = CCK_TABLE_SIZE-1;
566 else if (cck_index < 0)
569 /* 2 temporarily remove bNOPG */
570 /* Config by SwingTable */
571 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
572 dm_odm->RFCalibrateInfo.bDoneTxpower = true;
574 /* Revse TX power table. */
575 dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
576 dm_odm->BbSwingIdxCck = (u8)cck_index;
578 if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
579 dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
580 dm_odm->BbSwingFlagOfdm = true;
583 if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
584 dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
585 dm_odm->BbSwingFlagCck = true;
590 /* Delta temperature is equal to or larger than 20 centigrade.*/
591 if (delta_iqk >= 8) {
592 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
593 rtl88eu_phy_iq_calibrate(adapt, false);
595 /* update thermal meter value */
596 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
597 dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
599 dm_odm->RFCalibrateInfo.TXPowercount = 0;
602 #define MAX_TOLERANCE 5
604 static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
606 u32 reg_eac, reg_e94, reg_e9c;
610 /* path-A IQK setting */
611 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
612 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
613 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
614 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
616 /* LO calibration setting */
617 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
619 /* One shot, path A LOK & IQK */
620 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
621 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
623 mdelay(IQK_DELAY_TIME_88E);
625 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
626 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
627 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
629 if (!(reg_eac & BIT(28)) &&
630 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
631 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
636 static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
638 u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
640 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
641 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
643 /* 1 Get TXIMR setting */
644 /* modify RXIQK mode table */
645 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
646 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
647 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
648 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
649 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
652 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
653 phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
655 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
658 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
659 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
661 /* path-A IQK setting */
662 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
663 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
664 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
665 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
667 /* LO calibration setting */
668 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
670 /* One shot, path A LOK & IQK */
671 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
672 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
675 mdelay(IQK_DELAY_TIME_88E);
678 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
679 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
680 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
682 if (!(reg_eac & BIT(28)) &&
683 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
684 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
686 else /* if Tx not OK, ignore Rx */
689 u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16);
690 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
693 /* modify RXIQK mode table */
694 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
695 ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
696 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
697 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
698 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
699 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
700 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
701 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
704 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
706 /* path-A IQK setting */
707 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
708 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
709 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
710 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
712 /* LO calibration setting */
713 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
715 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
716 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
718 mdelay(IQK_DELAY_TIME_88E);
721 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
722 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
723 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
724 reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
727 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
728 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
730 if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
731 (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
732 (((reg_eac & 0x03FF0000)>>16) != 0x36))
735 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
736 ("Path A Rx IQK fail!!\n"));
741 static u8 phy_path_b_iqk(struct adapter *adapt)
743 u32 regeac, regeb4, regebc, regec4, regecc;
745 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
746 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
748 /* One shot, path B LOK & IQK */
749 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
750 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
752 mdelay(IQK_DELAY_TIME_88E);
754 regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
755 regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
756 regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
757 regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
758 regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
760 if (!(regeac & BIT(31)) &&
761 (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
762 (((regebc & 0x03FF0000)>>16) != 0x42))
767 if (!(regeac & BIT(30)) &&
768 (((regec4 & 0x03FF0000)>>16) != 0x132) &&
769 (((regecc & 0x03FF0000)>>16) != 0x36))
772 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
773 ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n"));
777 static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
778 u8 final_candidate, bool txonly)
780 u32 oldval_0, x, tx0_a, reg;
783 if (final_candidate == 0xFF) {
786 oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
788 x = result[final_candidate][0];
789 if ((x & 0x00000200) != 0)
792 tx0_a = (x * oldval_0) >> 8;
793 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
794 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
795 ((x * oldval_0>>7) & 0x1));
797 y = result[final_candidate][1];
798 if ((y & 0x00000200) != 0)
801 tx0_c = (y * oldval_0) >> 8;
802 phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
804 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
806 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
807 ((y * oldval_0>>7) & 0x1));
812 reg = result[final_candidate][2];
813 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
815 reg = result[final_candidate][3] & 0x3F;
816 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
818 reg = (result[final_candidate][3] >> 6) & 0xF;
819 phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
823 static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
824 u8 final_candidate, bool txonly)
826 u32 oldval_1, x, tx1_a, reg;
829 if (final_candidate == 0xFF) {
832 oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
834 x = result[final_candidate][4];
835 if ((x & 0x00000200) != 0)
837 tx1_a = (x * oldval_1) >> 8;
838 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
840 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
841 ((x * oldval_1>>7) & 0x1));
843 y = result[final_candidate][5];
844 if ((y & 0x00000200) != 0)
847 tx1_c = (y * oldval_1) >> 8;
849 phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
851 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
853 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
854 ((y * oldval_1>>7) & 0x1));
859 reg = result[final_candidate][6];
860 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
862 reg = result[final_candidate][7] & 0x3F;
863 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
865 reg = (result[final_candidate][7] >> 6) & 0xF;
866 phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
870 static void save_adda_registers(struct adapter *adapt, u32 *addareg,
871 u32 *backup, u32 register_num)
875 for (i = 0; i < register_num; i++) {
876 backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
880 static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
885 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
886 backup[i] = usb_read8(adapt, mac_reg[i]);
888 backup[i] = usb_read32(adapt, mac_reg[i]);
891 static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
892 u32 *backup, u32 regiester_num)
896 for (i = 0; i < regiester_num; i++)
897 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
900 static void reload_mac_registers(struct adapter *adapt,
901 u32 *mac_reg, u32 *backup)
905 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
906 usb_write8(adapt, mac_reg[i], (u8)backup[i]);
908 usb_write32(adapt, mac_reg[i], backup[i]);
911 static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
912 bool is_path_a_on, bool is2t)
918 path_on = 0x0bdb25a0;
919 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
921 path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
922 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
925 for (i = 1; i < IQK_ADDA_REG_NUM; i++)
926 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
929 static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
933 usb_write8(adapt, mac_reg[i], 0x3F);
935 for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
936 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
938 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
941 static void path_a_standby(struct adapter *adapt)
944 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
945 phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
946 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
949 static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
953 mode = pi_mode ? 0x01000100 : 0x01000000;
954 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
955 phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
958 static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
961 u32 i, j, diff, sim_bitmap = 0, bound;
962 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
963 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
964 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
966 s32 tmp1 = 0, tmp2 = 0;
968 if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) ||
969 (dm_odm->RFType == ODM_2T4R))
974 for (i = 0; i < bound; i++) {
975 if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
976 if ((resulta[c1][i] & 0x00000200) != 0)
977 tmp1 = resulta[c1][i] | 0xFFFFFC00;
979 tmp1 = resulta[c1][i];
981 if ((resulta[c2][i] & 0x00000200) != 0)
982 tmp2 = resulta[c2][i] | 0xFFFFFC00;
984 tmp2 = resulta[c2][i];
986 tmp1 = resulta[c1][i];
987 tmp2 = resulta[c2][i];
990 diff = abs(tmp1 - tmp2);
992 if (diff > MAX_TOLERANCE) {
993 if ((i == 2 || i == 6) && !sim_bitmap) {
994 if (resulta[c1][i] + resulta[c1][i+1] == 0)
995 final_candidate[(i/4)] = c2;
996 else if (resulta[c2][i] + resulta[c2][i+1] == 0)
997 final_candidate[(i/4)] = c1;
999 sim_bitmap = sim_bitmap | (1<<i);
1001 sim_bitmap = sim_bitmap | (1<<i);
1006 if (sim_bitmap == 0) {
1007 for (i = 0; i < (bound/4); i++) {
1008 if (final_candidate[i] != 0xFF) {
1009 for (j = i*4; j < (i+1)*4-2; j++)
1010 resulta[3][j] = resulta[final_candidate[i]][j];
1016 if (!(sim_bitmap & 0x03)) { /* path A TX OK */
1017 for (i = 0; i < 2; i++)
1018 resulta[3][i] = resulta[c1][i];
1020 if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
1021 for (i = 2; i < 4; i++)
1022 resulta[3][i] = resulta[c1][i];
1025 if (!(sim_bitmap & 0x30)) { /* path B TX OK */
1026 for (i = 4; i < 6; i++)
1027 resulta[3][i] = resulta[c1][i];
1030 if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
1031 for (i = 6; i < 8; i++)
1032 resulta[3][i] = resulta[c1][i];
1038 static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
1041 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1042 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1044 u8 path_a_ok, path_b_ok;
1045 u32 adda_reg[IQK_ADDA_REG_NUM] = {
1046 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
1047 rRx_Wait_CCA, rTx_CCK_RFON,
1048 rTx_CCK_BBON, rTx_OFDM_RFON,
1049 rTx_OFDM_BBON, rTx_To_Rx,
1051 rRx_OFDM, rRx_Wait_RIFS,
1052 rRx_TO_Rx, rStandby,
1053 rSleep, rPMPD_ANAEN};
1055 u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
1056 REG_TXPAUSE, REG_BCN_CTRL,
1057 REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
1059 /* since 92C & 92D have the different define in IQK_BB_REG */
1060 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1061 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
1062 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
1063 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
1064 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
1066 u32 retry_count = 9;
1067 if (*(dm_odm->mp_mode) == 1)
1074 /* Save ADDA parameters, turn Path A ADDA on */
1075 save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1077 save_mac_registers(adapt, iqk_mac_reg,
1078 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1079 save_adda_registers(adapt, iqk_bb_reg_92c,
1080 dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1083 path_adda_on(adapt, adda_reg, true, is2t);
1085 dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1088 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1089 /* Switch BB to PI mode to do IQ Calibration. */
1090 pi_mode_switch(adapt, true);
1094 phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
1095 phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1096 phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1097 phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1099 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
1100 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
1101 phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
1102 phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
1105 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1107 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1112 mac_setting_calibration(adapt, iqk_mac_reg,
1113 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1117 phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1120 phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1122 /* IQ calibration setting */
1123 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1124 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1125 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1127 for (i = 0; i < retry_count; i++) {
1128 path_a_ok = phy_path_a_iqk(adapt, is2t);
1129 if (path_a_ok == 0x01) {
1130 result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1131 bMaskDWord)&0x3FF0000)>>16;
1132 result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1133 bMaskDWord)&0x3FF0000)>>16;
1138 for (i = 0; i < retry_count; i++) {
1139 path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1140 if (path_a_ok == 0x03) {
1141 result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1142 bMaskDWord)&0x3FF0000)>>16;
1143 result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1144 bMaskDWord)&0x3FF0000)>>16;
1147 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1148 ("Path A Rx IQK Fail!!\n"));
1152 if (0x00 == path_a_ok) {
1153 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1154 ("Path A IQK failed!!\n"));
1158 path_a_standby(adapt);
1160 /* Turn Path B ADDA on */
1161 path_adda_on(adapt, adda_reg, false, is2t);
1163 for (i = 0; i < retry_count; i++) {
1164 path_b_ok = phy_path_b_iqk(adapt);
1165 if (path_b_ok == 0x03) {
1166 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1167 bMaskDWord)&0x3FF0000)>>16;
1168 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1169 bMaskDWord)&0x3FF0000)>>16;
1170 result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1171 bMaskDWord)&0x3FF0000)>>16;
1172 result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1173 bMaskDWord)&0x3FF0000)>>16;
1175 } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
1176 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1177 bMaskDWord)&0x3FF0000)>>16;
1178 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1179 bMaskDWord)&0x3FF0000)>>16;
1183 if (0x00 == path_b_ok) {
1184 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1185 ("Path B IQK failed!!\n"));
1189 /* Back to BB mode, load original value */
1190 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1193 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1194 /* Switch back BB to SI mode after
1195 * finish IQ Calibration.
1197 pi_mode_switch(adapt, false);
1200 /* Reload ADDA power saving parameters */
1201 reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1204 /* Reload MAC parameters */
1205 reload_mac_registers(adapt, iqk_mac_reg,
1206 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1208 reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1211 /* Restore RX initial gain */
1212 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1213 bMaskDWord, 0x00032ed3);
1215 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1216 bMaskDWord, 0x00032ed3);
1218 /* load 0xe30 IQC default value */
1219 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1220 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1224 static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1227 u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1229 /* Check continuous TX and Packet TX */
1230 tmpreg = usb_read8(adapt, 0xd03);
1232 if ((tmpreg&0x70) != 0)
1233 usb_write8(adapt, 0xd03, tmpreg&0x8F);
1235 usb_write8(adapt, REG_TXPAUSE, 0xFF);
1237 if ((tmpreg&0x70) != 0) {
1238 /* 1. Read original RF mode */
1240 rf_a_mode = phy_query_rf_reg(adapt, RF_PATH_A, RF_AC,
1245 rf_b_mode = phy_query_rf_reg(adapt, RF_PATH_B, RF_AC,
1248 /* 2. Set RF mode = standby mode */
1250 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1251 (rf_a_mode&0x8FFFF)|0x10000);
1255 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1256 (rf_b_mode&0x8FFFF)|0x10000);
1259 /* 3. Read RF reg18 */
1260 lc_cal = phy_query_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1262 /* 4. Set LC calibration begin bit15 */
1263 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1268 /* Restore original situation */
1269 if ((tmpreg&0x70) != 0) {
1270 /* Deal with continuous TX case */
1272 usb_write8(adapt, 0xd03, tmpreg);
1273 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1277 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1280 /* Deal with Packet TX case */
1281 usb_write8(adapt, REG_TXPAUSE, 0x00);
1285 void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1287 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1288 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1290 u8 i, final, chn_index;
1291 bool pathaok, pathbok;
1292 s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
1293 bool is12simular, is13simular, is23simular;
1294 bool singletone = false, carrier_sup = false;
1295 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1296 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1297 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1298 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1299 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1300 rOFDM0_RxIQExtAnta};
1303 is2t = (dm_odm->RFType == ODM_2T2R) ? true : false;
1305 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1308 if (singletone || carrier_sup)
1312 ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1313 ("phy_iq_calibrate: Return due to recovery!\n"));
1314 reload_adda_reg(adapt, iqk_bb_reg_92c,
1315 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1319 for (i = 0; i < 8; i++) {
1323 if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
1324 result[3][i] = 0x100;
1331 is12simular = false;
1332 is23simular = false;
1333 is13simular = false;
1335 for (i = 0; i < 3; i++) {
1336 phy_iq_calibrate(adapt, result, i, is2t);
1339 is12simular = simularity_compare(adapt, result, 0, 1);
1347 is13simular = simularity_compare(adapt, result, 0, 2);
1352 is23simular = simularity_compare(adapt, result, 1, 2);
1360 for (i = 0; i < 4; i++) {
1361 reg_e94 = result[i][0];
1362 reg_e9c = result[i][1];
1363 reg_ea4 = result[i][2];
1364 reg_eb4 = result[i][4];
1365 reg_ebc = result[i][5];
1366 reg_ec4 = result[i][6];
1369 if (final != 0xff) {
1370 reg_e94 = result[final][0];
1371 reg_e9c = result[final][1];
1372 reg_ea4 = result[final][2];
1373 reg_eb4 = result[final][4];
1374 reg_ebc = result[final][5];
1375 dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1376 dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1377 dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1378 dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1379 reg_ec4 = result[final][6];
1383 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1384 ("IQK: FAIL use default value\n"));
1385 dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1386 dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1387 dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1388 dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1391 patha_fill_iqk(adapt, pathaok, result, final,
1395 pathb_fill_iqk(adapt, pathbok, result, final,
1399 chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel);
1402 for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1403 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1404 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1407 save_adda_registers(adapt, iqk_bb_reg_92c,
1408 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1411 void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1413 bool singletone = false, carrier_sup = false;
1414 u32 timeout = 2000, timecount = 0;
1415 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1416 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1418 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1420 if (singletone || carrier_sup)
1423 while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1428 dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1430 if (dm_odm->RFType == ODM_2T2R) {
1431 phy_lc_calibrate(adapt, true);
1434 phy_lc_calibrate(adapt, false);
1437 dm_odm->RFCalibrateInfo.bLCKInProgress = false;