Commit | Line | Data |
---|---|---|
615a4d12 LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
4 | * | |
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. | |
8 | * | |
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 | |
12 | * more details. | |
13 | * | |
615a4d12 LF |
14 | ******************************************************************************/ |
15 | #define _RTL8188E_PHYCFG_C_ | |
16 | ||
17 | #include <osdep_service.h> | |
18 | #include <drv_types.h> | |
19 | #include <rtw_iol.h> | |
20 | #include <rtl8188e_hal.h> | |
20273244 | 21 | #include <rf.h> |
f60705fd | 22 | #include <phy.h> |
615a4d12 | 23 | |
615a4d12 LF |
24 | #define MAX_PRECMD_CNT 16 |
25 | #define MAX_RFDEPENDCMD_CNT 16 | |
26 | #define MAX_POSTCMD_CNT 16 | |
27 | ||
28 | #define MAX_DOZE_WAITING_TIMES_9x 64 | |
29 | ||
6e264feb | 30 | static u32 cal_bit_shift(u32 bitmask) |
615a4d12 LF |
31 | { |
32 | u32 i; | |
33 | ||
34 | for (i = 0; i <= 31; i++) { | |
6e264feb | 35 | if (((bitmask >> i) & 0x1) == 1) |
615a4d12 LF |
36 | break; |
37 | } | |
38 | return i; | |
39 | } | |
40 | ||
ecd1f9b3 | 41 | u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask) |
615a4d12 | 42 | { |
ecd1f9b3 | 43 | u32 return_value = 0, original_value, bit_shift; |
615a4d12 | 44 | |
ecd1f9b3 | 45 | original_value = usb_read32(adapt, regaddr); |
46 | bit_shift = cal_bit_shift(bitmask); | |
47 | return_value = (original_value & bitmask) >> bit_shift; | |
48 | return return_value; | |
615a4d12 LF |
49 | } |
50 | ||
9c6db651 | 51 | void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data) |
615a4d12 | 52 | { |
9c6db651 | 53 | u32 original_value, bit_shift; |
615a4d12 | 54 | |
9c6db651 | 55 | if (bitmask != bMaskDWord) { /* if not "double word" write */ |
56 | original_value = usb_read32(adapt, regaddr); | |
57 | bit_shift = cal_bit_shift(bitmask); | |
adb3d770 | 58 | data = (original_value & (~bitmask)) | (data << bit_shift); |
615a4d12 LF |
59 | } |
60 | ||
9c6db651 | 61 | usb_write32(adapt, regaddr, data); |
615a4d12 LF |
62 | } |
63 | ||
a35b747d | 64 | static u32 rf_serial_read(struct adapter *adapt, |
65 | enum rf_radio_path rfpath, u32 offset) | |
615a4d12 | 66 | { |
a35b747d | 67 | u32 ret = 0; |
68 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
69 | struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; | |
615a4d12 | 70 | u32 tmplong, tmplong2; |
a35b747d | 71 | u8 rfpi_enable = 0; |
615a4d12 | 72 | |
a35b747d | 73 | offset &= 0xff; |
615a4d12 | 74 | |
a35b747d | 75 | tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord); |
76 | if (rfpath == RF_PATH_A) | |
615a4d12 LF |
77 | tmplong2 = tmplong; |
78 | else | |
a35b747d | 79 | tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2, |
80 | bMaskDWord); | |
615a4d12 | 81 | |
a35b747d | 82 | tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | |
9734d632 | 83 | (offset<<23) | bLSSIReadEdge; |
615a4d12 | 84 | |
a35b747d | 85 | phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord, |
86 | tmplong&(~bLSSIReadEdge)); | |
87 | udelay(10); | |
615a4d12 | 88 | |
a35b747d | 89 | phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2); |
90 | udelay(100); | |
615a4d12 | 91 | |
a35b747d | 92 | udelay(10); |
615a4d12 | 93 | |
a35b747d | 94 | if (rfpath == RF_PATH_A) |
9c68ed09 | 95 | rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8)); |
a35b747d | 96 | else if (rfpath == RF_PATH_B) |
9c68ed09 | 97 | rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8)); |
615a4d12 | 98 | |
a35b747d | 99 | if (rfpi_enable) |
100 | ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi, | |
101 | bLSSIReadBackData); | |
102 | else | |
103 | ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack, | |
104 | bLSSIReadBackData); | |
105 | return ret; | |
615a4d12 LF |
106 | } |
107 | ||
42f27158 | 108 | static void rf_serial_write(struct adapter *adapt, |
109 | enum rf_radio_path rfpath, u32 offset, | |
110 | u32 data) | |
615a4d12 | 111 | { |
42f27158 | 112 | u32 data_and_addr = 0; |
113 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
114 | struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; | |
615a4d12 | 115 | |
065be69f VH |
116 | offset &= 0xff; |
117 | data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff; | |
42f27158 | 118 | phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr); |
615a4d12 LF |
119 | } |
120 | ||
76098bcb | 121 | u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, |
41b77d26 | 122 | u32 reg_addr, u32 bit_mask) |
615a4d12 | 123 | { |
41b77d26 | 124 | u32 original_value, readback_value, bit_shift; |
615a4d12 | 125 | |
41b77d26 | 126 | original_value = rf_serial_read(adapt, rf_path, reg_addr); |
127 | bit_shift = cal_bit_shift(bit_mask); | |
128 | readback_value = (original_value & bit_mask) >> bit_shift; | |
129 | return readback_value; | |
615a4d12 LF |
130 | } |
131 | ||
7b98485c | 132 | void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, |
133 | u32 reg_addr, u32 bit_mask, u32 data) | |
615a4d12 | 134 | { |
7b98485c | 135 | u32 original_value, bit_shift; |
615a4d12 LF |
136 | |
137 | /* RF data is 12 bits only */ | |
7b98485c | 138 | if (bit_mask != bRFRegOffsetMask) { |
139 | original_value = rf_serial_read(adapt, rf_path, reg_addr); | |
140 | bit_shift = cal_bit_shift(bit_mask); | |
adb3d770 | 141 | data = (original_value & (~bit_mask)) | (data << bit_shift); |
615a4d12 LF |
142 | } |
143 | ||
7b98485c | 144 | rf_serial_write(adapt, rf_path, reg_addr, data); |
615a4d12 LF |
145 | } |
146 | ||
88cbb390 | 147 | static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr, |
148 | u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr) | |
615a4d12 | 149 | { |
88cbb390 | 150 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
615a4d12 LF |
151 | u8 index = (channel - 1); |
152 | u8 TxCount = 0, path_nums; | |
153 | ||
88cbb390 | 154 | if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type)) |
615a4d12 LF |
155 | path_nums = 1; |
156 | else | |
157 | path_nums = 2; | |
158 | ||
159 | for (TxCount = 0; TxCount < path_nums; TxCount++) { | |
160 | if (TxCount == RF_PATH_A) { | |
88cbb390 | 161 | cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index]; |
162 | ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+ | |
163 | hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A]; | |
164 | ||
165 | bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+ | |
166 | hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]; | |
167 | bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index]; | |
615a4d12 | 168 | } else if (TxCount == RF_PATH_B) { |
88cbb390 | 169 | cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index]; |
170 | ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+ | |
171 | hal_data->BW20_24G_Diff[RF_PATH_A][index]+ | |
172 | hal_data->BW20_24G_Diff[TxCount][index]; | |
173 | ||
174 | bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+ | |
175 | hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+ | |
176 | hal_data->BW20_24G_Diff[TxCount][index]; | |
177 | bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index]; | |
615a4d12 LF |
178 | } |
179 | } | |
180 | } | |
181 | ||
a8b74c3e | 182 | static void phy_power_index_check(struct adapter *adapt, u8 channel, |
183 | u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr, | |
184 | u8 *bw40_pwr) | |
615a4d12 | 185 | { |
a8b74c3e | 186 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
615a4d12 | 187 | |
a8b74c3e | 188 | hal_data->CurrentCckTxPwrIdx = cck_pwr[0]; |
189 | hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0]; | |
190 | hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0]; | |
191 | hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0]; | |
615a4d12 LF |
192 | } |
193 | ||
01c5f833 | 194 | void phy_set_tx_power_level(struct adapter *adapt, u8 channel) |
615a4d12 | 195 | { |
01c5f833 | 196 | u8 cck_pwr[MAX_TX_COUNT] = {0}; |
197 | u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */ | |
198 | u8 bw20_pwr[MAX_TX_COUNT] = {0}; | |
199 | u8 bw40_pwr[MAX_TX_COUNT] = {0}; | |
615a4d12 | 200 | |
01c5f833 | 201 | get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0], |
202 | &bw20_pwr[0], &bw40_pwr[0]); | |
615a4d12 | 203 | |
01c5f833 | 204 | phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0], |
205 | &bw20_pwr[0], &bw40_pwr[0]); | |
615a4d12 | 206 | |
c5db81ac | 207 | rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]); |
fb393d26 | 208 | rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0], |
01c5f833 | 209 | &bw40_pwr[0], channel); |
615a4d12 LF |
210 | } |
211 | ||
55d8dfbf | 212 | static void phy_set_bw_mode_callback(struct adapter *adapt) |
615a4d12 | 213 | { |
55d8dfbf | 214 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
215 | u8 reg_bw_opmode; | |
216 | u8 reg_prsr_rsc; | |
615a4d12 | 217 | |
55d8dfbf | 218 | if (hal_data->rf_chip == RF_PSEUDO_11N) |
615a4d12 LF |
219 | return; |
220 | ||
221 | /* There is no 40MHz mode in RF_8225. */ | |
55d8dfbf | 222 | if (hal_data->rf_chip == RF_8225) |
615a4d12 LF |
223 | return; |
224 | ||
55d8dfbf | 225 | if (adapt->bDriverStopped) |
615a4d12 LF |
226 | return; |
227 | ||
55d8dfbf | 228 | /* Set MAC register */ |
615a4d12 | 229 | |
55d8dfbf | 230 | reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE); |
231 | reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2); | |
615a4d12 | 232 | |
55d8dfbf | 233 | switch (hal_data->CurrentChannelBW) { |
615a4d12 | 234 | case HT_CHANNEL_WIDTH_20: |
55d8dfbf | 235 | reg_bw_opmode |= BW_OPMODE_20MHZ; |
236 | usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode); | |
615a4d12 LF |
237 | break; |
238 | case HT_CHANNEL_WIDTH_40: | |
55d8dfbf | 239 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; |
240 | usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode); | |
241 | reg_prsr_rsc = (reg_prsr_rsc&0x90) | | |
242 | (hal_data->nCur40MhzPrimeSC<<5); | |
243 | usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc); | |
615a4d12 LF |
244 | break; |
245 | default: | |
246 | break; | |
247 | } | |
248 | ||
55d8dfbf | 249 | /* Set PHY related register */ |
250 | switch (hal_data->CurrentChannelBW) { | |
615a4d12 | 251 | case HT_CHANNEL_WIDTH_20: |
55d8dfbf | 252 | phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0); |
253 | phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0); | |
615a4d12 | 254 | break; |
615a4d12 | 255 | case HT_CHANNEL_WIDTH_40: |
55d8dfbf | 256 | phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1); |
257 | phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1); | |
258 | /* Set Control channel to upper or lower. | |
259 | * These settings are required only for 40MHz | |
260 | */ | |
261 | phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand, | |
262 | (hal_data->nCur40MhzPrimeSC>>1)); | |
263 | phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00, | |
264 | hal_data->nCur40MhzPrimeSC); | |
9c68ed09 | 265 | phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)), |
55d8dfbf | 266 | (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); |
615a4d12 LF |
267 | break; |
268 | default: | |
269 | break; | |
270 | } | |
615a4d12 | 271 | |
55d8dfbf | 272 | /* Set RF related register */ |
efb8d497 | 273 | if (hal_data->rf_chip == RF_6052) |
20273244 | 274 | rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW); |
615a4d12 LF |
275 | } |
276 | ||
1ac7c986 | 277 | void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, |
5f6a5cdb | 278 | unsigned char offset) |
615a4d12 | 279 | { |
5f6a5cdb | 280 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
281 | enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW; | |
615a4d12 | 282 | |
5f6a5cdb | 283 | hal_data->CurrentChannelBW = bandwidth; |
284 | hal_data->nCur40MhzPrimeSC = offset; | |
615a4d12 | 285 | |
5f6a5cdb | 286 | if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved)) |
287 | phy_set_bw_mode_callback(adapt); | |
615a4d12 | 288 | else |
5f6a5cdb | 289 | hal_data->CurrentChannelBW = tmp_bw; |
615a4d12 LF |
290 | } |
291 | ||
9c431940 | 292 | static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) |
615a4d12 | 293 | { |
9c431940 | 294 | u8 rf_path; |
615a4d12 | 295 | u32 param1, param2; |
9c431940 | 296 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
615a4d12 | 297 | |
01c5f833 | 298 | phy_set_tx_power_level(adapt, channel); |
615a4d12 | 299 | |
615a4d12 LF |
300 | param1 = RF_CHNLBW; |
301 | param2 = channel; | |
9c431940 | 302 | for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) { |
303 | hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] & | |
304 | 0xfffffc00) | param2; | |
305 | phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1, | |
306 | bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]); | |
615a4d12 LF |
307 | } |
308 | } | |
309 | ||
bada35ba | 310 | void rtw_hal_set_chan(struct adapter *adapt, u8 channel) |
615a4d12 | 311 | { |
ba50fbc0 | 312 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
313 | u8 tmpchannel = hal_data->CurrentChannel; | |
615a4d12 | 314 | |
ba50fbc0 | 315 | if (hal_data->rf_chip == RF_PSEUDO_11N) |
316 | return; | |
615a4d12 LF |
317 | |
318 | if (channel == 0) | |
319 | channel = 1; | |
320 | ||
ba50fbc0 | 321 | hal_data->CurrentChannel = channel; |
615a4d12 | 322 | |
8e2c69b6 | 323 | if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved)) |
ba50fbc0 | 324 | phy_sw_chnl_callback(adapt, channel); |
8e2c69b6 | 325 | else |
ba50fbc0 | 326 | hal_data->CurrentChannel = tmpchannel; |
615a4d12 | 327 | } |
d9124e06 | 328 | |
329 | #define ODM_TXPWRTRACK_MAX_IDX_88E 6 | |
330 | ||
331 | static u8 get_right_chnl_for_iqk(u8 chnl) | |
332 | { | |
93ab486d | 333 | u8 place; |
d9124e06 | 334 | u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = { |
d9124e06 | 335 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, |
336 | 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, | |
337 | 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, | |
338 | 155, 157, 159, 161, 163, 165 | |
339 | }; | |
d9124e06 | 340 | |
341 | if (chnl > 14) { | |
93ab486d | 342 | for (place = 0; place < sizeof(channel_all); place++) { |
d9124e06 | 343 | if (channel_all[place] == chnl) |
93ab486d | 344 | return ++place; |
d9124e06 | 345 | } |
346 | } | |
347 | return 0; | |
348 | } | |
349 | ||
350 | void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, | |
351 | u8 *direction, u32 *out_write_val) | |
352 | { | |
353 | u8 pwr_value = 0; | |
354 | /* Tx power tracking BB swing table. */ | |
355 | if (type == 0) { /* For OFDM adjust */ | |
356 | ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, | |
357 | ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n", | |
358 | dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm)); | |
359 | ||
360 | if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) { | |
361 | *direction = 1; | |
adb3d770 HM |
362 | pwr_value = dm_odm->BbSwingIdxOfdmBase - |
363 | dm_odm->BbSwingIdxOfdm; | |
d9124e06 | 364 | } else { |
365 | *direction = 2; | |
adb3d770 HM |
366 | pwr_value = dm_odm->BbSwingIdxOfdm - |
367 | dm_odm->BbSwingIdxOfdmBase; | |
d9124e06 | 368 | } |
369 | ||
370 | } else if (type == 1) { /* For CCK adjust. */ | |
371 | ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, | |
372 | ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n", | |
373 | dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase)); | |
374 | ||
375 | if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) { | |
376 | *direction = 1; | |
adb3d770 HM |
377 | pwr_value = dm_odm->BbSwingIdxCckBase - |
378 | dm_odm->BbSwingIdxCck; | |
d9124e06 | 379 | } else { |
380 | *direction = 2; | |
adb3d770 HM |
381 | pwr_value = dm_odm->BbSwingIdxCck - |
382 | dm_odm->BbSwingIdxCckBase; | |
d9124e06 | 383 | } |
384 | ||
385 | } | |
386 | ||
387 | if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1) | |
388 | pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E; | |
389 | ||
390 | *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) | | |
391 | (pwr_value<<24); | |
392 | } | |
393 | ||
394 | static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm) | |
395 | { | |
396 | if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) { | |
397 | ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, | |
398 | ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel))); | |
399 | phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel)); | |
400 | dm_odm->BbSwingFlagOfdm = false; | |
401 | dm_odm->BbSwingFlagCck = false; | |
402 | } | |
403 | } | |
404 | ||
405 | void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) | |
406 | { | |
407 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
408 | u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset; | |
409 | u8 thermal_avg_count = 0; | |
410 | u32 thermal_avg = 0; | |
0395e554 | 411 | s32 ele_d, temp_cck; |
d9124e06 | 412 | s8 ofdm_index[2], cck_index = 0; |
413 | s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0; | |
414 | u32 i = 0, j = 0; | |
415 | bool is2t = false; | |
416 | ||
417 | u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */ | |
d9124e06 | 418 | s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = { |
419 | /* 2.4G, decrease power */ | |
420 | {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, | |
421 | /* 2.4G, increase power */ | |
7be921a2 | 422 | {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10}, |
d9124e06 | 423 | }; |
424 | u8 thermal_mapping[2][index_mapping_NUM_88E] = { | |
425 | /* 2.4G, decrease power */ | |
426 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27}, | |
427 | /* 2.4G, increase power */ | |
428 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25}, | |
429 | }; | |
430 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
431 | ||
432 | dm_txpwr_track_setpwr(dm_odm); | |
433 | ||
434 | dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++; | |
435 | dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true; | |
436 | ||
437 | dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317; | |
438 | ||
76098bcb | 439 | thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A, |
d9124e06 | 440 | RF_T_METER_88E, 0xfc00); |
441 | ||
442 | if (is2t) | |
443 | rf = 2; | |
444 | else | |
445 | rf = 1; | |
446 | ||
447 | if (thermal_val) { | |
448 | /* Query OFDM path A default setting */ | |
449 | ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; | |
450 | for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { | |
451 | if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) { | |
452 | ofdm_index_old[0] = (u8)i; | |
453 | dm_odm->BbSwingIdxOfdmBase = (u8)i; | |
454 | break; | |
455 | } | |
456 | } | |
457 | ||
458 | /* Query OFDM path B default setting */ | |
459 | if (is2t) { | |
460 | ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; | |
461 | for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { | |
462 | if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) { | |
463 | ofdm_index_old[1] = (u8)i; | |
464 | break; | |
465 | } | |
466 | } | |
467 | } | |
468 | ||
469 | /* Query CCK default setting From 0xa24 */ | |
470 | temp_cck = dm_odm->RFCalibrateInfo.RegA24; | |
471 | ||
472 | for (i = 0; i < CCK_TABLE_SIZE; i++) { | |
294a7fcc VH |
473 | if ((dm_odm->RFCalibrateInfo.bCCKinCH14 && |
474 | memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) || | |
475 | memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) { | |
d9124e06 | 476 | cck_index_old = (u8)i; |
477 | dm_odm->BbSwingIdxCckBase = (u8)i; | |
478 | break; | |
d9124e06 | 479 | } |
480 | } | |
481 | ||
482 | if (!dm_odm->RFCalibrateInfo.ThermalValue) { | |
483 | dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter; | |
484 | dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val; | |
485 | dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val; | |
486 | ||
487 | for (i = 0; i < rf; i++) | |
488 | dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i]; | |
489 | dm_odm->RFCalibrateInfo.CCK_index = cck_index_old; | |
490 | } | |
491 | ||
492 | /* calculate average thermal meter */ | |
493 | dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val; | |
494 | dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++; | |
495 | if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E) | |
496 | dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0; | |
497 | ||
498 | for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { | |
499 | if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) { | |
500 | thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]; | |
501 | thermal_avg_count++; | |
502 | } | |
503 | } | |
504 | ||
505 | if (thermal_avg_count) | |
506 | thermal_val = (u8)(thermal_avg / thermal_avg_count); | |
507 | ||
4c3fa640 VH |
508 | if (dm_odm->RFCalibrateInfo.bDoneTxpower && |
509 | !dm_odm->RFCalibrateInfo.bReloadtxpowerindex) | |
510 | delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue); | |
511 | else { | |
512 | delta = abs(thermal_val - hal_data->EEPROMThermalMeter); | |
513 | if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) { | |
514 | dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false; | |
515 | dm_odm->RFCalibrateInfo.bDoneTxpower = false; | |
516 | } | |
d9124e06 | 517 | } |
4c3fa640 VH |
518 | |
519 | delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val); | |
520 | delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val); | |
d9124e06 | 521 | |
522 | /* Delta temperature is equal to or larger than 20 centigrade.*/ | |
523 | if ((delta_lck >= 8)) { | |
524 | dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val; | |
525 | rtl88eu_phy_lc_calibrate(adapt); | |
526 | } | |
527 | ||
528 | if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) { | |
d5dd06ea VH |
529 | delta = abs(hal_data->EEPROMThermalMeter - thermal_val); |
530 | ||
d9124e06 | 531 | /* calculate new OFDM / CCK offset */ |
532 | if (thermal_val > hal_data->EEPROMThermalMeter) | |
533 | j = 1; | |
534 | else | |
535 | j = 0; | |
536 | for (offset = 0; offset < index_mapping_NUM_88E; offset++) { | |
537 | if (delta < thermal_mapping[j][offset]) { | |
538 | if (offset != 0) | |
539 | offset--; | |
540 | break; | |
541 | } | |
542 | } | |
543 | if (offset >= index_mapping_NUM_88E) | |
544 | offset = index_mapping_NUM_88E-1; | |
d9124e06 | 545 | |
4ceb7f72 | 546 | /* Updating ofdm_index values with new OFDM / CCK offset */ |
d9124e06 | 547 | for (i = 0; i < rf; i++) { |
4ceb7f72 | 548 | ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset]; |
d9124e06 | 549 | if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1) |
550 | ofdm_index[i] = OFDM_TABLE_SIZE_92D-1; | |
551 | else if (ofdm_index[i] < ofdm_min_index) | |
552 | ofdm_index[i] = ofdm_min_index; | |
553 | } | |
554 | ||
4ceb7f72 | 555 | cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset]; |
d9124e06 | 556 | if (cck_index > CCK_TABLE_SIZE-1) |
557 | cck_index = CCK_TABLE_SIZE-1; | |
558 | else if (cck_index < 0) | |
559 | cck_index = 0; | |
560 | ||
561 | /* 2 temporarily remove bNOPG */ | |
562 | /* Config by SwingTable */ | |
563 | if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) { | |
564 | dm_odm->RFCalibrateInfo.bDoneTxpower = true; | |
565 | ||
d9124e06 | 566 | /* Revse TX power table. */ |
567 | dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0]; | |
568 | dm_odm->BbSwingIdxCck = (u8)cck_index; | |
569 | ||
570 | if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) { | |
571 | dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm; | |
572 | dm_odm->BbSwingFlagOfdm = true; | |
573 | } | |
574 | ||
575 | if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) { | |
576 | dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck; | |
577 | dm_odm->BbSwingFlagCck = true; | |
578 | } | |
d9124e06 | 579 | } |
580 | } | |
581 | ||
582 | /* Delta temperature is equal to or larger than 20 centigrade.*/ | |
583 | if (delta_iqk >= 8) { | |
584 | dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val; | |
585 | rtl88eu_phy_iq_calibrate(adapt, false); | |
586 | } | |
587 | /* update thermal meter value */ | |
588 | if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) | |
589 | dm_odm->RFCalibrateInfo.ThermalValue = thermal_val; | |
590 | } | |
591 | dm_odm->RFCalibrateInfo.TXPowercount = 0; | |
592 | } | |
593 | ||
594 | #define MAX_TOLERANCE 5 | |
595 | ||
596 | static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb) | |
597 | { | |
9393d34e | 598 | u32 reg_eac, reg_e94, reg_e9c; |
d9124e06 | 599 | u8 result = 0x00; |
600 | ||
601 | /* 1 Tx IQK */ | |
602 | /* path-A IQK setting */ | |
603 | phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); | |
604 | phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); | |
605 | phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a); | |
606 | phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000); | |
607 | ||
608 | /* LO calibration setting */ | |
609 | phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); | |
610 | ||
611 | /* One shot, path A LOK & IQK */ | |
612 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); | |
613 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); | |
614 | ||
615 | mdelay(IQK_DELAY_TIME_88E); | |
616 | ||
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); | |
d9124e06 | 620 | |
9c68ed09 | 621 | if (!(reg_eac & BIT(28)) && |
d9124e06 | 622 | (((reg_e94 & 0x03FF0000)>>16) != 0x142) && |
623 | (((reg_e9c & 0x03FF0000)>>16) != 0x42)) | |
624 | result |= 0x01; | |
625 | return result; | |
626 | } | |
627 | ||
628 | static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB) | |
629 | { | |
630 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp; | |
631 | u8 result = 0x00; | |
632 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
633 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
634 | ||
635 | /* 1 Get TXIMR setting */ | |
636 | /* modify RXIQK mode table */ | |
637 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); | |
638 | phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0); | |
639 | phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000); | |
640 | phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f); | |
641 | phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B); | |
642 | ||
643 | /* PA,PAD off */ | |
644 | phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980); | |
645 | phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000); | |
646 | ||
647 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); | |
648 | ||
649 | /* IQK setting */ | |
650 | phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00); | |
651 | phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800); | |
652 | ||
653 | /* path-A IQK setting */ | |
654 | phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); | |
655 | phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); | |
656 | phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f); | |
657 | phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000); | |
658 | ||
659 | /* LO calibration setting */ | |
660 | phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); | |
661 | ||
662 | /* One shot, path A LOK & IQK */ | |
663 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); | |
664 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); | |
665 | ||
666 | /* delay x ms */ | |
667 | mdelay(IQK_DELAY_TIME_88E); | |
668 | ||
669 | /* Check failed */ | |
670 | reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); | |
671 | reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord); | |
672 | reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord); | |
673 | ||
9c68ed09 | 674 | if (!(reg_eac & BIT(28)) && |
d9124e06 | 675 | (((reg_e94 & 0x03FF0000)>>16) != 0x142) && |
676 | (((reg_e9c & 0x03FF0000)>>16) != 0x42)) | |
677 | result |= 0x01; | |
678 | else /* if Tx not OK, ignore Rx */ | |
679 | return result; | |
680 | ||
681 | u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16); | |
682 | phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp); | |
683 | ||
684 | /* 1 RX IQK */ | |
685 | /* modify RXIQK mode table */ | |
686 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
687 | ("Path-A Rx IQK modify RXIQK mode table 2!\n")); | |
688 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); | |
689 | phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0); | |
690 | phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000); | |
691 | phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f); | |
692 | phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa); | |
693 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); | |
694 | ||
695 | /* IQK setting */ | |
696 | phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800); | |
697 | ||
698 | /* path-A IQK setting */ | |
699 | phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c); | |
700 | phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c); | |
701 | phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05); | |
702 | phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f); | |
703 | ||
704 | /* LO calibration setting */ | |
705 | phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); | |
706 | ||
707 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); | |
708 | phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); | |
709 | ||
710 | mdelay(IQK_DELAY_TIME_88E); | |
711 | ||
712 | /* Check failed */ | |
713 | reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); | |
714 | reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord); | |
715 | reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord); | |
716 | reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord); | |
717 | ||
718 | /* reload RF 0xdf */ | |
719 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); | |
720 | phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180); | |
721 | ||
9c68ed09 | 722 | if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */ |
d9124e06 | 723 | (((reg_ea4 & 0x03FF0000)>>16) != 0x132) && |
724 | (((reg_eac & 0x03FF0000)>>16) != 0x36)) | |
725 | result |= 0x02; | |
726 | else | |
727 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
728 | ("Path A Rx IQK fail!!\n")); | |
729 | ||
730 | return result; | |
731 | } | |
732 | ||
733 | static u8 phy_path_b_iqk(struct adapter *adapt) | |
734 | { | |
735 | u32 regeac, regeb4, regebc, regec4, regecc; | |
736 | u8 result = 0x00; | |
737 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
738 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
739 | ||
740 | /* One shot, path B LOK & IQK */ | |
741 | phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002); | |
742 | phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000); | |
743 | ||
744 | mdelay(IQK_DELAY_TIME_88E); | |
745 | ||
746 | regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord); | |
747 | regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord); | |
748 | regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord); | |
749 | regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord); | |
750 | regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord); | |
751 | ||
9c68ed09 | 752 | if (!(regeac & BIT(31)) && |
d9124e06 | 753 | (((regeb4 & 0x03FF0000)>>16) != 0x142) && |
754 | (((regebc & 0x03FF0000)>>16) != 0x42)) | |
755 | result |= 0x01; | |
756 | else | |
757 | return result; | |
758 | ||
9c68ed09 | 759 | if (!(regeac & BIT(30)) && |
d9124e06 | 760 | (((regec4 & 0x03FF0000)>>16) != 0x132) && |
761 | (((regecc & 0x03FF0000)>>16) != 0x36)) | |
762 | result |= 0x02; | |
763 | else | |
764 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, | |
765 | ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n")); | |
766 | return result; | |
767 | } | |
768 | ||
769 | static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], | |
770 | u8 final_candidate, bool txonly) | |
771 | { | |
772 | u32 oldval_0, x, tx0_a, reg; | |
773 | s32 y, tx0_c; | |
774 | ||
775 | if (final_candidate == 0xFF) { | |
776 | return; | |
777 | } else if (iqkok) { | |
778 | oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF; | |
779 | ||
780 | x = result[final_candidate][0]; | |
781 | if ((x & 0x00000200) != 0) | |
782 | x = x | 0xFFFFFC00; | |
783 | ||
784 | tx0_a = (x * oldval_0) >> 8; | |
785 | phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a); | |
786 | phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31), | |
787 | ((x * oldval_0>>7) & 0x1)); | |
788 | ||
789 | y = result[final_candidate][1]; | |
790 | if ((y & 0x00000200) != 0) | |
791 | y = y | 0xFFFFFC00; | |
792 | ||
793 | tx0_c = (y * oldval_0) >> 8; | |
794 | phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000, | |
795 | ((tx0_c&0x3C0)>>6)); | |
796 | phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000, | |
797 | (tx0_c&0x3F)); | |
798 | phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29), | |
799 | ((y * oldval_0>>7) & 0x1)); | |
800 | ||
801 | if (txonly) | |
802 | return; | |
803 | ||
804 | reg = result[final_candidate][2]; | |
805 | phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg); | |
806 | ||
807 | reg = result[final_candidate][3] & 0x3F; | |
808 | phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg); | |
809 | ||
810 | reg = (result[final_candidate][3] >> 6) & 0xF; | |
811 | phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg); | |
812 | } | |
813 | } | |
814 | ||
815 | static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], | |
816 | u8 final_candidate, bool txonly) | |
817 | { | |
818 | u32 oldval_1, x, tx1_a, reg; | |
819 | s32 y, tx1_c; | |
820 | ||
821 | if (final_candidate == 0xFF) { | |
822 | return; | |
823 | } else if (iqkok) { | |
824 | oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF; | |
825 | ||
826 | x = result[final_candidate][4]; | |
827 | if ((x & 0x00000200) != 0) | |
828 | x = x | 0xFFFFFC00; | |
829 | tx1_a = (x * oldval_1) >> 8; | |
830 | phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a); | |
831 | ||
832 | phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27), | |
833 | ((x * oldval_1>>7) & 0x1)); | |
834 | ||
835 | y = result[final_candidate][5]; | |
836 | if ((y & 0x00000200) != 0) | |
837 | y = y | 0xFFFFFC00; | |
838 | ||
839 | tx1_c = (y * oldval_1) >> 8; | |
840 | ||
841 | phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000, | |
842 | ((tx1_c&0x3C0)>>6)); | |
843 | phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000, | |
844 | (tx1_c&0x3F)); | |
845 | phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25), | |
846 | ((y * oldval_1>>7) & 0x1)); | |
847 | ||
848 | if (txonly) | |
849 | return; | |
850 | ||
851 | reg = result[final_candidate][6]; | |
852 | phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg); | |
853 | ||
854 | reg = result[final_candidate][7] & 0x3F; | |
855 | phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg); | |
856 | ||
857 | reg = (result[final_candidate][7] >> 6) & 0xF; | |
858 | phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg); | |
859 | } | |
860 | } | |
861 | ||
862 | static void save_adda_registers(struct adapter *adapt, u32 *addareg, | |
863 | u32 *backup, u32 register_num) | |
864 | { | |
865 | u32 i; | |
866 | ||
867 | for (i = 0; i < register_num; i++) { | |
868 | backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord); | |
869 | } | |
870 | } | |
871 | ||
872 | static void save_mac_registers(struct adapter *adapt, u32 *mac_reg, | |
873 | u32 *backup) | |
874 | { | |
875 | u32 i; | |
876 | ||
877 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) { | |
878 | backup[i] = usb_read8(adapt, mac_reg[i]); | |
879 | } | |
880 | backup[i] = usb_read32(adapt, mac_reg[i]); | |
881 | } | |
882 | ||
883 | static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg, | |
884 | u32 *backup, u32 regiester_num) | |
885 | { | |
886 | u32 i; | |
887 | ||
888 | for (i = 0; i < regiester_num; i++) | |
889 | phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]); | |
890 | } | |
891 | ||
892 | static void reload_mac_registers(struct adapter *adapt, | |
893 | u32 *mac_reg, u32 *backup) | |
894 | { | |
895 | u32 i; | |
896 | ||
897 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) { | |
898 | usb_write8(adapt, mac_reg[i], (u8)backup[i]); | |
899 | } | |
900 | usb_write32(adapt, mac_reg[i], backup[i]); | |
901 | } | |
902 | ||
903 | static void path_adda_on(struct adapter *adapt, u32 *adda_reg, | |
904 | bool is_path_a_on, bool is2t) | |
905 | { | |
906 | u32 path_on; | |
907 | u32 i; | |
908 | ||
d9124e06 | 909 | if (!is2t) { |
910 | path_on = 0x0bdb25a0; | |
911 | phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0); | |
912 | } else { | |
179e7dcd | 913 | path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4; |
d9124e06 | 914 | phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on); |
915 | } | |
916 | ||
917 | for (i = 1; i < IQK_ADDA_REG_NUM; i++) | |
918 | phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on); | |
919 | } | |
920 | ||
921 | static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup) | |
922 | { | |
923 | u32 i = 0; | |
924 | ||
925 | usb_write8(adapt, mac_reg[i], 0x3F); | |
926 | ||
927 | for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) { | |
9c68ed09 | 928 | usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3)))); |
d9124e06 | 929 | } |
9c68ed09 | 930 | usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5)))); |
d9124e06 | 931 | } |
932 | ||
933 | static void path_a_standby(struct adapter *adapt) | |
934 | { | |
935 | ||
936 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0); | |
937 | phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000); | |
938 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); | |
939 | } | |
940 | ||
941 | static void pi_mode_switch(struct adapter *adapt, bool pi_mode) | |
942 | { | |
943 | u32 mode; | |
944 | ||
945 | mode = pi_mode ? 0x01000100 : 0x01000000; | |
946 | phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode); | |
947 | phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode); | |
948 | } | |
949 | ||
950 | static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], | |
951 | u8 c1, u8 c2) | |
952 | { | |
3fe90658 | 953 | u32 i, j, diff, sim_bitmap = 0, bound; |
d9124e06 | 954 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); |
955 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
956 | u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ | |
957 | bool result = true; | |
d9124e06 | 958 | s32 tmp1 = 0, tmp2 = 0; |
959 | ||
960 | if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) || | |
961 | (dm_odm->RFType == ODM_2T4R)) | |
d9124e06 | 962 | bound = 8; |
963 | else | |
964 | bound = 4; | |
965 | ||
d9124e06 | 966 | for (i = 0; i < bound; i++) { |
967 | if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { | |
968 | if ((resulta[c1][i] & 0x00000200) != 0) | |
969 | tmp1 = resulta[c1][i] | 0xFFFFFC00; | |
970 | else | |
971 | tmp1 = resulta[c1][i]; | |
972 | ||
973 | if ((resulta[c2][i] & 0x00000200) != 0) | |
974 | tmp2 = resulta[c2][i] | 0xFFFFFC00; | |
975 | else | |
976 | tmp2 = resulta[c2][i]; | |
977 | } else { | |
978 | tmp1 = resulta[c1][i]; | |
979 | tmp2 = resulta[c2][i]; | |
980 | } | |
981 | ||
016c6bba | 982 | diff = abs(tmp1 - tmp2); |
d9124e06 | 983 | |
984 | if (diff > MAX_TOLERANCE) { | |
985 | if ((i == 2 || i == 6) && !sim_bitmap) { | |
986 | if (resulta[c1][i] + resulta[c1][i+1] == 0) | |
987 | final_candidate[(i/4)] = c2; | |
988 | else if (resulta[c2][i] + resulta[c2][i+1] == 0) | |
989 | final_candidate[(i/4)] = c1; | |
990 | else | |
991 | sim_bitmap = sim_bitmap | (1<<i); | |
992 | } else { | |
993 | sim_bitmap = sim_bitmap | (1<<i); | |
994 | } | |
995 | } | |
996 | } | |
997 | ||
998 | if (sim_bitmap == 0) { | |
999 | for (i = 0; i < (bound/4); i++) { | |
1000 | if (final_candidate[i] != 0xFF) { | |
1001 | for (j = i*4; j < (i+1)*4-2; j++) | |
1002 | resulta[3][j] = resulta[final_candidate[i]][j]; | |
1003 | result = false; | |
1004 | } | |
1005 | } | |
1006 | return result; | |
1007 | } else { | |
1008 | if (!(sim_bitmap & 0x03)) { /* path A TX OK */ | |
1009 | for (i = 0; i < 2; i++) | |
1010 | resulta[3][i] = resulta[c1][i]; | |
1011 | } | |
1012 | if (!(sim_bitmap & 0x0c)) { /* path A RX OK */ | |
1013 | for (i = 2; i < 4; i++) | |
1014 | resulta[3][i] = resulta[c1][i]; | |
1015 | } | |
1016 | ||
1017 | if (!(sim_bitmap & 0x30)) { /* path B TX OK */ | |
1018 | for (i = 4; i < 6; i++) | |
1019 | resulta[3][i] = resulta[c1][i]; | |
1020 | } | |
1021 | ||
1022 | if (!(sim_bitmap & 0xc0)) { /* path B RX OK */ | |
1023 | for (i = 6; i < 8; i++) | |
1024 | resulta[3][i] = resulta[c1][i]; | |
1025 | } | |
1026 | return false; | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], | |
1031 | u8 t, bool is2t) | |
1032 | { | |
1033 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
1034 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
1035 | u32 i; | |
1036 | u8 path_a_ok, path_b_ok; | |
1037 | u32 adda_reg[IQK_ADDA_REG_NUM] = { | |
1038 | rFPGA0_XCD_SwitchControl, rBlue_Tooth, | |
1039 | rRx_Wait_CCA, rTx_CCK_RFON, | |
1040 | rTx_CCK_BBON, rTx_OFDM_RFON, | |
1041 | rTx_OFDM_BBON, rTx_To_Rx, | |
1042 | rTx_To_Tx, rRx_CCK, | |
1043 | rRx_OFDM, rRx_Wait_RIFS, | |
1044 | rRx_TO_Rx, rStandby, | |
1045 | rSleep, rPMPD_ANAEN}; | |
1046 | ||
1047 | u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { | |
1048 | REG_TXPAUSE, REG_BCN_CTRL, | |
1049 | REG_BCN_CTRL_1, REG_GPIO_MUXCFG}; | |
1050 | ||
1051 | /* since 92C & 92D have the different define in IQK_BB_REG */ | |
1052 | u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = { | |
1053 | rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar, | |
1054 | rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB, | |
1055 | rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE, | |
1056 | rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD}; | |
1057 | ||
1058 | u32 retry_count = 9; | |
1059 | if (*(dm_odm->mp_mode) == 1) | |
1060 | retry_count = 9; | |
1061 | else | |
1062 | retry_count = 2; | |
1063 | ||
1064 | if (t == 0) { | |
1065 | ||
1066 | /* Save ADDA parameters, turn Path A ADDA on */ | |
1067 | save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup, | |
1068 | IQK_ADDA_REG_NUM); | |
1069 | save_mac_registers(adapt, iqk_mac_reg, | |
1070 | dm_odm->RFCalibrateInfo.IQK_MAC_backup); | |
1071 | save_adda_registers(adapt, iqk_bb_reg_92c, | |
1072 | dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM); | |
1073 | } | |
1074 | ||
1075 | path_adda_on(adapt, adda_reg, true, is2t); | |
1076 | if (t == 0) | |
1077 | dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, | |
1078 | BIT(8)); | |
1079 | ||
1080 | if (!dm_odm->RFCalibrateInfo.bRfPiEnable) { | |
1081 | /* Switch BB to PI mode to do IQ Calibration. */ | |
1082 | pi_mode_switch(adapt, true); | |
1083 | } | |
1084 | ||
1085 | /* BB setting */ | |
9c68ed09 | 1086 | phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00); |
d9124e06 | 1087 | phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600); |
1088 | phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4); | |
1089 | phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000); | |
1090 | ||
9c68ed09 AB |
1091 | phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01); |
1092 | phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01); | |
1093 | phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00); | |
1094 | phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00); | |
d9124e06 | 1095 | |
1096 | if (is2t) { | |
1097 | phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord, | |
1098 | 0x00010000); | |
1099 | phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord, | |
1100 | 0x00010000); | |
1101 | } | |
1102 | ||
1103 | /* MAC settings */ | |
1104 | mac_setting_calibration(adapt, iqk_mac_reg, | |
1105 | dm_odm->RFCalibrateInfo.IQK_MAC_backup); | |
1106 | ||
1107 | /* Page B init */ | |
1108 | /* AP or IQK */ | |
1109 | phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000); | |
1110 | ||
1111 | if (is2t) | |
1112 | phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000); | |
1113 | ||
1114 | /* IQ calibration setting */ | |
1115 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000); | |
1116 | phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00); | |
1117 | phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800); | |
1118 | ||
1119 | for (i = 0; i < retry_count; i++) { | |
1120 | path_a_ok = phy_path_a_iqk(adapt, is2t); | |
1121 | if (path_a_ok == 0x01) { | |
1122 | result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, | |
1123 | bMaskDWord)&0x3FF0000)>>16; | |
1124 | result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, | |
1125 | bMaskDWord)&0x3FF0000)>>16; | |
1126 | break; | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | for (i = 0; i < retry_count; i++) { | |
1131 | path_a_ok = phy_path_a_rx_iqk(adapt, is2t); | |
1132 | if (path_a_ok == 0x03) { | |
1133 | result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, | |
1134 | bMaskDWord)&0x3FF0000)>>16; | |
1135 | result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, | |
1136 | bMaskDWord)&0x3FF0000)>>16; | |
1137 | break; | |
1138 | } else { | |
1139 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
1140 | ("Path A Rx IQK Fail!!\n")); | |
1141 | } | |
1142 | } | |
1143 | ||
1144 | if (0x00 == path_a_ok) { | |
1145 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
1146 | ("Path A IQK failed!!\n")); | |
1147 | } | |
1148 | ||
1149 | if (is2t) { | |
1150 | path_a_standby(adapt); | |
1151 | ||
1152 | /* Turn Path B ADDA on */ | |
1153 | path_adda_on(adapt, adda_reg, false, is2t); | |
1154 | ||
1155 | for (i = 0; i < retry_count; i++) { | |
1156 | path_b_ok = phy_path_b_iqk(adapt); | |
1157 | if (path_b_ok == 0x03) { | |
1158 | result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, | |
1159 | bMaskDWord)&0x3FF0000)>>16; | |
1160 | result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, | |
1161 | bMaskDWord)&0x3FF0000)>>16; | |
1162 | result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, | |
1163 | bMaskDWord)&0x3FF0000)>>16; | |
1164 | result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, | |
1165 | bMaskDWord)&0x3FF0000)>>16; | |
1166 | break; | |
1167 | } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */ | |
1168 | result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, | |
1169 | bMaskDWord)&0x3FF0000)>>16; | |
1170 | result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, | |
1171 | bMaskDWord)&0x3FF0000)>>16; | |
1172 | } | |
1173 | } | |
1174 | ||
1175 | if (0x00 == path_b_ok) { | |
1176 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
1177 | ("Path B IQK failed!!\n")); | |
1178 | } | |
1179 | } | |
1180 | ||
1181 | /* Back to BB mode, load original value */ | |
1182 | phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0); | |
1183 | ||
1184 | if (t != 0) { | |
1185 | if (!dm_odm->RFCalibrateInfo.bRfPiEnable) { | |
1186 | /* Switch back BB to SI mode after | |
1187 | * finish IQ Calibration. | |
1188 | */ | |
1189 | pi_mode_switch(adapt, false); | |
1190 | } | |
1191 | ||
1192 | /* Reload ADDA power saving parameters */ | |
1193 | reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup, | |
1194 | IQK_ADDA_REG_NUM); | |
1195 | ||
1196 | /* Reload MAC parameters */ | |
1197 | reload_mac_registers(adapt, iqk_mac_reg, | |
1198 | dm_odm->RFCalibrateInfo.IQK_MAC_backup); | |
1199 | ||
1200 | reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup, | |
1201 | IQK_BB_REG_NUM); | |
1202 | ||
1203 | /* Restore RX initial gain */ | |
1204 | phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, | |
1205 | bMaskDWord, 0x00032ed3); | |
1206 | if (is2t) | |
1207 | phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, | |
1208 | bMaskDWord, 0x00032ed3); | |
1209 | ||
1210 | /* load 0xe30 IQC default value */ | |
1211 | phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00); | |
1212 | phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00); | |
1213 | } | |
1214 | } | |
1215 | ||
1216 | static void phy_lc_calibrate(struct adapter *adapt, bool is2t) | |
1217 | { | |
1218 | u8 tmpreg; | |
1219 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | |
1220 | ||
1221 | /* Check continuous TX and Packet TX */ | |
1222 | tmpreg = usb_read8(adapt, 0xd03); | |
1223 | ||
1224 | if ((tmpreg&0x70) != 0) | |
1225 | usb_write8(adapt, 0xd03, tmpreg&0x8F); | |
1226 | else | |
1227 | usb_write8(adapt, REG_TXPAUSE, 0xFF); | |
1228 | ||
1229 | if ((tmpreg&0x70) != 0) { | |
1230 | /* 1. Read original RF mode */ | |
1231 | /* Path-A */ | |
76098bcb | 1232 | rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC, |
d9124e06 | 1233 | bMask12Bits); |
1234 | ||
1235 | /* Path-B */ | |
1236 | if (is2t) | |
76098bcb | 1237 | rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC, |
d9124e06 | 1238 | bMask12Bits); |
1239 | ||
1240 | /* 2. Set RF mode = standby mode */ | |
1241 | /* Path-A */ | |
1242 | phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, | |
1243 | (rf_a_mode&0x8FFFF)|0x10000); | |
1244 | ||
1245 | /* Path-B */ | |
1246 | if (is2t) | |
1247 | phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits, | |
1248 | (rf_b_mode&0x8FFFF)|0x10000); | |
1249 | } | |
1250 | ||
1251 | /* 3. Read RF reg18 */ | |
76098bcb | 1252 | lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits); |
d9124e06 | 1253 | |
1254 | /* 4. Set LC calibration begin bit15 */ | |
1255 | phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits, | |
1256 | lc_cal|0x08000); | |
1257 | ||
1258 | msleep(100); | |
1259 | ||
1260 | /* Restore original situation */ | |
1261 | if ((tmpreg&0x70) != 0) { | |
1262 | /* Deal with continuous TX case */ | |
1263 | /* Path-A */ | |
1264 | usb_write8(adapt, 0xd03, tmpreg); | |
1265 | phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode); | |
1266 | ||
1267 | /* Path-B */ | |
1268 | if (is2t) | |
1269 | phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits, | |
1270 | rf_b_mode); | |
1271 | } else { | |
1272 | /* Deal with Packet TX case */ | |
1273 | usb_write8(adapt, REG_TXPAUSE, 0x00); | |
1274 | } | |
1275 | } | |
1276 | ||
1277 | void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) | |
1278 | { | |
1279 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
1280 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
1281 | s32 result[4][8]; | |
1282 | u8 i, final, chn_index; | |
1283 | bool pathaok, pathbok; | |
9393d34e | 1284 | s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4; |
d9124e06 | 1285 | bool is12simular, is13simular, is23simular; |
1286 | bool singletone = false, carrier_sup = false; | |
1287 | u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = { | |
1288 | rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance, | |
1289 | rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable, | |
1290 | rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance, | |
1291 | rOFDM0_XCTxAFE, rOFDM0_XDTxAFE, | |
1292 | rOFDM0_RxIQExtAnta}; | |
1293 | bool is2t; | |
1294 | ||
1295 | is2t = (dm_odm->RFType == ODM_2T2R) ? true : false; | |
1296 | ||
1297 | if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) | |
1298 | return; | |
1299 | ||
1300 | if (singletone || carrier_sup) | |
1301 | return; | |
1302 | ||
1303 | if (recovery) { | |
1304 | ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, | |
1305 | ("phy_iq_calibrate: Return due to recovery!\n")); | |
1306 | reload_adda_reg(adapt, iqk_bb_reg_92c, | |
1307 | dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); | |
1308 | return; | |
1309 | } | |
1310 | ||
1311 | for (i = 0; i < 8; i++) { | |
1312 | result[0][i] = 0; | |
1313 | result[1][i] = 0; | |
1314 | result[2][i] = 0; | |
1315 | if ((i == 0) || (i == 2) || (i == 4) || (i == 6)) | |
1316 | result[3][i] = 0x100; | |
1317 | else | |
1318 | result[3][i] = 0; | |
1319 | } | |
1320 | final = 0xff; | |
1321 | pathaok = false; | |
1322 | pathbok = false; | |
1323 | is12simular = false; | |
1324 | is23simular = false; | |
1325 | is13simular = false; | |
1326 | ||
1327 | for (i = 0; i < 3; i++) { | |
1328 | phy_iq_calibrate(adapt, result, i, is2t); | |
1329 | ||
1330 | if (i == 1) { | |
1331 | is12simular = simularity_compare(adapt, result, 0, 1); | |
1332 | if (is12simular) { | |
1333 | final = 0; | |
1334 | break; | |
1335 | } | |
1336 | } | |
1337 | ||
1338 | if (i == 2) { | |
1339 | is13simular = simularity_compare(adapt, result, 0, 2); | |
1340 | if (is13simular) { | |
1341 | final = 0; | |
1342 | break; | |
1343 | } | |
1344 | is23simular = simularity_compare(adapt, result, 1, 2); | |
1345 | if (is23simular) | |
1346 | final = 1; | |
1347 | else | |
1348 | final = 3; | |
1349 | } | |
1350 | } | |
1351 | ||
1352 | for (i = 0; i < 4; i++) { | |
1353 | reg_e94 = result[i][0]; | |
1354 | reg_e9c = result[i][1]; | |
1355 | reg_ea4 = result[i][2]; | |
d9124e06 | 1356 | reg_eb4 = result[i][4]; |
1357 | reg_ebc = result[i][5]; | |
1358 | reg_ec4 = result[i][6]; | |
d9124e06 | 1359 | } |
1360 | ||
1361 | if (final != 0xff) { | |
1362 | reg_e94 = result[final][0]; | |
1363 | reg_e9c = result[final][1]; | |
1364 | reg_ea4 = result[final][2]; | |
d9124e06 | 1365 | reg_eb4 = result[final][4]; |
1366 | reg_ebc = result[final][5]; | |
1367 | dm_odm->RFCalibrateInfo.RegE94 = reg_e94; | |
1368 | dm_odm->RFCalibrateInfo.RegE9C = reg_e9c; | |
1369 | dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4; | |
1370 | dm_odm->RFCalibrateInfo.RegEBC = reg_ebc; | |
1371 | reg_ec4 = result[final][6]; | |
d9124e06 | 1372 | pathaok = true; |
1373 | pathbok = true; | |
1374 | } else { | |
1375 | ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, | |
1376 | ("IQK: FAIL use default value\n")); | |
1377 | dm_odm->RFCalibrateInfo.RegE94 = 0x100; | |
1378 | dm_odm->RFCalibrateInfo.RegEB4 = 0x100; | |
1379 | dm_odm->RFCalibrateInfo.RegE9C = 0x0; | |
1380 | dm_odm->RFCalibrateInfo.RegEBC = 0x0; | |
1381 | } | |
1382 | if (reg_e94 != 0) | |
1383 | patha_fill_iqk(adapt, pathaok, result, final, | |
1384 | (reg_ea4 == 0)); | |
1385 | if (is2t) { | |
1386 | if (reg_eb4 != 0) | |
1387 | pathb_fill_iqk(adapt, pathbok, result, final, | |
1388 | (reg_ec4 == 0)); | |
1389 | } | |
1390 | ||
1391 | chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel); | |
1392 | ||
1393 | if (final < 4) { | |
1394 | for (i = 0; i < IQK_Matrix_REG_NUM; i++) | |
1395 | dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i]; | |
1396 | dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true; | |
1397 | } | |
1398 | ||
1399 | save_adda_registers(adapt, iqk_bb_reg_92c, | |
1400 | dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); | |
1401 | } | |
1402 | ||
1403 | void rtl88eu_phy_lc_calibrate(struct adapter *adapt) | |
1404 | { | |
1405 | bool singletone = false, carrier_sup = false; | |
1406 | u32 timeout = 2000, timecount = 0; | |
1407 | struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); | |
1408 | struct odm_dm_struct *dm_odm = &hal_data->odmpriv; | |
1409 | ||
1410 | if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) | |
1411 | return; | |
1412 | if (singletone || carrier_sup) | |
1413 | return; | |
1414 | ||
1415 | while (*(dm_odm->pbScanInProcess) && timecount < timeout) { | |
1416 | mdelay(50); | |
1417 | timecount += 50; | |
1418 | } | |
1419 | ||
1420 | dm_odm->RFCalibrateInfo.bLCKInProgress = true; | |
1421 | ||
1422 | if (dm_odm->RFType == ODM_2T2R) { | |
1423 | phy_lc_calibrate(adapt, true); | |
1424 | } else { | |
1425 | /* For 88C 1T1R */ | |
1426 | phy_lc_calibrate(adapt, false); | |
1427 | } | |
1428 | ||
1429 | dm_odm->RFCalibrateInfo.bLCKInProgress = false; | |
1430 | } |