1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include <drv_types.h> |
9 | #include <rtw_debug.h> |
10 | #include <hal_data.h> |
11 | #include <linux/kernel.h> |
12 | |
13 | u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath, |
14 | enum rate_section RateSection) |
15 | { |
16 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
17 | u8 value = 0; |
18 | |
19 | if (RfPath >= RF_PATH_MAX) |
20 | return 0; |
21 | |
22 | switch (RateSection) { |
23 | case CCK: |
24 | value = pHalData->TxPwrByRateBase2_4G[RfPath][0]; |
25 | break; |
26 | case OFDM: |
27 | value = pHalData->TxPwrByRateBase2_4G[RfPath][1]; |
28 | break; |
29 | case HT_MCS0_MCS7: |
30 | value = pHalData->TxPwrByRateBase2_4G[RfPath][2]; |
31 | break; |
32 | default: |
33 | break; |
34 | } |
35 | |
36 | return value; |
37 | } |
38 | |
39 | static void |
40 | phy_SetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath, |
41 | enum rate_section RateSection, u8 Value) |
42 | { |
43 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
44 | |
45 | if (RfPath >= RF_PATH_MAX) |
46 | return; |
47 | |
48 | switch (RateSection) { |
49 | case CCK: |
50 | pHalData->TxPwrByRateBase2_4G[RfPath][0] = Value; |
51 | break; |
52 | case OFDM: |
53 | pHalData->TxPwrByRateBase2_4G[RfPath][1] = Value; |
54 | break; |
55 | case HT_MCS0_MCS7: |
56 | pHalData->TxPwrByRateBase2_4G[RfPath][2] = Value; |
57 | break; |
58 | default: |
59 | break; |
60 | } |
61 | } |
62 | |
63 | static void |
64 | phy_StoreTxPowerByRateBase( |
65 | struct adapter *padapter |
66 | ) |
67 | { |
68 | u8 path, base; |
69 | |
70 | for (path = RF_PATH_A; path <= RF_PATH_B; ++path) { |
71 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_11M); |
72 | phy_SetTxPowerByRateBase(Adapter: padapter, RfPath: path, RateSection: CCK, Value: base); |
73 | |
74 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_54M); |
75 | phy_SetTxPowerByRateBase(Adapter: padapter, RfPath: path, RateSection: OFDM, Value: base); |
76 | |
77 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_MCS7); |
78 | phy_SetTxPowerByRateBase(Adapter: padapter, RfPath: path, RateSection: HT_MCS0_MCS7, Value: base); |
79 | } |
80 | } |
81 | |
82 | u8 PHY_GetRateSectionIndexOfTxPowerByRate( |
83 | struct adapter *padapter, u32 RegAddr, u32 BitMask |
84 | ) |
85 | { |
86 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
87 | struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; |
88 | u8 index = 0; |
89 | |
90 | if (pDM_Odm->PhyRegPgVersion == 0) { |
91 | switch (RegAddr) { |
92 | case rTxAGC_A_Rate18_06: |
93 | index = 0; |
94 | break; |
95 | case rTxAGC_A_Rate54_24: |
96 | index = 1; |
97 | break; |
98 | case rTxAGC_A_CCK1_Mcs32: |
99 | index = 6; |
100 | break; |
101 | case rTxAGC_B_CCK11_A_CCK2_11: |
102 | if (BitMask == bMaskH3Bytes) |
103 | index = 7; |
104 | else if (BitMask == 0x000000ff) |
105 | index = 15; |
106 | break; |
107 | |
108 | case rTxAGC_A_Mcs03_Mcs00: |
109 | index = 2; |
110 | break; |
111 | case rTxAGC_A_Mcs07_Mcs04: |
112 | index = 3; |
113 | break; |
114 | case rTxAGC_B_Rate18_06: |
115 | index = 8; |
116 | break; |
117 | case rTxAGC_B_Rate54_24: |
118 | index = 9; |
119 | break; |
120 | case rTxAGC_B_CCK1_55_Mcs32: |
121 | index = 14; |
122 | break; |
123 | case rTxAGC_B_Mcs03_Mcs00: |
124 | index = 10; |
125 | break; |
126 | case rTxAGC_B_Mcs07_Mcs04: |
127 | index = 11; |
128 | break; |
129 | default: |
130 | break; |
131 | } |
132 | } |
133 | |
134 | return index; |
135 | } |
136 | |
137 | void |
138 | PHY_GetRateValuesOfTxPowerByRate( |
139 | struct adapter *padapter, |
140 | u32 RegAddr, |
141 | u32 BitMask, |
142 | u32 Value, |
143 | u8 *RateIndex, |
144 | s8 *PwrByRateVal, |
145 | u8 *RateNum |
146 | ) |
147 | { |
148 | u8 i = 0; |
149 | |
150 | switch (RegAddr) { |
151 | case rTxAGC_A_Rate18_06: |
152 | case rTxAGC_B_Rate18_06: |
153 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_6M); |
154 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_9M); |
155 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_12M); |
156 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_18M); |
157 | for (i = 0; i < 4; ++i) { |
158 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
159 | ((Value >> (i * 8)) & 0xF)); |
160 | } |
161 | *RateNum = 4; |
162 | break; |
163 | |
164 | case rTxAGC_A_Rate54_24: |
165 | case rTxAGC_B_Rate54_24: |
166 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_24M); |
167 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_36M); |
168 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_48M); |
169 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_54M); |
170 | for (i = 0; i < 4; ++i) { |
171 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
172 | ((Value >> (i * 8)) & 0xF)); |
173 | } |
174 | *RateNum = 4; |
175 | break; |
176 | |
177 | case rTxAGC_A_CCK1_Mcs32: |
178 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_1M); |
179 | PwrByRateVal[0] = (s8) ((((Value >> (8 + 4)) & 0xF)) * 10 + |
180 | ((Value >> 8) & 0xF)); |
181 | *RateNum = 1; |
182 | break; |
183 | |
184 | case rTxAGC_B_CCK11_A_CCK2_11: |
185 | if (BitMask == 0xffffff00) { |
186 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_2M); |
187 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_5_5M); |
188 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_11M); |
189 | for (i = 1; i < 4; ++i) { |
190 | PwrByRateVal[i - 1] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
191 | ((Value >> (i * 8)) & 0xF)); |
192 | } |
193 | *RateNum = 3; |
194 | } else if (BitMask == 0x000000ff) { |
195 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_11M); |
196 | PwrByRateVal[0] = (s8) ((((Value >> 4) & 0xF)) * 10 + (Value & 0xF)); |
197 | *RateNum = 1; |
198 | } |
199 | break; |
200 | |
201 | case rTxAGC_A_Mcs03_Mcs00: |
202 | case rTxAGC_B_Mcs03_Mcs00: |
203 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS0); |
204 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS1); |
205 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS2); |
206 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS3); |
207 | for (i = 0; i < 4; ++i) { |
208 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
209 | ((Value >> (i * 8)) & 0xF)); |
210 | } |
211 | *RateNum = 4; |
212 | break; |
213 | |
214 | case rTxAGC_A_Mcs07_Mcs04: |
215 | case rTxAGC_B_Mcs07_Mcs04: |
216 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS4); |
217 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS5); |
218 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS6); |
219 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS7); |
220 | for (i = 0; i < 4; ++i) { |
221 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
222 | ((Value >> (i * 8)) & 0xF)); |
223 | } |
224 | *RateNum = 4; |
225 | break; |
226 | |
227 | case rTxAGC_B_CCK1_55_Mcs32: |
228 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_1M); |
229 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_2M); |
230 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_5_5M); |
231 | for (i = 1; i < 4; ++i) { |
232 | PwrByRateVal[i - 1] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
233 | ((Value >> (i * 8)) & 0xF)); |
234 | } |
235 | *RateNum = 3; |
236 | break; |
237 | |
238 | case 0xC20: |
239 | case 0xE20: |
240 | case 0x1820: |
241 | case 0x1a20: |
242 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_1M); |
243 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_2M); |
244 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_5_5M); |
245 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_11M); |
246 | for (i = 0; i < 4; ++i) { |
247 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
248 | ((Value >> (i * 8)) & 0xF)); |
249 | } |
250 | *RateNum = 4; |
251 | break; |
252 | |
253 | case 0xC24: |
254 | case 0xE24: |
255 | case 0x1824: |
256 | case 0x1a24: |
257 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_6M); |
258 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_9M); |
259 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_12M); |
260 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_18M); |
261 | for (i = 0; i < 4; ++i) { |
262 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
263 | ((Value >> (i * 8)) & 0xF)); |
264 | } |
265 | *RateNum = 4; |
266 | break; |
267 | |
268 | case 0xC28: |
269 | case 0xE28: |
270 | case 0x1828: |
271 | case 0x1a28: |
272 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_24M); |
273 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_36M); |
274 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_48M); |
275 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_54M); |
276 | for (i = 0; i < 4; ++i) { |
277 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
278 | ((Value >> (i * 8)) & 0xF)); |
279 | } |
280 | *RateNum = 4; |
281 | break; |
282 | |
283 | case 0xC2C: |
284 | case 0xE2C: |
285 | case 0x182C: |
286 | case 0x1a2C: |
287 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS0); |
288 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS1); |
289 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS2); |
290 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS3); |
291 | for (i = 0; i < 4; ++i) { |
292 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
293 | ((Value >> (i * 8)) & 0xF)); |
294 | } |
295 | *RateNum = 4; |
296 | break; |
297 | |
298 | case 0xC30: |
299 | case 0xE30: |
300 | case 0x1830: |
301 | case 0x1a30: |
302 | RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS4); |
303 | RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS5); |
304 | RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS6); |
305 | RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(Rate: MGN_MCS7); |
306 | for (i = 0; i < 4; ++i) { |
307 | PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + |
308 | ((Value >> (i * 8)) & 0xF)); |
309 | } |
310 | *RateNum = 4; |
311 | break; |
312 | |
313 | default: |
314 | break; |
315 | } |
316 | } |
317 | |
318 | static void PHY_StoreTxPowerByRateNew(struct adapter *padapter, u32 RfPath, |
319 | u32 RegAddr, u32 BitMask, u32 Data) |
320 | { |
321 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
322 | u8 i = 0, rateIndex[4] = {0}, rateNum = 0; |
323 | s8 PwrByRateVal[4] = {0}; |
324 | |
325 | PHY_GetRateValuesOfTxPowerByRate(padapter, RegAddr, BitMask, Value: Data, RateIndex: rateIndex, PwrByRateVal, RateNum: &rateNum); |
326 | |
327 | if (RfPath >= RF_PATH_MAX) |
328 | return; |
329 | |
330 | for (i = 0; i < rateNum; ++i) { |
331 | pHalData->TxPwrByRateOffset[RfPath][rateIndex[i]] = PwrByRateVal[i]; |
332 | } |
333 | } |
334 | |
335 | static void PHY_StoreTxPowerByRateOld( |
336 | struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data |
337 | ) |
338 | { |
339 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
340 | u8 index = PHY_GetRateSectionIndexOfTxPowerByRate(padapter, RegAddr, BitMask); |
341 | |
342 | pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][index] = Data; |
343 | } |
344 | |
345 | void PHY_InitTxPowerByRate(struct adapter *padapter) |
346 | { |
347 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
348 | u8 rfPath, rate; |
349 | |
350 | for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) |
351 | for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate) |
352 | pHalData->TxPwrByRateOffset[rfPath][rate] = 0; |
353 | } |
354 | |
355 | void PHY_StoreTxPowerByRate( |
356 | struct adapter *padapter, |
357 | u32 RfPath, |
358 | u32 RegAddr, |
359 | u32 BitMask, |
360 | u32 Data |
361 | ) |
362 | { |
363 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
364 | struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; |
365 | |
366 | if (pDM_Odm->PhyRegPgVersion > 0) |
367 | PHY_StoreTxPowerByRateNew(padapter, RfPath, RegAddr, BitMask, Data); |
368 | else if (pDM_Odm->PhyRegPgVersion == 0) { |
369 | PHY_StoreTxPowerByRateOld(padapter, RegAddr, BitMask, Data); |
370 | } |
371 | } |
372 | |
373 | static void |
374 | phy_ConvertTxPowerByRateInDbmToRelativeValues( |
375 | struct adapter *padapter |
376 | ) |
377 | { |
378 | u8 base = 0, i = 0, value = 0, path = 0; |
379 | u8 cckRates[4] = { |
380 | MGN_1M, MGN_2M, MGN_5_5M, MGN_11M |
381 | }; |
382 | u8 ofdmRates[8] = { |
383 | MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M |
384 | }; |
385 | u8 mcs0_7Rates[8] = { |
386 | MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7 |
387 | }; |
388 | for (path = RF_PATH_A; path < RF_PATH_MAX; ++path) { |
389 | /* CCK */ |
390 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_11M); |
391 | for (i = 0; i < ARRAY_SIZE(cckRates); ++i) { |
392 | value = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: cckRates[i]); |
393 | PHY_SetTxPowerByRate(padapter, RFPath: path, Rate: cckRates[i], Value: value - base); |
394 | } |
395 | |
396 | /* OFDM */ |
397 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_54M); |
398 | for (i = 0; i < sizeof(ofdmRates); ++i) { |
399 | value = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: ofdmRates[i]); |
400 | PHY_SetTxPowerByRate(padapter, RFPath: path, Rate: ofdmRates[i], Value: value - base); |
401 | } |
402 | |
403 | /* HT MCS0~7 */ |
404 | base = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: MGN_MCS7); |
405 | for (i = 0; i < sizeof(mcs0_7Rates); ++i) { |
406 | value = PHY_GetTxPowerByRate(padapter, RFPath: path, RateIndex: mcs0_7Rates[i]); |
407 | PHY_SetTxPowerByRate(padapter, RFPath: path, Rate: mcs0_7Rates[i], Value: value - base); |
408 | } |
409 | } |
410 | } |
411 | |
412 | /* |
413 | * This function must be called if the value in the PHY_REG_PG.txt(or header) |
414 | * is exact dBm values |
415 | */ |
416 | void PHY_TxPowerByRateConfiguration(struct adapter *padapter) |
417 | { |
418 | phy_StoreTxPowerByRateBase(padapter); |
419 | phy_ConvertTxPowerByRateInDbmToRelativeValues(padapter); |
420 | } |
421 | |
422 | void PHY_SetTxPowerIndexByRateSection( |
423 | struct adapter *padapter, u8 RFPath, u8 Channel, u8 RateSection |
424 | ) |
425 | { |
426 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
427 | |
428 | if (RateSection == CCK) { |
429 | u8 cckRates[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M}; |
430 | PHY_SetTxPowerIndexByRateArray(padapter, RFPath, |
431 | BandWidth: pHalData->CurrentChannelBW, |
432 | Channel, Rates: cckRates, |
433 | ARRAY_SIZE(cckRates)); |
434 | |
435 | } else if (RateSection == OFDM) { |
436 | u8 ofdmRates[] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}; |
437 | PHY_SetTxPowerIndexByRateArray(padapter, RFPath, |
438 | BandWidth: pHalData->CurrentChannelBW, |
439 | Channel, Rates: ofdmRates, |
440 | ARRAY_SIZE(ofdmRates)); |
441 | |
442 | } else if (RateSection == HT_MCS0_MCS7) { |
443 | u8 htRates1T[] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7}; |
444 | PHY_SetTxPowerIndexByRateArray(padapter, RFPath, |
445 | BandWidth: pHalData->CurrentChannelBW, |
446 | Channel, Rates: htRates1T, |
447 | ARRAY_SIZE(htRates1T)); |
448 | |
449 | } |
450 | } |
451 | |
452 | u8 PHY_GetTxPowerIndexBase( |
453 | struct adapter *padapter, |
454 | u8 RFPath, |
455 | u8 Rate, |
456 | enum channel_width BandWidth, |
457 | u8 Channel |
458 | ) |
459 | { |
460 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
461 | u8 txPower = 0; |
462 | u8 chnlIdx = (Channel-1); |
463 | |
464 | if (HAL_IsLegalChannel(Adapter: padapter, Channel) == false) |
465 | chnlIdx = 0; |
466 | |
467 | if (IS_CCK_RATE(Rate)) |
468 | txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx]; |
469 | else if (MGN_6M <= Rate) |
470 | txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx]; |
471 | |
472 | /* OFDM-1T */ |
473 | if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) |
474 | txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S]; |
475 | |
476 | if (BandWidth == CHANNEL_WIDTH_20) { /* BW20-1S, BW20-2S */ |
477 | if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7) |
478 | txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S]; |
479 | } else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */ |
480 | if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7) |
481 | txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; |
482 | } |
483 | |
484 | return txPower; |
485 | } |
486 | |
487 | s8 PHY_GetTxPowerTrackingOffset(struct adapter *padapter, u8 RFPath, u8 Rate) |
488 | { |
489 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
490 | struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; |
491 | s8 offset = 0; |
492 | |
493 | if (pDM_Odm->RFCalibrateInfo.TxPowerTrackControl == false) |
494 | return offset; |
495 | |
496 | if ((Rate == MGN_1M) || (Rate == MGN_2M) || (Rate == MGN_5_5M) || (Rate == MGN_11M)) |
497 | offset = pDM_Odm->Remnant_CCKSwingIdx; |
498 | else |
499 | offset = pDM_Odm->Remnant_OFDMSwingIdx[RFPath]; |
500 | |
501 | return offset; |
502 | } |
503 | |
504 | u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate) |
505 | { |
506 | u8 index = 0; |
507 | switch (Rate) { |
508 | case MGN_1M: |
509 | index = 0; |
510 | break; |
511 | case MGN_2M: |
512 | index = 1; |
513 | break; |
514 | case MGN_5_5M: |
515 | index = 2; |
516 | break; |
517 | case MGN_11M: |
518 | index = 3; |
519 | break; |
520 | case MGN_6M: |
521 | index = 4; |
522 | break; |
523 | case MGN_9M: |
524 | index = 5; |
525 | break; |
526 | case MGN_12M: |
527 | index = 6; |
528 | break; |
529 | case MGN_18M: |
530 | index = 7; |
531 | break; |
532 | case MGN_24M: |
533 | index = 8; |
534 | break; |
535 | case MGN_36M: |
536 | index = 9; |
537 | break; |
538 | case MGN_48M: |
539 | index = 10; |
540 | break; |
541 | case MGN_54M: |
542 | index = 11; |
543 | break; |
544 | case MGN_MCS0: |
545 | index = 12; |
546 | break; |
547 | case MGN_MCS1: |
548 | index = 13; |
549 | break; |
550 | case MGN_MCS2: |
551 | index = 14; |
552 | break; |
553 | case MGN_MCS3: |
554 | index = 15; |
555 | break; |
556 | case MGN_MCS4: |
557 | index = 16; |
558 | break; |
559 | case MGN_MCS5: |
560 | index = 17; |
561 | break; |
562 | case MGN_MCS6: |
563 | index = 18; |
564 | break; |
565 | case MGN_MCS7: |
566 | index = 19; |
567 | break; |
568 | default: |
569 | break; |
570 | } |
571 | return index; |
572 | } |
573 | |
574 | s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 Rate) |
575 | { |
576 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
577 | s8 value = 0; |
578 | u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); |
579 | |
580 | if ((padapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory == 2) || |
581 | padapter->registrypriv.RegEnableTxPowerByRate == 0) |
582 | return 0; |
583 | |
584 | if (RFPath >= RF_PATH_MAX) |
585 | return value; |
586 | |
587 | if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) |
588 | return value; |
589 | |
590 | return pHalData->TxPwrByRateOffset[RFPath][rateIndex]; |
591 | |
592 | } |
593 | |
594 | void PHY_SetTxPowerByRate( |
595 | struct adapter *padapter, |
596 | u8 RFPath, |
597 | u8 Rate, |
598 | s8 Value |
599 | ) |
600 | { |
601 | struct hal_com_data *pHalData = GET_HAL_DATA(padapter); |
602 | u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); |
603 | |
604 | if (RFPath >= RF_PATH_MAX) |
605 | return; |
606 | |
607 | if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) |
608 | return; |
609 | |
610 | pHalData->TxPwrByRateOffset[RFPath][rateIndex] = Value; |
611 | } |
612 | |
613 | void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path) |
614 | { |
615 | PHY_SetTxPowerIndexByRateSection(padapter: Adapter, RFPath: path, Channel: channel, RateSection: CCK); |
616 | |
617 | PHY_SetTxPowerIndexByRateSection(padapter: Adapter, RFPath: path, Channel: channel, RateSection: OFDM); |
618 | PHY_SetTxPowerIndexByRateSection(padapter: Adapter, RFPath: path, Channel: channel, RateSection: HT_MCS0_MCS7); |
619 | } |
620 | |
621 | void PHY_SetTxPowerIndexByRateArray( |
622 | struct adapter *padapter, |
623 | u8 RFPath, |
624 | enum channel_width BandWidth, |
625 | u8 Channel, |
626 | u8 *Rates, |
627 | u8 RateArraySize |
628 | ) |
629 | { |
630 | u32 powerIndex = 0; |
631 | int i = 0; |
632 | |
633 | for (i = 0; i < RateArraySize; ++i) { |
634 | powerIndex = PHY_GetTxPowerIndex(padapter, RFPath, Rate: Rates[i], BandWidth, Channel); |
635 | PHY_SetTxPowerIndex(Adapter: padapter, PowerIndex: powerIndex, RFPath, Rate: Rates[i]); |
636 | } |
637 | } |
638 | |
639 | static s8 phy_GetWorldWideLimit(s8 *LimitTable) |
640 | { |
641 | s8 min = LimitTable[0]; |
642 | u8 i = 0; |
643 | |
644 | for (i = 0; i < MAX_REGULATION_NUM; ++i) { |
645 | if (LimitTable[i] < min) |
646 | min = LimitTable[i]; |
647 | } |
648 | |
649 | return min; |
650 | } |
651 | |
652 | static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Channel) |
653 | { |
654 | return Channel - 1; |
655 | } |
656 | |
657 | static s16 get_bandwidth_idx(const enum channel_width bandwidth) |
658 | { |
659 | switch (bandwidth) { |
660 | case CHANNEL_WIDTH_20: |
661 | return 0; |
662 | case CHANNEL_WIDTH_40: |
663 | return 1; |
664 | default: |
665 | return -1; |
666 | } |
667 | } |
668 | |
669 | static s16 get_rate_sctn_idx(const u8 rate) |
670 | { |
671 | switch (rate) { |
672 | case MGN_1M: case MGN_2M: case MGN_5_5M: case MGN_11M: |
673 | return 0; |
674 | case MGN_6M: case MGN_9M: case MGN_12M: case MGN_18M: |
675 | case MGN_24M: case MGN_36M: case MGN_48M: case MGN_54M: |
676 | return 1; |
677 | case MGN_MCS0: case MGN_MCS1: case MGN_MCS2: case MGN_MCS3: |
678 | case MGN_MCS4: case MGN_MCS5: case MGN_MCS6: case MGN_MCS7: |
679 | return 2; |
680 | default: |
681 | return -1; |
682 | } |
683 | } |
684 | |
685 | s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 reg_pwr_tbl_sel, |
686 | enum channel_width bandwidth, |
687 | u8 rf_path, u8 data_rate, u8 channel) |
688 | { |
689 | s16 idx_regulation = -1; |
690 | s16 idx_bandwidth = -1; |
691 | s16 idx_rate_sctn = -1; |
692 | s16 idx_channel = -1; |
693 | s8 pwr_lmt = MAX_POWER_INDEX; |
694 | struct hal_com_data *hal_data = GET_HAL_DATA(adapter); |
695 | s8 limits[10] = {0}; u8 i = 0; |
696 | |
697 | if (((adapter->registrypriv.RegEnableTxPowerLimit == 2) && |
698 | (hal_data->EEPROMRegulatory != 1)) || |
699 | (adapter->registrypriv.RegEnableTxPowerLimit == 0)) |
700 | return MAX_POWER_INDEX; |
701 | |
702 | switch (adapter->registrypriv.RegPwrTblSel) { |
703 | case 1: |
704 | idx_regulation = TXPWR_LMT_ETSI; |
705 | break; |
706 | case 2: |
707 | idx_regulation = TXPWR_LMT_MKK; |
708 | break; |
709 | case 3: |
710 | idx_regulation = TXPWR_LMT_FCC; |
711 | break; |
712 | case 4: |
713 | idx_regulation = TXPWR_LMT_WW; |
714 | break; |
715 | default: |
716 | idx_regulation = hal_data->Regulation2_4G; |
717 | break; |
718 | } |
719 | |
720 | idx_bandwidth = get_bandwidth_idx(bandwidth); |
721 | idx_rate_sctn = get_rate_sctn_idx(rate: data_rate); |
722 | |
723 | /* workaround for wrong index combination to obtain tx power limit, */ |
724 | /* OFDM only exists in BW 20M */ |
725 | /* CCK table will only be given in BW 20M */ |
726 | /* HT on 80M will reference to HT on 40M */ |
727 | if (idx_rate_sctn == 0 || idx_rate_sctn == 1) |
728 | idx_bandwidth = 0; |
729 | |
730 | channel = phy_GetChannelIndexOfTxPowerLimit(Channel: channel); |
731 | |
732 | if (idx_regulation == -1 || idx_bandwidth == -1 || |
733 | idx_rate_sctn == -1 || idx_channel == -1) |
734 | return MAX_POWER_INDEX; |
735 | |
736 | |
737 | for (i = 0; i < MAX_REGULATION_NUM; i++) |
738 | limits[i] = hal_data->TxPwrLimit_2_4G[i] |
739 | [idx_bandwidth] |
740 | [idx_rate_sctn] |
741 | [idx_channel] |
742 | [rf_path]; |
743 | |
744 | pwr_lmt = (idx_regulation == TXPWR_LMT_WW) ? |
745 | phy_GetWorldWideLimit(LimitTable: limits) : |
746 | hal_data->TxPwrLimit_2_4G[idx_regulation] |
747 | [idx_bandwidth] |
748 | [idx_rate_sctn] |
749 | [idx_channel] |
750 | [rf_path]; |
751 | |
752 | return pwr_lmt; |
753 | } |
754 | |
755 | void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter) |
756 | { |
757 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
758 | u8 BW40PwrBasedBm2_4G = 0x2E; |
759 | u8 regulation, bw, channel, rateSection; |
760 | s8 tempValue = 0, tempPwrLmt = 0; |
761 | u8 rfPath = 0; |
762 | |
763 | for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { |
764 | for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) { |
765 | for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) { |
766 | for (rateSection = 0; rateSection < MAX_RATE_SECTION_NUM; ++rateSection) { |
767 | tempPwrLmt = pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][RF_PATH_A]; |
768 | |
769 | for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) { |
770 | if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) { |
771 | if (rateSection == 2) /* HT 1T */ |
772 | BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, RfPath: rfPath, RateSection: HT_MCS0_MCS7); |
773 | else if (rateSection == 1) /* OFDM */ |
774 | BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, RfPath: rfPath, RateSection: OFDM); |
775 | else if (rateSection == 0) /* CCK */ |
776 | BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, RfPath: rfPath, RateSection: CCK); |
777 | } else |
778 | BW40PwrBasedBm2_4G = Adapter->registrypriv.RegPowerBase * 2; |
779 | |
780 | if (tempPwrLmt != MAX_POWER_INDEX) { |
781 | tempValue = tempPwrLmt - BW40PwrBasedBm2_4G; |
782 | pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][rfPath] = tempValue; |
783 | } |
784 | } |
785 | } |
786 | } |
787 | } |
788 | } |
789 | } |
790 | |
791 | void PHY_InitTxPowerLimit(struct adapter *Adapter) |
792 | { |
793 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
794 | u8 i, j, k, l, m; |
795 | |
796 | for (i = 0; i < MAX_REGULATION_NUM; ++i) { |
797 | for (j = 0; j < MAX_2_4G_BANDWIDTH_NUM; ++j) |
798 | for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) |
799 | for (m = 0; m < CHANNEL_MAX_NUMBER_2G; ++m) |
800 | for (l = 0; l < MAX_RF_PATH_NUM; ++l) |
801 | pHalData->TxPwrLimit_2_4G[i][j][k][m][l] = MAX_POWER_INDEX; |
802 | } |
803 | } |
804 | |
805 | void PHY_SetTxPowerLimit( |
806 | struct adapter *Adapter, |
807 | u8 *Regulation, |
808 | u8 *Bandwidth, |
809 | u8 *RateSection, |
810 | u8 *RfPath, |
811 | u8 *Channel, |
812 | u8 *PowerLimit |
813 | ) |
814 | { |
815 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
816 | u8 regulation = 0, bandwidth = 0, rateSection = 0, channel; |
817 | s8 powerLimit = 0, prevPowerLimit, channelIndex; |
818 | |
819 | GetU1ByteIntegerFromStringInDecimal(str: (s8 *)Channel, in: &channel); |
820 | GetU1ByteIntegerFromStringInDecimal(str: (s8 *)PowerLimit, in: &powerLimit); |
821 | |
822 | powerLimit = powerLimit > MAX_POWER_INDEX ? MAX_POWER_INDEX : powerLimit; |
823 | |
824 | if (eqNByte(str1: Regulation, str2: (u8 *)("FCC" ), num: 3)) |
825 | regulation = 0; |
826 | else if (eqNByte(str1: Regulation, str2: (u8 *)("MKK" ), num: 3)) |
827 | regulation = 1; |
828 | else if (eqNByte(str1: Regulation, str2: (u8 *)("ETSI" ), num: 4)) |
829 | regulation = 2; |
830 | else if (eqNByte(str1: Regulation, str2: (u8 *)("WW13" ), num: 4)) |
831 | regulation = 3; |
832 | |
833 | if (eqNByte(str1: RateSection, str2: (u8 *)("CCK" ), num: 3) && eqNByte(str1: RfPath, str2: (u8 *)("1T" ), num: 2)) |
834 | rateSection = 0; |
835 | else if (eqNByte(str1: RateSection, str2: (u8 *)("OFDM" ), num: 4) && eqNByte(str1: RfPath, str2: (u8 *)("1T" ), num: 2)) |
836 | rateSection = 1; |
837 | else if (eqNByte(str1: RateSection, str2: (u8 *)("HT" ), num: 2) && eqNByte(str1: RfPath, str2: (u8 *)("1T" ), num: 2)) |
838 | rateSection = 2; |
839 | else |
840 | return; |
841 | |
842 | if (eqNByte(str1: Bandwidth, str2: (u8 *)("20M" ), num: 3)) |
843 | bandwidth = 0; |
844 | else if (eqNByte(str1: Bandwidth, str2: (u8 *)("40M" ), num: 3)) |
845 | bandwidth = 1; |
846 | |
847 | channelIndex = phy_GetChannelIndexOfTxPowerLimit(Channel: channel); |
848 | |
849 | if (channelIndex == -1) |
850 | return; |
851 | |
852 | prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A]; |
853 | |
854 | if (powerLimit < prevPowerLimit) |
855 | pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A] = powerLimit; |
856 | } |
857 | |
858 | void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) |
859 | { |
860 | struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); |
861 | pHalData->Regulation2_4G = TXPWR_LMT_WW; |
862 | |
863 | switch (ChannelPlan) { |
864 | case RT_CHANNEL_DOMAIN_WORLD_NULL: |
865 | pHalData->Regulation2_4G = TXPWR_LMT_WW; |
866 | break; |
867 | case RT_CHANNEL_DOMAIN_ETSI1_NULL: |
868 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
869 | break; |
870 | case RT_CHANNEL_DOMAIN_FCC1_NULL: |
871 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
872 | break; |
873 | case RT_CHANNEL_DOMAIN_MKK1_NULL: |
874 | pHalData->Regulation2_4G = TXPWR_LMT_MKK; |
875 | break; |
876 | case RT_CHANNEL_DOMAIN_ETSI2_NULL: |
877 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
878 | break; |
879 | case RT_CHANNEL_DOMAIN_FCC1_FCC1: |
880 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
881 | break; |
882 | case RT_CHANNEL_DOMAIN_WORLD_ETSI1: |
883 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
884 | break; |
885 | case RT_CHANNEL_DOMAIN_MKK1_MKK1: |
886 | pHalData->Regulation2_4G = TXPWR_LMT_MKK; |
887 | break; |
888 | case RT_CHANNEL_DOMAIN_WORLD_KCC1: |
889 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
890 | break; |
891 | case RT_CHANNEL_DOMAIN_WORLD_FCC2: |
892 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
893 | break; |
894 | case RT_CHANNEL_DOMAIN_WORLD_FCC3: |
895 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
896 | break; |
897 | case RT_CHANNEL_DOMAIN_WORLD_FCC4: |
898 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
899 | break; |
900 | case RT_CHANNEL_DOMAIN_WORLD_FCC5: |
901 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
902 | break; |
903 | case RT_CHANNEL_DOMAIN_WORLD_FCC6: |
904 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
905 | break; |
906 | case RT_CHANNEL_DOMAIN_FCC1_FCC7: |
907 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
908 | break; |
909 | case RT_CHANNEL_DOMAIN_WORLD_ETSI2: |
910 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
911 | break; |
912 | case RT_CHANNEL_DOMAIN_WORLD_ETSI3: |
913 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
914 | break; |
915 | case RT_CHANNEL_DOMAIN_MKK1_MKK2: |
916 | pHalData->Regulation2_4G = TXPWR_LMT_MKK; |
917 | break; |
918 | case RT_CHANNEL_DOMAIN_MKK1_MKK3: |
919 | pHalData->Regulation2_4G = TXPWR_LMT_MKK; |
920 | break; |
921 | case RT_CHANNEL_DOMAIN_FCC1_NCC1: |
922 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
923 | break; |
924 | case RT_CHANNEL_DOMAIN_FCC1_NCC2: |
925 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
926 | break; |
927 | case RT_CHANNEL_DOMAIN_GLOBAL_NULL: |
928 | pHalData->Regulation2_4G = TXPWR_LMT_WW; |
929 | break; |
930 | case RT_CHANNEL_DOMAIN_ETSI1_ETSI4: |
931 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
932 | break; |
933 | case RT_CHANNEL_DOMAIN_FCC1_FCC2: |
934 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
935 | break; |
936 | case RT_CHANNEL_DOMAIN_FCC1_NCC3: |
937 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
938 | break; |
939 | case RT_CHANNEL_DOMAIN_WORLD_ETSI5: |
940 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
941 | break; |
942 | case RT_CHANNEL_DOMAIN_FCC1_FCC8: |
943 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
944 | break; |
945 | case RT_CHANNEL_DOMAIN_WORLD_ETSI6: |
946 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
947 | break; |
948 | case RT_CHANNEL_DOMAIN_WORLD_ETSI7: |
949 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
950 | break; |
951 | case RT_CHANNEL_DOMAIN_WORLD_ETSI8: |
952 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
953 | break; |
954 | case RT_CHANNEL_DOMAIN_WORLD_ETSI9: |
955 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
956 | break; |
957 | case RT_CHANNEL_DOMAIN_WORLD_ETSI10: |
958 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
959 | break; |
960 | case RT_CHANNEL_DOMAIN_WORLD_ETSI11: |
961 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
962 | break; |
963 | case RT_CHANNEL_DOMAIN_FCC1_NCC4: |
964 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
965 | break; |
966 | case RT_CHANNEL_DOMAIN_WORLD_ETSI12: |
967 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
968 | break; |
969 | case RT_CHANNEL_DOMAIN_FCC1_FCC9: |
970 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
971 | break; |
972 | case RT_CHANNEL_DOMAIN_WORLD_ETSI13: |
973 | pHalData->Regulation2_4G = TXPWR_LMT_ETSI; |
974 | break; |
975 | case RT_CHANNEL_DOMAIN_FCC1_FCC10: |
976 | pHalData->Regulation2_4G = TXPWR_LMT_FCC; |
977 | break; |
978 | case RT_CHANNEL_DOMAIN_REALTEK_DEFINE: /* Realtek Reserve */ |
979 | pHalData->Regulation2_4G = TXPWR_LMT_WW; |
980 | break; |
981 | default: |
982 | break; |
983 | } |
984 | } |
985 | |