blob: a83bbea9be93b8e3a2c2b5faa5e3e9b7f3931cc6 [file] [log] [blame]
Larry Finger615a4d12013-08-21 22:33:56 -05001/******************************************************************************
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 *
Larry Finger615a4d12013-08-21 22:33:56 -050014 ******************************************************************************/
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>
navin patidar20273242014-08-31 14:08:21 +053021#include <rf.h>
Nicolas Theryf60705f2014-09-06 07:18:47 +020022#include <phy.h>
Larry Finger615a4d12013-08-21 22:33:56 -050023
Larry Finger615a4d12013-08-21 22:33:56 -050024#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
navin patidar6e264fe2014-08-23 19:48:22 +053030static u32 cal_bit_shift(u32 bitmask)
Larry Finger615a4d12013-08-21 22:33:56 -050031{
32 u32 i;
33
34 for (i = 0; i <= 31; i++) {
navin patidar6e264fe2014-08-23 19:48:22 +053035 if (((bitmask >> i) & 0x1) == 1)
Larry Finger615a4d12013-08-21 22:33:56 -050036 break;
37 }
38 return i;
39}
40
navin patidarecd1f9b2014-08-31 12:14:17 +053041u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
Larry Finger615a4d12013-08-21 22:33:56 -050042{
navin patidarecd1f9b2014-08-31 12:14:17 +053043 u32 return_value = 0, original_value, bit_shift;
Larry Finger615a4d12013-08-21 22:33:56 -050044
navin patidarecd1f9b2014-08-31 12:14:17 +053045 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;
Larry Finger615a4d12013-08-21 22:33:56 -050049}
50
navin patidar9c6db652014-08-31 12:14:19 +053051void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
Larry Finger615a4d12013-08-21 22:33:56 -050052{
navin patidar9c6db652014-08-31 12:14:19 +053053 u32 original_value, bit_shift;
Larry Finger615a4d12013-08-21 22:33:56 -050054
navin patidar9c6db652014-08-31 12:14:19 +053055 if (bitmask != bMaskDWord) { /* if not "double word" write */
56 original_value = usb_read32(adapt, regaddr);
57 bit_shift = cal_bit_shift(bitmask);
Haneen Mohammedadb3d772015-03-13 19:55:55 +030058 data = (original_value & (~bitmask)) | (data << bit_shift);
Larry Finger615a4d12013-08-21 22:33:56 -050059 }
60
navin patidar9c6db652014-08-31 12:14:19 +053061 usb_write32(adapt, regaddr, data);
Larry Finger615a4d12013-08-21 22:33:56 -050062}
63
navin patidara35b7472014-08-31 12:14:20 +053064static u32 rf_serial_read(struct adapter *adapt,
65 enum rf_radio_path rfpath, u32 offset)
Larry Finger615a4d12013-08-21 22:33:56 -050066{
navin patidara35b7472014-08-31 12:14:20 +053067 u32 ret = 0;
68 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
69 struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
Larry Finger615a4d12013-08-21 22:33:56 -050070 u32 tmplong, tmplong2;
navin patidara35b7472014-08-31 12:14:20 +053071 u8 rfpi_enable = 0;
Larry Finger615a4d12013-08-21 22:33:56 -050072
navin patidara35b7472014-08-31 12:14:20 +053073 offset &= 0xff;
Larry Finger615a4d12013-08-21 22:33:56 -050074
navin patidara35b7472014-08-31 12:14:20 +053075 tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
76 if (rfpath == RF_PATH_A)
Larry Finger615a4d12013-08-21 22:33:56 -050077 tmplong2 = tmplong;
78 else
navin patidara35b7472014-08-31 12:14:20 +053079 tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
80 bMaskDWord);
Larry Finger615a4d12013-08-21 22:33:56 -050081
navin patidara35b7472014-08-31 12:14:20 +053082 tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
Vatika Harlalka9734d632015-02-23 14:20:30 +053083 (offset<<23) | bLSSIReadEdge;
Larry Finger615a4d12013-08-21 22:33:56 -050084
navin patidara35b7472014-08-31 12:14:20 +053085 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
86 tmplong&(~bLSSIReadEdge));
87 udelay(10);
Larry Finger615a4d12013-08-21 22:33:56 -050088
navin patidara35b7472014-08-31 12:14:20 +053089 phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
90 udelay(100);
Larry Finger615a4d12013-08-21 22:33:56 -050091
navin patidara35b7472014-08-31 12:14:20 +053092 udelay(10);
Larry Finger615a4d12013-08-21 22:33:56 -050093
navin patidara35b7472014-08-31 12:14:20 +053094 if (rfpath == RF_PATH_A)
Anish Bhatt9c68ed02015-10-18 22:51:41 -070095 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
navin patidara35b7472014-08-31 12:14:20 +053096 else if (rfpath == RF_PATH_B)
Anish Bhatt9c68ed02015-10-18 22:51:41 -070097 rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
Larry Finger615a4d12013-08-21 22:33:56 -050098
navin patidara35b7472014-08-31 12:14:20 +053099 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;
Larry Finger615a4d12013-08-21 22:33:56 -0500106}
107
navin patidar42f27152014-08-31 12:14:21 +0530108static void rf_serial_write(struct adapter *adapt,
109 enum rf_radio_path rfpath, u32 offset,
110 u32 data)
Larry Finger615a4d12013-08-21 22:33:56 -0500111{
navin patidar42f27152014-08-31 12:14:21 +0530112 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];
Larry Finger615a4d12013-08-21 22:33:56 -0500115
Vatika Harlalka065be692015-02-23 14:46:13 +0530116 offset &= 0xff;
117 data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
navin patidar42f27152014-08-31 12:14:21 +0530118 phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
Larry Finger615a4d12013-08-21 22:33:56 -0500119}
120
navin patidar41b77d22014-08-31 12:14:22 +0530121u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
122 u32 reg_addr, u32 bit_mask)
Larry Finger615a4d12013-08-21 22:33:56 -0500123{
navin patidar41b77d22014-08-31 12:14:22 +0530124 u32 original_value, readback_value, bit_shift;
Larry Finger615a4d12013-08-21 22:33:56 -0500125
navin patidar41b77d22014-08-31 12:14:22 +0530126 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;
Larry Finger615a4d12013-08-21 22:33:56 -0500130}
131
navin patidar7b984852014-08-31 12:14:23 +0530132void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
133 u32 reg_addr, u32 bit_mask, u32 data)
Larry Finger615a4d12013-08-21 22:33:56 -0500134{
navin patidar7b984852014-08-31 12:14:23 +0530135 u32 original_value, bit_shift;
Larry Finger615a4d12013-08-21 22:33:56 -0500136
137 /* RF data is 12 bits only */
navin patidar7b984852014-08-31 12:14:23 +0530138 if (bit_mask != bRFRegOffsetMask) {
139 original_value = rf_serial_read(adapt, rf_path, reg_addr);
140 bit_shift = cal_bit_shift(bit_mask);
Haneen Mohammedadb3d772015-03-13 19:55:55 +0300141 data = (original_value & (~bit_mask)) | (data << bit_shift);
Larry Finger615a4d12013-08-21 22:33:56 -0500142 }
143
navin patidar7b984852014-08-31 12:14:23 +0530144 rf_serial_write(adapt, rf_path, reg_addr, data);
Larry Finger615a4d12013-08-21 22:33:56 -0500145}
146
navin patidar88cbb392014-08-31 12:14:24 +0530147static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
148 u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
Larry Finger615a4d12013-08-21 22:33:56 -0500149{
navin patidar88cbb392014-08-31 12:14:24 +0530150 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
Larry Finger615a4d12013-08-21 22:33:56 -0500151 u8 index = (channel - 1);
152 u8 TxCount = 0, path_nums;
153
navin patidar88cbb392014-08-31 12:14:24 +0530154 if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type))
Larry Finger615a4d12013-08-21 22:33:56 -0500155 path_nums = 1;
156 else
157 path_nums = 2;
158
159 for (TxCount = 0; TxCount < path_nums; TxCount++) {
160 if (TxCount == RF_PATH_A) {
navin patidar88cbb392014-08-31 12:14:24 +0530161 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];
Larry Finger615a4d12013-08-21 22:33:56 -0500168 } else if (TxCount == RF_PATH_B) {
navin patidar88cbb392014-08-31 12:14:24 +0530169 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];
Larry Finger615a4d12013-08-21 22:33:56 -0500178 }
179 }
180}
181
navin patidara8b74c32014-08-31 12:14:25 +0530182static void phy_power_index_check(struct adapter *adapt, u8 channel,
183 u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
184 u8 *bw40_pwr)
Larry Finger615a4d12013-08-21 22:33:56 -0500185{
navin patidara8b74c32014-08-31 12:14:25 +0530186 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
Larry Finger615a4d12013-08-21 22:33:56 -0500187
navin patidara8b74c32014-08-31 12:14:25 +0530188 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];
Larry Finger615a4d12013-08-21 22:33:56 -0500192}
193
navin patidar01c5f832014-08-31 12:14:28 +0530194void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
Larry Finger615a4d12013-08-21 22:33:56 -0500195{
navin patidar01c5f832014-08-31 12:14:28 +0530196 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};
Larry Finger615a4d12013-08-21 22:33:56 -0500200
navin patidar01c5f832014-08-31 12:14:28 +0530201 get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
202 &bw20_pwr[0], &bw40_pwr[0]);
Larry Finger615a4d12013-08-21 22:33:56 -0500203
navin patidar01c5f832014-08-31 12:14:28 +0530204 phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
205 &bw20_pwr[0], &bw40_pwr[0]);
Larry Finger615a4d12013-08-21 22:33:56 -0500206
navin patidarc5db81ac2014-08-31 14:08:22 +0530207 rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
navin patidarfb393d22014-08-31 14:08:24 +0530208 rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
navin patidar01c5f832014-08-31 12:14:28 +0530209 &bw40_pwr[0], channel);
Larry Finger615a4d12013-08-21 22:33:56 -0500210}
211
navin patidar55d8dfb2014-08-31 12:14:26 +0530212static void phy_set_bw_mode_callback(struct adapter *adapt)
Larry Finger615a4d12013-08-21 22:33:56 -0500213{
navin patidar55d8dfb2014-08-31 12:14:26 +0530214 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
215 u8 reg_bw_opmode;
216 u8 reg_prsr_rsc;
Larry Finger615a4d12013-08-21 22:33:56 -0500217
navin patidar55d8dfb2014-08-31 12:14:26 +0530218 if (hal_data->rf_chip == RF_PSEUDO_11N)
Larry Finger615a4d12013-08-21 22:33:56 -0500219 return;
220
221 /* There is no 40MHz mode in RF_8225. */
navin patidar55d8dfb2014-08-31 12:14:26 +0530222 if (hal_data->rf_chip == RF_8225)
Larry Finger615a4d12013-08-21 22:33:56 -0500223 return;
224
navin patidar55d8dfb2014-08-31 12:14:26 +0530225 if (adapt->bDriverStopped)
Larry Finger615a4d12013-08-21 22:33:56 -0500226 return;
227
navin patidar55d8dfb2014-08-31 12:14:26 +0530228 /* Set MAC register */
Larry Finger615a4d12013-08-21 22:33:56 -0500229
navin patidar55d8dfb2014-08-31 12:14:26 +0530230 reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
231 reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
Larry Finger615a4d12013-08-21 22:33:56 -0500232
navin patidar55d8dfb2014-08-31 12:14:26 +0530233 switch (hal_data->CurrentChannelBW) {
Larry Finger615a4d12013-08-21 22:33:56 -0500234 case HT_CHANNEL_WIDTH_20:
navin patidar55d8dfb2014-08-31 12:14:26 +0530235 reg_bw_opmode |= BW_OPMODE_20MHZ;
236 usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
Larry Finger615a4d12013-08-21 22:33:56 -0500237 break;
238 case HT_CHANNEL_WIDTH_40:
navin patidar55d8dfb2014-08-31 12:14:26 +0530239 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);
Larry Finger615a4d12013-08-21 22:33:56 -0500244 break;
245 default:
246 break;
247 }
248
navin patidar55d8dfb2014-08-31 12:14:26 +0530249 /* Set PHY related register */
250 switch (hal_data->CurrentChannelBW) {
Larry Finger615a4d12013-08-21 22:33:56 -0500251 case HT_CHANNEL_WIDTH_20:
navin patidar55d8dfb2014-08-31 12:14:26 +0530252 phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
253 phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
Larry Finger615a4d12013-08-21 22:33:56 -0500254 break;
Larry Finger615a4d12013-08-21 22:33:56 -0500255 case HT_CHANNEL_WIDTH_40:
navin patidar55d8dfb2014-08-31 12:14:26 +0530256 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);
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700265 phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
navin patidar55d8dfb2014-08-31 12:14:26 +0530266 (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
Larry Finger615a4d12013-08-21 22:33:56 -0500267 break;
268 default:
269 break;
270 }
Larry Finger615a4d12013-08-21 22:33:56 -0500271
navin patidar55d8dfb2014-08-31 12:14:26 +0530272 /* Set RF related register */
Vatika Harlalkaefb8d492015-02-23 14:41:07 +0530273 if (hal_data->rf_chip == RF_6052)
navin patidar20273242014-08-31 14:08:21 +0530274 rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
Larry Finger615a4d12013-08-21 22:33:56 -0500275}
276
navin patidar5f6a5cd2014-08-31 12:14:29 +0530277void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth,
278 unsigned char offset)
Larry Finger615a4d12013-08-21 22:33:56 -0500279{
navin patidar5f6a5cd2014-08-31 12:14:29 +0530280 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
281 enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
Larry Finger615a4d12013-08-21 22:33:56 -0500282
navin patidar5f6a5cd2014-08-31 12:14:29 +0530283 hal_data->CurrentChannelBW = bandwidth;
284 hal_data->nCur40MhzPrimeSC = offset;
Larry Finger615a4d12013-08-21 22:33:56 -0500285
navin patidar5f6a5cd2014-08-31 12:14:29 +0530286 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
287 phy_set_bw_mode_callback(adapt);
Larry Finger615a4d12013-08-21 22:33:56 -0500288 else
navin patidar5f6a5cd2014-08-31 12:14:29 +0530289 hal_data->CurrentChannelBW = tmp_bw;
Larry Finger615a4d12013-08-21 22:33:56 -0500290}
291
navin patidar9c431942014-08-31 12:14:27 +0530292static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
Larry Finger615a4d12013-08-21 22:33:56 -0500293{
navin patidar9c431942014-08-31 12:14:27 +0530294 u8 rf_path;
Larry Finger615a4d12013-08-21 22:33:56 -0500295 u32 param1, param2;
navin patidar9c431942014-08-31 12:14:27 +0530296 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
Larry Finger615a4d12013-08-21 22:33:56 -0500297
navin patidar9c431942014-08-31 12:14:27 +0530298 if (adapt->bNotifyChannelChange)
Larry Finger615a4d12013-08-21 22:33:56 -0500299 DBG_88E("[%s] ch = %d\n", __func__, channel);
300
navin patidar01c5f832014-08-31 12:14:28 +0530301 phy_set_tx_power_level(adapt, channel);
Larry Finger615a4d12013-08-21 22:33:56 -0500302
Larry Finger615a4d12013-08-21 22:33:56 -0500303 param1 = RF_CHNLBW;
304 param2 = channel;
navin patidar9c431942014-08-31 12:14:27 +0530305 for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) {
306 hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] &
307 0xfffffc00) | param2;
308 phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1,
309 bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]);
Larry Finger615a4d12013-08-21 22:33:56 -0500310 }
311}
312
navin patidarba50fbc2014-08-31 12:14:30 +0530313void phy_sw_chnl(struct adapter *adapt, u8 channel)
Larry Finger615a4d12013-08-21 22:33:56 -0500314{
navin patidarba50fbc2014-08-31 12:14:30 +0530315 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
316 u8 tmpchannel = hal_data->CurrentChannel;
Larry Finger615a4d12013-08-21 22:33:56 -0500317
navin patidarba50fbc2014-08-31 12:14:30 +0530318 if (hal_data->rf_chip == RF_PSEUDO_11N)
319 return;
Larry Finger615a4d12013-08-21 22:33:56 -0500320
321 if (channel == 0)
322 channel = 1;
323
navin patidarba50fbc2014-08-31 12:14:30 +0530324 hal_data->CurrentChannel = channel;
Larry Finger615a4d12013-08-21 22:33:56 -0500325
Vatika Harlalka8e2c69b2015-02-26 18:31:52 +0530326 if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
navin patidarba50fbc2014-08-31 12:14:30 +0530327 phy_sw_chnl_callback(adapt, channel);
Vatika Harlalka8e2c69b2015-02-26 18:31:52 +0530328 else
navin patidarba50fbc2014-08-31 12:14:30 +0530329 hal_data->CurrentChannel = tmpchannel;
Larry Finger615a4d12013-08-21 22:33:56 -0500330}
navin patidard9124e02014-09-07 16:38:04 +0530331
332#define ODM_TXPWRTRACK_MAX_IDX_88E 6
333
334static u8 get_right_chnl_for_iqk(u8 chnl)
335{
Vatika Harlalka93ab4862015-02-23 19:32:38 +0530336 u8 place;
navin patidard9124e02014-09-07 16:38:04 +0530337 u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
navin patidard9124e02014-09-07 16:38:04 +0530338 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
339 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
340 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
341 155, 157, 159, 161, 163, 165
342 };
navin patidard9124e02014-09-07 16:38:04 +0530343
344 if (chnl > 14) {
Vatika Harlalka93ab4862015-02-23 19:32:38 +0530345 for (place = 0; place < sizeof(channel_all); place++) {
navin patidard9124e02014-09-07 16:38:04 +0530346 if (channel_all[place] == chnl)
Vatika Harlalka93ab4862015-02-23 19:32:38 +0530347 return ++place;
navin patidard9124e02014-09-07 16:38:04 +0530348 }
349 }
350 return 0;
351}
352
353void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
354 u8 *direction, u32 *out_write_val)
355{
356 u8 pwr_value = 0;
357 /* Tx power tracking BB swing table. */
358 if (type == 0) { /* For OFDM adjust */
359 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
360 ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
361 dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
362
363 if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
364 *direction = 1;
Haneen Mohammedadb3d772015-03-13 19:55:55 +0300365 pwr_value = dm_odm->BbSwingIdxOfdmBase -
366 dm_odm->BbSwingIdxOfdm;
navin patidard9124e02014-09-07 16:38:04 +0530367 } else {
368 *direction = 2;
Haneen Mohammedadb3d772015-03-13 19:55:55 +0300369 pwr_value = dm_odm->BbSwingIdxOfdm -
370 dm_odm->BbSwingIdxOfdmBase;
navin patidard9124e02014-09-07 16:38:04 +0530371 }
372
373 } else if (type == 1) { /* For CCK adjust. */
374 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
375 ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
376 dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
377
378 if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
379 *direction = 1;
Haneen Mohammedadb3d772015-03-13 19:55:55 +0300380 pwr_value = dm_odm->BbSwingIdxCckBase -
381 dm_odm->BbSwingIdxCck;
navin patidard9124e02014-09-07 16:38:04 +0530382 } else {
383 *direction = 2;
Haneen Mohammedadb3d772015-03-13 19:55:55 +0300384 pwr_value = dm_odm->BbSwingIdxCck -
385 dm_odm->BbSwingIdxCckBase;
navin patidard9124e02014-09-07 16:38:04 +0530386 }
387
388 }
389
390 if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
391 pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
392
393 *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
394 (pwr_value<<24);
395}
396
397static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
398{
399 if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
400 ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
401 ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
402 phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
403 dm_odm->BbSwingFlagOfdm = false;
404 dm_odm->BbSwingFlagCck = false;
405 }
406}
407
408void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
409{
410 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
411 u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
412 u8 thermal_avg_count = 0;
413 u32 thermal_avg = 0;
Vatika Harlalka0395e552015-02-27 02:12:10 +0530414 s32 ele_d, temp_cck;
navin patidard9124e02014-09-07 16:38:04 +0530415 s8 ofdm_index[2], cck_index = 0;
416 s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
417 u32 i = 0, j = 0;
418 bool is2t = false;
419
420 u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */
navin patidard9124e02014-09-07 16:38:04 +0530421 s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
422 /* 2.4G, decrease power */
423 {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
424 /* 2.4G, increase power */
Jia He7be921a22014-11-04 09:39:58 +0800425 {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
navin patidard9124e02014-09-07 16:38:04 +0530426 };
427 u8 thermal_mapping[2][index_mapping_NUM_88E] = {
428 /* 2.4G, decrease power */
429 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
430 /* 2.4G, increase power */
431 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
432 };
433 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
434
435 dm_txpwr_track_setpwr(dm_odm);
436
437 dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
438 dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
439
440 dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
441
442 thermal_val = (u8)phy_query_rf_reg(adapt, RF_PATH_A,
443 RF_T_METER_88E, 0xfc00);
444
445 if (is2t)
446 rf = 2;
447 else
448 rf = 1;
449
450 if (thermal_val) {
451 /* Query OFDM path A default setting */
452 ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
453 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
454 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
455 ofdm_index_old[0] = (u8)i;
456 dm_odm->BbSwingIdxOfdmBase = (u8)i;
457 break;
458 }
459 }
460
461 /* Query OFDM path B default setting */
462 if (is2t) {
463 ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D;
464 for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
465 if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
466 ofdm_index_old[1] = (u8)i;
467 break;
468 }
469 }
470 }
471
472 /* Query CCK default setting From 0xa24 */
473 temp_cck = dm_odm->RFCalibrateInfo.RegA24;
474
475 for (i = 0; i < CCK_TABLE_SIZE; i++) {
Vatika Harlalka294a7fc2015-02-26 23:05:11 +0530476 if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
477 memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
478 memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
navin patidard9124e02014-09-07 16:38:04 +0530479 cck_index_old = (u8)i;
480 dm_odm->BbSwingIdxCckBase = (u8)i;
481 break;
navin patidard9124e02014-09-07 16:38:04 +0530482 }
483 }
484
485 if (!dm_odm->RFCalibrateInfo.ThermalValue) {
486 dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
487 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
488 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
489
490 for (i = 0; i < rf; i++)
491 dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i];
492 dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
493 }
494
495 /* calculate average thermal meter */
496 dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
497 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
498 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
499 dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
500
501 for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
502 if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
503 thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
504 thermal_avg_count++;
505 }
506 }
507
508 if (thermal_avg_count)
509 thermal_val = (u8)(thermal_avg / thermal_avg_count);
510
Vatika Harlalka4c3fa642015-02-23 23:40:27 +0530511 if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
512 !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
513 delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
514 else {
515 delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
516 if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
517 dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
518 dm_odm->RFCalibrateInfo.bDoneTxpower = false;
519 }
navin patidard9124e02014-09-07 16:38:04 +0530520 }
Vatika Harlalka4c3fa642015-02-23 23:40:27 +0530521
522 delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
523 delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
navin patidard9124e02014-09-07 16:38:04 +0530524
525 /* Delta temperature is equal to or larger than 20 centigrade.*/
526 if ((delta_lck >= 8)) {
527 dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
528 rtl88eu_phy_lc_calibrate(adapt);
529 }
530
531 if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
Vatika Harlalkad5dd06e2015-02-24 00:06:14 +0530532 delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
533
navin patidard9124e02014-09-07 16:38:04 +0530534 /* calculate new OFDM / CCK offset */
535 if (thermal_val > hal_data->EEPROMThermalMeter)
536 j = 1;
537 else
538 j = 0;
539 for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
540 if (delta < thermal_mapping[j][offset]) {
541 if (offset != 0)
542 offset--;
543 break;
544 }
545 }
546 if (offset >= index_mapping_NUM_88E)
547 offset = index_mapping_NUM_88E-1;
navin patidard9124e02014-09-07 16:38:04 +0530548
Vatika Harlalka4ceb7f72015-02-26 23:47:39 +0530549 /* Updating ofdm_index values with new OFDM / CCK offset */
navin patidard9124e02014-09-07 16:38:04 +0530550 for (i = 0; i < rf; i++) {
Vatika Harlalka4ceb7f72015-02-26 23:47:39 +0530551 ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
navin patidard9124e02014-09-07 16:38:04 +0530552 if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1)
553 ofdm_index[i] = OFDM_TABLE_SIZE_92D-1;
554 else if (ofdm_index[i] < ofdm_min_index)
555 ofdm_index[i] = ofdm_min_index;
556 }
557
Vatika Harlalka4ceb7f72015-02-26 23:47:39 +0530558 cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
navin patidard9124e02014-09-07 16:38:04 +0530559 if (cck_index > CCK_TABLE_SIZE-1)
560 cck_index = CCK_TABLE_SIZE-1;
561 else if (cck_index < 0)
562 cck_index = 0;
563
564 /* 2 temporarily remove bNOPG */
565 /* Config by SwingTable */
566 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
567 dm_odm->RFCalibrateInfo.bDoneTxpower = true;
568
navin patidard9124e02014-09-07 16:38:04 +0530569 /* Revse TX power table. */
570 dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
571 dm_odm->BbSwingIdxCck = (u8)cck_index;
572
573 if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
574 dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
575 dm_odm->BbSwingFlagOfdm = true;
576 }
577
578 if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
579 dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
580 dm_odm->BbSwingFlagCck = true;
581 }
navin patidard9124e02014-09-07 16:38:04 +0530582 }
583 }
584
585 /* Delta temperature is equal to or larger than 20 centigrade.*/
586 if (delta_iqk >= 8) {
587 dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
588 rtl88eu_phy_iq_calibrate(adapt, false);
589 }
590 /* update thermal meter value */
591 if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
592 dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
593 }
594 dm_odm->RFCalibrateInfo.TXPowercount = 0;
595}
596
597#define MAX_TOLERANCE 5
598
599static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
600{
Sudip Mukherjee9393d342015-06-12 16:20:42 +0530601 u32 reg_eac, reg_e94, reg_e9c;
navin patidard9124e02014-09-07 16:38:04 +0530602 u8 result = 0x00;
603
604 /* 1 Tx IQK */
605 /* path-A IQK setting */
606 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
607 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
608 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
609 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
610
611 /* LO calibration setting */
612 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
613
614 /* One shot, path A LOK & IQK */
615 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
616 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
617
618 mdelay(IQK_DELAY_TIME_88E);
619
620 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
621 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
622 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
navin patidard9124e02014-09-07 16:38:04 +0530623
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700624 if (!(reg_eac & BIT(28)) &&
navin patidard9124e02014-09-07 16:38:04 +0530625 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
626 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
627 result |= 0x01;
628 return result;
629}
630
631static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
632{
633 u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
634 u8 result = 0x00;
635 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
636 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
637
638 /* 1 Get TXIMR setting */
639 /* modify RXIQK mode table */
640 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
641 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
642 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
643 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
644 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
645
646 /* PA,PAD off */
647 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
648 phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
649
650 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
651
652 /* IQK setting */
653 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
654 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
655
656 /* path-A IQK setting */
657 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
658 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
659 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
660 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
661
662 /* LO calibration setting */
663 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
664
665 /* One shot, path A LOK & IQK */
666 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
667 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
668
669 /* delay x ms */
670 mdelay(IQK_DELAY_TIME_88E);
671
672 /* Check failed */
673 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
674 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
675 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
676
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700677 if (!(reg_eac & BIT(28)) &&
navin patidard9124e02014-09-07 16:38:04 +0530678 (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
679 (((reg_e9c & 0x03FF0000)>>16) != 0x42))
680 result |= 0x01;
681 else /* if Tx not OK, ignore Rx */
682 return result;
683
684 u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16);
685 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
686
687 /* 1 RX IQK */
688 /* modify RXIQK mode table */
689 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
690 ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
691 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
692 phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
693 phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
694 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
695 phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
696 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
697
698 /* IQK setting */
699 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
700
701 /* path-A IQK setting */
702 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
703 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
704 phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
705 phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
706
707 /* LO calibration setting */
708 phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
709
710 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
711 phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
712
713 mdelay(IQK_DELAY_TIME_88E);
714
715 /* Check failed */
716 reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
717 reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
718 reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
719 reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
720
721 /* reload RF 0xdf */
722 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
723 phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
724
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700725 if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
navin patidard9124e02014-09-07 16:38:04 +0530726 (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
727 (((reg_eac & 0x03FF0000)>>16) != 0x36))
728 result |= 0x02;
729 else
730 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
731 ("Path A Rx IQK fail!!\n"));
732
733 return result;
734}
735
736static u8 phy_path_b_iqk(struct adapter *adapt)
737{
738 u32 regeac, regeb4, regebc, regec4, regecc;
739 u8 result = 0x00;
740 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
741 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
742
743 /* One shot, path B LOK & IQK */
744 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
745 phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
746
747 mdelay(IQK_DELAY_TIME_88E);
748
749 regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
750 regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
751 regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
752 regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
753 regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
754
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700755 if (!(regeac & BIT(31)) &&
navin patidard9124e02014-09-07 16:38:04 +0530756 (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
757 (((regebc & 0x03FF0000)>>16) != 0x42))
758 result |= 0x01;
759 else
760 return result;
761
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700762 if (!(regeac & BIT(30)) &&
navin patidard9124e02014-09-07 16:38:04 +0530763 (((regec4 & 0x03FF0000)>>16) != 0x132) &&
764 (((regecc & 0x03FF0000)>>16) != 0x36))
765 result |= 0x02;
766 else
767 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
768 ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n"));
769 return result;
770}
771
772static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
773 u8 final_candidate, bool txonly)
774{
775 u32 oldval_0, x, tx0_a, reg;
776 s32 y, tx0_c;
777
778 if (final_candidate == 0xFF) {
779 return;
780 } else if (iqkok) {
781 oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
782
783 x = result[final_candidate][0];
784 if ((x & 0x00000200) != 0)
785 x = x | 0xFFFFFC00;
786
787 tx0_a = (x * oldval_0) >> 8;
788 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
789 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
790 ((x * oldval_0>>7) & 0x1));
791
792 y = result[final_candidate][1];
793 if ((y & 0x00000200) != 0)
794 y = y | 0xFFFFFC00;
795
796 tx0_c = (y * oldval_0) >> 8;
797 phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
798 ((tx0_c&0x3C0)>>6));
799 phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
800 (tx0_c&0x3F));
801 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
802 ((y * oldval_0>>7) & 0x1));
803
804 if (txonly)
805 return;
806
807 reg = result[final_candidate][2];
808 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
809
810 reg = result[final_candidate][3] & 0x3F;
811 phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
812
813 reg = (result[final_candidate][3] >> 6) & 0xF;
814 phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
815 }
816}
817
818static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
819 u8 final_candidate, bool txonly)
820{
821 u32 oldval_1, x, tx1_a, reg;
822 s32 y, tx1_c;
823
824 if (final_candidate == 0xFF) {
825 return;
826 } else if (iqkok) {
827 oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
828
829 x = result[final_candidate][4];
830 if ((x & 0x00000200) != 0)
831 x = x | 0xFFFFFC00;
832 tx1_a = (x * oldval_1) >> 8;
833 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
834
835 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
836 ((x * oldval_1>>7) & 0x1));
837
838 y = result[final_candidate][5];
839 if ((y & 0x00000200) != 0)
840 y = y | 0xFFFFFC00;
841
842 tx1_c = (y * oldval_1) >> 8;
843
844 phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
845 ((tx1_c&0x3C0)>>6));
846 phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
847 (tx1_c&0x3F));
848 phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
849 ((y * oldval_1>>7) & 0x1));
850
851 if (txonly)
852 return;
853
854 reg = result[final_candidate][6];
855 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
856
857 reg = result[final_candidate][7] & 0x3F;
858 phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
859
860 reg = (result[final_candidate][7] >> 6) & 0xF;
861 phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
862 }
863}
864
865static void save_adda_registers(struct adapter *adapt, u32 *addareg,
866 u32 *backup, u32 register_num)
867{
868 u32 i;
869
870 for (i = 0; i < register_num; i++) {
871 backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
872 }
873}
874
875static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
876 u32 *backup)
877{
878 u32 i;
879
880 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
881 backup[i] = usb_read8(adapt, mac_reg[i]);
882 }
883 backup[i] = usb_read32(adapt, mac_reg[i]);
884}
885
886static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
887 u32 *backup, u32 regiester_num)
888{
889 u32 i;
890
891 for (i = 0; i < regiester_num; i++)
892 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
893}
894
895static void reload_mac_registers(struct adapter *adapt,
896 u32 *mac_reg, u32 *backup)
897{
898 u32 i;
899
900 for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
901 usb_write8(adapt, mac_reg[i], (u8)backup[i]);
902 }
903 usb_write32(adapt, mac_reg[i], backup[i]);
904}
905
906static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
907 bool is_path_a_on, bool is2t)
908{
909 u32 path_on;
910 u32 i;
911
navin patidard9124e02014-09-07 16:38:04 +0530912 if (!is2t) {
913 path_on = 0x0bdb25a0;
914 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
915 } else {
Vatika Harlalka179e7dc2015-02-27 15:18:02 +0530916 path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
navin patidard9124e02014-09-07 16:38:04 +0530917 phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
918 }
919
920 for (i = 1; i < IQK_ADDA_REG_NUM; i++)
921 phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
922}
923
924static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
925{
926 u32 i = 0;
927
928 usb_write8(adapt, mac_reg[i], 0x3F);
929
930 for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700931 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
navin patidard9124e02014-09-07 16:38:04 +0530932 }
Anish Bhatt9c68ed02015-10-18 22:51:41 -0700933 usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
navin patidard9124e02014-09-07 16:38:04 +0530934}
935
936static void path_a_standby(struct adapter *adapt)
937{
938
939 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
940 phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
941 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
942}
943
944static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
945{
946 u32 mode;
947
948 mode = pi_mode ? 0x01000100 : 0x01000000;
949 phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
950 phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
951}
952
953static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
954 u8 c1, u8 c2)
955{
Vatika Harlalka3fe90652015-02-27 23:23:57 +0530956 u32 i, j, diff, sim_bitmap = 0, bound;
navin patidard9124e02014-09-07 16:38:04 +0530957 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
958 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
959 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
960 bool result = true;
navin patidard9124e02014-09-07 16:38:04 +0530961 s32 tmp1 = 0, tmp2 = 0;
962
963 if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) ||
964 (dm_odm->RFType == ODM_2T4R))
navin patidard9124e02014-09-07 16:38:04 +0530965 bound = 8;
966 else
967 bound = 4;
968
navin patidard9124e02014-09-07 16:38:04 +0530969 for (i = 0; i < bound; i++) {
970 if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
971 if ((resulta[c1][i] & 0x00000200) != 0)
972 tmp1 = resulta[c1][i] | 0xFFFFFC00;
973 else
974 tmp1 = resulta[c1][i];
975
976 if ((resulta[c2][i] & 0x00000200) != 0)
977 tmp2 = resulta[c2][i] | 0xFFFFFC00;
978 else
979 tmp2 = resulta[c2][i];
980 } else {
981 tmp1 = resulta[c1][i];
982 tmp2 = resulta[c2][i];
983 }
984
Ivan Safonov016c6bb2015-10-27 22:20:28 +0700985 diff = abs(tmp1 - tmp2);
navin patidard9124e02014-09-07 16:38:04 +0530986
987 if (diff > MAX_TOLERANCE) {
988 if ((i == 2 || i == 6) && !sim_bitmap) {
989 if (resulta[c1][i] + resulta[c1][i+1] == 0)
990 final_candidate[(i/4)] = c2;
991 else if (resulta[c2][i] + resulta[c2][i+1] == 0)
992 final_candidate[(i/4)] = c1;
993 else
994 sim_bitmap = sim_bitmap | (1<<i);
995 } else {
996 sim_bitmap = sim_bitmap | (1<<i);
997 }
998 }
999 }
1000
1001 if (sim_bitmap == 0) {
1002 for (i = 0; i < (bound/4); i++) {
1003 if (final_candidate[i] != 0xFF) {
1004 for (j = i*4; j < (i+1)*4-2; j++)
1005 resulta[3][j] = resulta[final_candidate[i]][j];
1006 result = false;
1007 }
1008 }
1009 return result;
1010 } else {
1011 if (!(sim_bitmap & 0x03)) { /* path A TX OK */
1012 for (i = 0; i < 2; i++)
1013 resulta[3][i] = resulta[c1][i];
1014 }
1015 if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
1016 for (i = 2; i < 4; i++)
1017 resulta[3][i] = resulta[c1][i];
1018 }
1019
1020 if (!(sim_bitmap & 0x30)) { /* path B TX OK */
1021 for (i = 4; i < 6; i++)
1022 resulta[3][i] = resulta[c1][i];
1023 }
1024
1025 if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
1026 for (i = 6; i < 8; i++)
1027 resulta[3][i] = resulta[c1][i];
1028 }
1029 return false;
1030 }
1031}
1032
1033static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
1034 u8 t, bool is2t)
1035{
1036 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1037 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1038 u32 i;
1039 u8 path_a_ok, path_b_ok;
1040 u32 adda_reg[IQK_ADDA_REG_NUM] = {
1041 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
1042 rRx_Wait_CCA, rTx_CCK_RFON,
1043 rTx_CCK_BBON, rTx_OFDM_RFON,
1044 rTx_OFDM_BBON, rTx_To_Rx,
1045 rTx_To_Tx, rRx_CCK,
1046 rRx_OFDM, rRx_Wait_RIFS,
1047 rRx_TO_Rx, rStandby,
1048 rSleep, rPMPD_ANAEN};
1049
1050 u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
1051 REG_TXPAUSE, REG_BCN_CTRL,
1052 REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
1053
1054 /* since 92C & 92D have the different define in IQK_BB_REG */
1055 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1056 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
1057 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
1058 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
1059 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
1060
1061 u32 retry_count = 9;
1062 if (*(dm_odm->mp_mode) == 1)
1063 retry_count = 9;
1064 else
1065 retry_count = 2;
1066
1067 if (t == 0) {
1068
1069 /* Save ADDA parameters, turn Path A ADDA on */
1070 save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1071 IQK_ADDA_REG_NUM);
1072 save_mac_registers(adapt, iqk_mac_reg,
1073 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1074 save_adda_registers(adapt, iqk_bb_reg_92c,
1075 dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1076 }
1077
1078 path_adda_on(adapt, adda_reg, true, is2t);
1079 if (t == 0)
1080 dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1081 BIT(8));
1082
1083 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1084 /* Switch BB to PI mode to do IQ Calibration. */
1085 pi_mode_switch(adapt, true);
1086 }
1087
1088 /* BB setting */
Anish Bhatt9c68ed02015-10-18 22:51:41 -07001089 phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
navin patidard9124e02014-09-07 16:38:04 +05301090 phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1091 phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1092 phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1093
Anish Bhatt9c68ed02015-10-18 22:51:41 -07001094 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
1095 phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
1096 phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
1097 phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
navin patidard9124e02014-09-07 16:38:04 +05301098
1099 if (is2t) {
1100 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1101 0x00010000);
1102 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1103 0x00010000);
1104 }
1105
1106 /* MAC settings */
1107 mac_setting_calibration(adapt, iqk_mac_reg,
1108 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1109
1110 /* Page B init */
1111 /* AP or IQK */
1112 phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1113
1114 if (is2t)
1115 phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1116
1117 /* IQ calibration setting */
1118 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1119 phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1120 phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1121
1122 for (i = 0; i < retry_count; i++) {
1123 path_a_ok = phy_path_a_iqk(adapt, is2t);
1124 if (path_a_ok == 0x01) {
1125 result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1126 bMaskDWord)&0x3FF0000)>>16;
1127 result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1128 bMaskDWord)&0x3FF0000)>>16;
1129 break;
1130 }
1131 }
1132
1133 for (i = 0; i < retry_count; i++) {
1134 path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1135 if (path_a_ok == 0x03) {
1136 result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1137 bMaskDWord)&0x3FF0000)>>16;
1138 result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1139 bMaskDWord)&0x3FF0000)>>16;
1140 break;
1141 } else {
1142 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1143 ("Path A Rx IQK Fail!!\n"));
1144 }
1145 }
1146
1147 if (0x00 == path_a_ok) {
1148 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1149 ("Path A IQK failed!!\n"));
1150 }
1151
1152 if (is2t) {
1153 path_a_standby(adapt);
1154
1155 /* Turn Path B ADDA on */
1156 path_adda_on(adapt, adda_reg, false, is2t);
1157
1158 for (i = 0; i < retry_count; i++) {
1159 path_b_ok = phy_path_b_iqk(adapt);
1160 if (path_b_ok == 0x03) {
1161 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1162 bMaskDWord)&0x3FF0000)>>16;
1163 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1164 bMaskDWord)&0x3FF0000)>>16;
1165 result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1166 bMaskDWord)&0x3FF0000)>>16;
1167 result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1168 bMaskDWord)&0x3FF0000)>>16;
1169 break;
1170 } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
1171 result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1172 bMaskDWord)&0x3FF0000)>>16;
1173 result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1174 bMaskDWord)&0x3FF0000)>>16;
1175 }
1176 }
1177
1178 if (0x00 == path_b_ok) {
1179 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1180 ("Path B IQK failed!!\n"));
1181 }
1182 }
1183
1184 /* Back to BB mode, load original value */
1185 phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1186
1187 if (t != 0) {
1188 if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1189 /* Switch back BB to SI mode after
1190 * finish IQ Calibration.
1191 */
1192 pi_mode_switch(adapt, false);
1193 }
1194
1195 /* Reload ADDA power saving parameters */
1196 reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1197 IQK_ADDA_REG_NUM);
1198
1199 /* Reload MAC parameters */
1200 reload_mac_registers(adapt, iqk_mac_reg,
1201 dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1202
1203 reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1204 IQK_BB_REG_NUM);
1205
1206 /* Restore RX initial gain */
1207 phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1208 bMaskDWord, 0x00032ed3);
1209 if (is2t)
1210 phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1211 bMaskDWord, 0x00032ed3);
1212
1213 /* load 0xe30 IQC default value */
1214 phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1215 phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1216 }
1217}
1218
1219static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1220{
1221 u8 tmpreg;
1222 u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1223
1224 /* Check continuous TX and Packet TX */
1225 tmpreg = usb_read8(adapt, 0xd03);
1226
1227 if ((tmpreg&0x70) != 0)
1228 usb_write8(adapt, 0xd03, tmpreg&0x8F);
1229 else
1230 usb_write8(adapt, REG_TXPAUSE, 0xFF);
1231
1232 if ((tmpreg&0x70) != 0) {
1233 /* 1. Read original RF mode */
1234 /* Path-A */
1235 rf_a_mode = phy_query_rf_reg(adapt, RF_PATH_A, RF_AC,
1236 bMask12Bits);
1237
1238 /* Path-B */
1239 if (is2t)
1240 rf_b_mode = phy_query_rf_reg(adapt, RF_PATH_B, RF_AC,
1241 bMask12Bits);
1242
1243 /* 2. Set RF mode = standby mode */
1244 /* Path-A */
1245 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1246 (rf_a_mode&0x8FFFF)|0x10000);
1247
1248 /* Path-B */
1249 if (is2t)
1250 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1251 (rf_b_mode&0x8FFFF)|0x10000);
1252 }
1253
1254 /* 3. Read RF reg18 */
1255 lc_cal = phy_query_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1256
1257 /* 4. Set LC calibration begin bit15 */
1258 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1259 lc_cal|0x08000);
1260
1261 msleep(100);
1262
1263 /* Restore original situation */
1264 if ((tmpreg&0x70) != 0) {
1265 /* Deal with continuous TX case */
1266 /* Path-A */
1267 usb_write8(adapt, 0xd03, tmpreg);
1268 phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1269
1270 /* Path-B */
1271 if (is2t)
1272 phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1273 rf_b_mode);
1274 } else {
1275 /* Deal with Packet TX case */
1276 usb_write8(adapt, REG_TXPAUSE, 0x00);
1277 }
1278}
1279
1280void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1281{
1282 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1283 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1284 s32 result[4][8];
1285 u8 i, final, chn_index;
1286 bool pathaok, pathbok;
Sudip Mukherjee9393d342015-06-12 16:20:42 +05301287 s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
navin patidard9124e02014-09-07 16:38:04 +05301288 bool is12simular, is13simular, is23simular;
1289 bool singletone = false, carrier_sup = false;
1290 u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1291 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1292 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1293 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1294 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1295 rOFDM0_RxIQExtAnta};
1296 bool is2t;
1297
1298 is2t = (dm_odm->RFType == ODM_2T2R) ? true : false;
1299
1300 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1301 return;
1302
1303 if (singletone || carrier_sup)
1304 return;
1305
1306 if (recovery) {
1307 ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1308 ("phy_iq_calibrate: Return due to recovery!\n"));
1309 reload_adda_reg(adapt, iqk_bb_reg_92c,
1310 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1311 return;
1312 }
1313
1314 for (i = 0; i < 8; i++) {
1315 result[0][i] = 0;
1316 result[1][i] = 0;
1317 result[2][i] = 0;
1318 if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
1319 result[3][i] = 0x100;
1320 else
1321 result[3][i] = 0;
1322 }
1323 final = 0xff;
1324 pathaok = false;
1325 pathbok = false;
1326 is12simular = false;
1327 is23simular = false;
1328 is13simular = false;
1329
1330 for (i = 0; i < 3; i++) {
1331 phy_iq_calibrate(adapt, result, i, is2t);
1332
1333 if (i == 1) {
1334 is12simular = simularity_compare(adapt, result, 0, 1);
1335 if (is12simular) {
1336 final = 0;
1337 break;
1338 }
1339 }
1340
1341 if (i == 2) {
1342 is13simular = simularity_compare(adapt, result, 0, 2);
1343 if (is13simular) {
1344 final = 0;
1345 break;
1346 }
1347 is23simular = simularity_compare(adapt, result, 1, 2);
1348 if (is23simular)
1349 final = 1;
1350 else
1351 final = 3;
1352 }
1353 }
1354
1355 for (i = 0; i < 4; i++) {
1356 reg_e94 = result[i][0];
1357 reg_e9c = result[i][1];
1358 reg_ea4 = result[i][2];
navin patidard9124e02014-09-07 16:38:04 +05301359 reg_eb4 = result[i][4];
1360 reg_ebc = result[i][5];
1361 reg_ec4 = result[i][6];
navin patidard9124e02014-09-07 16:38:04 +05301362 }
1363
1364 if (final != 0xff) {
1365 reg_e94 = result[final][0];
1366 reg_e9c = result[final][1];
1367 reg_ea4 = result[final][2];
navin patidard9124e02014-09-07 16:38:04 +05301368 reg_eb4 = result[final][4];
1369 reg_ebc = result[final][5];
1370 dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1371 dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1372 dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1373 dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1374 reg_ec4 = result[final][6];
navin patidard9124e02014-09-07 16:38:04 +05301375 pathaok = true;
1376 pathbok = true;
1377 } else {
1378 ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1379 ("IQK: FAIL use default value\n"));
1380 dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1381 dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1382 dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1383 dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1384 }
1385 if (reg_e94 != 0)
1386 patha_fill_iqk(adapt, pathaok, result, final,
1387 (reg_ea4 == 0));
1388 if (is2t) {
1389 if (reg_eb4 != 0)
1390 pathb_fill_iqk(adapt, pathbok, result, final,
1391 (reg_ec4 == 0));
1392 }
1393
1394 chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel);
1395
1396 if (final < 4) {
1397 for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1398 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1399 dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1400 }
1401
1402 save_adda_registers(adapt, iqk_bb_reg_92c,
1403 dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1404}
1405
1406void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1407{
1408 bool singletone = false, carrier_sup = false;
1409 u32 timeout = 2000, timecount = 0;
1410 struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1411 struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1412
1413 if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1414 return;
1415 if (singletone || carrier_sup)
1416 return;
1417
1418 while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1419 mdelay(50);
1420 timecount += 50;
1421 }
1422
1423 dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1424
1425 if (dm_odm->RFType == ODM_2T2R) {
1426 phy_lc_calibrate(adapt, true);
1427 } else {
1428 /* For 88C 1T1R */
1429 phy_lc_calibrate(adapt, false);
1430 }
1431
1432 dm_odm->RFCalibrateInfo.bLCKInProgress = false;
1433}