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, path, MGN_11M);
72		phy_SetTxPowerByRateBase(padapter, path, CCK, base);
73
74		base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
75		phy_SetTxPowerByRateBase(padapter, path, OFDM, base);
76
77		base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
78		phy_SetTxPowerByRateBase(padapter, path, HT_MCS0_MCS7, 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(MGN_6M);
154		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_9M);
155		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_12M);
156		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_24M);
167		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_36M);
168		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_48M);
169		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(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(MGN_2M);
187			RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_5_5M);
188			RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(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(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(MGN_MCS0);
204		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS1);
205		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS2);
206		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_MCS4);
217		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS5);
218		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS6);
219		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_1M);
229		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
230		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_1M);
243		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
244		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_5_5M);
245		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_6M);
258		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_9M);
259		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_12M);
260		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_24M);
273		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_36M);
274		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_48M);
275		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_MCS0);
288		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS1);
289		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS2);
290		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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(MGN_MCS4);
303		RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS5);
304		RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS6);
305		RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(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, Data, rateIndex, PwrByRateVal, &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, path, MGN_11M);
391		for (i = 0; i < ARRAY_SIZE(cckRates); ++i) {
392			value = PHY_GetTxPowerByRate(padapter, path, cckRates[i]);
393			PHY_SetTxPowerByRate(padapter, path, cckRates[i], value - base);
394		}
395
396		/*  OFDM */
397		base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
398		for (i = 0; i < sizeof(ofdmRates); ++i) {
399			value = PHY_GetTxPowerByRate(padapter, path, ofdmRates[i]);
400			PHY_SetTxPowerByRate(padapter, path, ofdmRates[i], value - base);
401		}
402
403		/*  HT MCS0~7 */
404		base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
405		for (i = 0; i < sizeof(mcs0_7Rates); ++i) {
406			value = PHY_GetTxPowerByRate(padapter, path, mcs0_7Rates[i]);
407			PHY_SetTxPowerByRate(padapter, path, mcs0_7Rates[i], 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					     pHalData->CurrentChannelBW,
432					     Channel, 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					       pHalData->CurrentChannelBW,
439					       Channel, 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					       pHalData->CurrentChannelBW,
446					       Channel, 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(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(Adapter, path, channel, CCK);
616
617	PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, OFDM);
618	PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, 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, Rates[i], BandWidth, Channel);
635		PHY_SetTxPowerIndex(padapter, powerIndex, RFPath, 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(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);
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(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, HT_MCS0_MCS7);
773							else if (rateSection == 1) /*  OFDM */
774								BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, OFDM);
775							else if (rateSection == 0) /*  CCK */
776								BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, 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((s8 *)Channel, &channel);
820	GetU1ByteIntegerFromStringInDecimal((s8 *)PowerLimit, &powerLimit);
821
822	powerLimit = powerLimit > MAX_POWER_INDEX ? MAX_POWER_INDEX : powerLimit;
823
824	if (eqNByte(Regulation, (u8 *)("FCC"), 3))
825		regulation = 0;
826	else if (eqNByte(Regulation, (u8 *)("MKK"), 3))
827		regulation = 1;
828	else if (eqNByte(Regulation, (u8 *)("ETSI"), 4))
829		regulation = 2;
830	else if (eqNByte(Regulation, (u8 *)("WW13"), 4))
831		regulation = 3;
832
833	if (eqNByte(RateSection, (u8 *)("CCK"), 3) && eqNByte(RfPath, (u8 *)("1T"), 2))
834		rateSection = 0;
835	else if (eqNByte(RateSection, (u8 *)("OFDM"), 4) && eqNByte(RfPath, (u8 *)("1T"), 2))
836		rateSection = 1;
837	else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("1T"), 2))
838		rateSection = 2;
839	else
840		return;
841
842	if (eqNByte(Bandwidth, (u8 *)("20M"), 3))
843		bandwidth = 0;
844	else if (eqNByte(Bandwidth, (u8 *)("40M"), 3))
845		bandwidth = 1;
846
847	channelIndex = phy_GetChannelIndexOfTxPowerLimit(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