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