1
2
3
4
5
6
7
8#include <osdep_service.h>
9#include <drv_types.h>
10#include <phy.h>
11#include <rf.h>
12#include <rtl8188e_hal.h>
13
14void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
15 enum ht_channel_width bandwidth)
16{
17 struct hal_data_8188e *hal_data = adapt->HalData;
18
19 switch (bandwidth) {
20 case HT_CHANNEL_WIDTH_20:
21 hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
22 0xfffff3ff) | BIT(10) | BIT(11));
23 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
24 hal_data->RfRegChnlVal[0]);
25 break;
26 case HT_CHANNEL_WIDTH_40:
27 hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
28 0xfffff3ff) | BIT(10));
29 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
30 hal_data->RfRegChnlVal[0]);
31 break;
32 default:
33 break;
34 }
35}
36
37void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel)
38{
39 struct hal_data_8188e *hal_data = adapt->HalData;
40 struct dm_priv *pdmpriv = &hal_data->dmpriv;
41 struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
42 u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value;
43 u8 idx1, idx2;
44 u8 *ptr;
45 u8 direction;
46
47 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
48 tx_agc[RF_PATH_A] = 0x3f3f3f3f;
49 tx_agc[RF_PATH_B] = 0x3f3f3f3f;
50 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
51 tx_agc[idx1] = powerlevel[idx1] |
52 (powerlevel[idx1] << 8) |
53 (powerlevel[idx1] << 16) |
54 (powerlevel[idx1] << 24);
55 }
56 } else {
57 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
58 tx_agc[RF_PATH_A] = 0x10101010;
59 tx_agc[RF_PATH_B] = 0x10101010;
60 } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
61 tx_agc[RF_PATH_A] = 0x00000000;
62 tx_agc[RF_PATH_B] = 0x00000000;
63 } else {
64 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
65 tx_agc[idx1] = powerlevel[idx1] |
66 (powerlevel[idx1] << 8) |
67 (powerlevel[idx1] << 16) |
68 (powerlevel[idx1] << 24);
69 }
70 if (hal_data->EEPROMRegulatory == 0) {
71 tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][6] +
72 (hal_data->MCSTxPowerLevelOriginalOffset[0][7] << 8);
73 tx_agc[RF_PATH_A] += tmpval;
74
75 tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][14] +
76 (hal_data->MCSTxPowerLevelOriginalOffset[0][15] << 24);
77 tx_agc[RF_PATH_B] += tmpval;
78 }
79 }
80 }
81 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
82 ptr = (u8 *)(&tx_agc[idx1]);
83 for (idx2 = 0; idx2 < 4; idx2++) {
84 if (*ptr > RF6052_MAX_TX_PWR)
85 *ptr = RF6052_MAX_TX_PWR;
86 ptr++;
87 }
88 }
89 rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
90 &pwrtrac_value);
91
92 if (direction == 1) {
93
94 tx_agc[0] += pwrtrac_value;
95 tx_agc[1] += pwrtrac_value;
96 } else if (direction == 2) {
97
98 tx_agc[0] -= pwrtrac_value;
99 tx_agc[1] -= pwrtrac_value;
100 }
101
102
103 tmpval = tx_agc[RF_PATH_A] & 0xff;
104 phy_set_bb_reg(adapt, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
105 tmpval = tx_agc[RF_PATH_A] >> 8;
106 phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
107
108
109 tmpval = tx_agc[RF_PATH_B] >> 24;
110 phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
111 tmpval = tx_agc[RF_PATH_B] & 0x00ffffff;
112 phy_set_bb_reg(adapt, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
113}
114
115
116
117static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm,
118 u8 *pwr_level_bw20, u8 *pwr_level_bw40,
119 u8 channel, u32 *ofdmbase, u32 *mcs_base)
120{
121 u32 powerbase0, powerbase1;
122 u8 i, powerlevel[2];
123
124 for (i = 0; i < 2; i++) {
125 powerbase0 = pwr_level_ofdm[i];
126
127 powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
128 (powerbase0 << 8) | powerbase0;
129 *(ofdmbase + i) = powerbase0;
130 }
131
132 if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
133 powerlevel[0] = pwr_level_bw20[0];
134 else
135 powerlevel[0] = pwr_level_bw40[0];
136 powerbase1 = powerlevel[0];
137 powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |
138 (powerbase1 << 8) | powerbase1;
139 *mcs_base = powerbase1;
140}
141
142static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel,
143 u8 index, u32 *powerbase0, u32 *powerbase1,
144 u32 *out_val)
145{
146 struct hal_data_8188e *hal_data = adapt->HalData;
147 struct dm_priv *pdmpriv = &hal_data->dmpriv;
148 u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
149 s8 pwr_diff = 0;
150 u32 write_val, customer_limit, rf;
151 u8 regulatory = hal_data->EEPROMRegulatory;
152
153
154
155 for (rf = 0; rf < 2; rf++) {
156 u8 j = index + (rf ? 8 : 0);
157
158 switch (regulatory) {
159 case 0:
160 chnlGroup = 0;
161 write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
162 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
163 break;
164 case 1:
165
166 if (hal_data->pwrGroupCnt == 1)
167 chnlGroup = 0;
168 if (hal_data->pwrGroupCnt >= hal_data->PGMaxGroup)
169 Hal_GetChnlGroup88E(channel, &chnlGroup);
170
171 write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
172 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
173 break;
174 case 2:
175
176 write_val = (index < 2) ? powerbase0[rf] : powerbase1[rf];
177 break;
178 case 3:
179
180 chnlGroup = 0;
181
182 if (index < 2)
183 pwr_diff = hal_data->TxPwrLegacyHtDiff[rf][channel - 1];
184 else if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
185 pwr_diff = hal_data->TxPwrHt20Diff[rf][channel - 1];
186
187 if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
188 customer_pwr_limit = hal_data->PwrGroupHT40[rf][channel - 1];
189 else
190 customer_pwr_limit = hal_data->PwrGroupHT20[rf][channel - 1];
191
192 if (pwr_diff >= customer_pwr_limit)
193 pwr_diff = 0;
194 else
195 pwr_diff = customer_pwr_limit - pwr_diff;
196
197 for (i = 0; i < 4; i++) {
198 pwr_diff_limit[i] = (u8)((hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] &
199 (0x7f << (i * 8))) >> (i * 8));
200
201 if (pwr_diff_limit[i] > pwr_diff)
202 pwr_diff_limit[i] = pwr_diff;
203 }
204 customer_limit = (pwr_diff_limit[3] << 24) |
205 (pwr_diff_limit[2] << 16) |
206 (pwr_diff_limit[1] << 8) |
207 (pwr_diff_limit[0]);
208 write_val = customer_limit + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
209 break;
210 default:
211 chnlGroup = 0;
212 write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] +
213 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
214 break;
215 }
216
217
218
219
220 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
221 write_val = 0x14141414;
222 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
223 write_val = 0x00000000;
224
225 *(out_val + rf) = write_val;
226 }
227}
228
229static void write_ofdm_pwr_reg(struct adapter *adapt, u8 index, u32 *pvalue)
230{
231 u16 regoffset_a[6] = { rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
232 rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
233 rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 };
234 u16 regoffset_b[6] = { rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
235 rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
236 rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 };
237 u8 i, rf, pwr_val[4];
238 u32 write_val;
239 u16 regoffset;
240
241 for (rf = 0; rf < 2; rf++) {
242 write_val = pvalue[rf];
243 for (i = 0; i < 4; i++) {
244 pwr_val[i] = (u8)((write_val & (0x7f << (i * 8))) >> (i * 8));
245 if (pwr_val[i] > RF6052_MAX_TX_PWR)
246 pwr_val[i] = RF6052_MAX_TX_PWR;
247 }
248 write_val = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
249 (pwr_val[1] << 8) | pwr_val[0];
250
251 if (rf == 0)
252 regoffset = regoffset_a[index];
253 else
254 regoffset = regoffset_b[index];
255
256 phy_set_bb_reg(adapt, regoffset, bMaskDWord, write_val);
257 }
258}
259
260void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
261 u8 *pwr_level_ofdm,
262 u8 *pwr_level_bw20,
263 u8 *pwr_level_bw40, u8 channel)
264{
265 u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value;
266 u8 direction;
267 u8 index = 0;
268
269 getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40,
270 channel, &powerbase0[0], &powerbase1[0]);
271
272 rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0,
273 &direction, &pwrtrac_value);
274
275 for (index = 0; index < 6; index++) {
276 get_rx_power_val_by_reg(adapt, channel, index,
277 &powerbase0[0], &powerbase1[0],
278 &write_val[0]);
279
280 if (direction == 1) {
281 write_val[0] += pwrtrac_value;
282 write_val[1] += pwrtrac_value;
283 } else if (direction == 2) {
284 write_val[0] -= pwrtrac_value;
285 write_val[1] -= pwrtrac_value;
286 }
287 write_ofdm_pwr_reg(adapt, index, &write_val[0]);
288 }
289}
290