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
13u8 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
39static void
40phy_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
63static void
64phy_StoreTxPowerByRateBase(
65struct 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
82u8 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
137void
138PHY_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
318static 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
335static 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
345void 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
355void 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
373static void
374phy_ConvertTxPowerByRateInDbmToRelativeValues(
375struct 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 */
416void PHY_TxPowerByRateConfiguration(struct adapter *padapter)
417{
418 phy_StoreTxPowerByRateBase(padapter);
419 phy_ConvertTxPowerByRateInDbmToRelativeValues(padapter);
420}
421
422void 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
452u8 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
487s8 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
504u8 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
574s8 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
594void 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
613void 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
621void 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
639static 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
652static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Channel)
653{
654 return Channel - 1;
655}
656
657static 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
669static 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
685s8 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
755void 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
791void 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
805void 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
858void 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

source code of linux/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c