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 <rtl8723b_hal.h>
11 
12 /**
13  * phy_CalculateBitShift - Get shifted position of the BitMask.
14  * @BitMask: Bitmask.
15  *
16  * Return:	Return the shift bit position of the mask
17  */
18 static	u32 phy_CalculateBitShift(u32 BitMask)
19 {
20 	u32 i;
21 
22 	for (i = 0; i <= 31; i++) {
23 		if (((BitMask>>i) &  0x1) == 1)
24 			break;
25 	}
26 	return i;
27 }
28 
29 
30 /**
31  * PHY_QueryBBReg_8723B - Read "specific bits" from BB register.
32  * @Adapter:
33  * @RegAddr:	The target address to be readback
34  * @BitMask:	The target bit position in the target address
35  *				to be readback
36  *
37  * Return:	The readback register value
38  *
39  * .. Note::	This function is equal to "GetRegSetting" in PHY programming
40  *			guide
41  */
42 u32 PHY_QueryBBReg_8723B(struct adapter *Adapter, u32 RegAddr, u32 BitMask)
43 {
44 	u32 OriginalValue, BitShift;
45 
46 	OriginalValue = rtw_read32(Adapter, RegAddr);
47 	BitShift = phy_CalculateBitShift(BitMask);
48 
49 	return (OriginalValue & BitMask) >> BitShift;
50 
51 }
52 
53 
54 /**
55  * PHY_SetBBReg_8723B - Write "Specific bits" to BB register (page 8~).
56  * @Adapter:
57  * @RegAddr:	The target address to be modified
58  * @BitMask:	The target bit position in the target address
59  *				to be modified
60  * @Data:		The new register value in the target bit position
61  *				of the target address
62  *
63  * .. Note::	This function is equal to "PutRegSetting" in PHY programming
64  *			guide
65  */
66 
67 void PHY_SetBBReg_8723B(
68 	struct adapter *Adapter,
69 	u32 RegAddr,
70 	u32 BitMask,
71 	u32 Data
72 )
73 {
74 	/* u16 BBWaitCounter	= 0; */
75 	u32 OriginalValue, BitShift;
76 
77 	if (BitMask != bMaskDWord) { /* if not "double word" write */
78 		OriginalValue = rtw_read32(Adapter, RegAddr);
79 		BitShift = phy_CalculateBitShift(BitMask);
80 		Data = ((OriginalValue & (~BitMask)) | ((Data << BitShift) & BitMask));
81 	}
82 
83 	rtw_write32(Adapter, RegAddr, Data);
84 
85 }
86 
87 
88 /*  */
89 /*  2. RF register R/W API */
90 /*  */
91 
92 static u32 phy_RFSerialRead_8723B(
93 	struct adapter *Adapter, enum rf_path eRFPath, u32 Offset
94 )
95 {
96 	u32 retValue = 0;
97 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
98 	struct bb_register_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
99 	u32 NewOffset;
100 	u32 tmplong2;
101 	u8 RfPiEnable = 0;
102 	u32 MaskforPhySet = 0;
103 	int i = 0;
104 
105 	/*  */
106 	/*  Make sure RF register offset is correct */
107 	/*  */
108 	Offset &= 0xff;
109 
110 	NewOffset = Offset;
111 
112 	if (eRFPath == RF_PATH_A) {
113 		tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);
114 		tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge;	/* T65 RF */
115 		PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2&(~bLSSIReadEdge));
116 	} else {
117 		tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XB_HSSIParameter2|MaskforPhySet, bMaskDWord);
118 		tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge;	/* T65 RF */
119 		PHY_SetBBReg(Adapter, rFPGA0_XB_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2&(~bLSSIReadEdge));
120 	}
121 
122 	tmplong2 = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord);
123 	PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2 & (~bLSSIReadEdge));
124 	PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2|MaskforPhySet, bMaskDWord, tmplong2 | bLSSIReadEdge);
125 
126 	udelay(10);
127 
128 	for (i = 0; i < 2; i++)
129 		udelay(MAX_STALL_TIME);
130 	udelay(10);
131 
132 	if (eRFPath == RF_PATH_A)
133 		RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter1|MaskforPhySet, BIT8);
134 	else if (eRFPath == RF_PATH_B)
135 		RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XB_HSSIParameter1|MaskforPhySet, BIT8);
136 
137 	if (RfPiEnable) {
138 		/*  Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */
139 		retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi|MaskforPhySet, bLSSIReadBackData);
140 	} else {
141 		/* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */
142 		retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack|MaskforPhySet, bLSSIReadBackData);
143 	}
144 	return retValue;
145 
146 }
147 
148 /**
149  * phy_RFSerialWrite_8723B - Write data to RF register (page 8~).
150  * @Adapter:
151  * @eRFPath:	Radio path of A/B/C/D
152  * @Offset:	The target address to be read
153  * @Data:	The new register Data in the target bit position
154  *			of the target to be read
155  *
156  * .. Note::	Threre are three types of serial operations:
157  *		1. Software serial write
158  *		2. Hardware LSSI-Low Speed Serial Interface
159  *		3. Hardware HSSI-High speed
160  *		serial write. Driver need to implement (1) and (2).
161  *		This function is equal to the combination of RF_ReadReg() and  RFLSSIRead()
162  *
163  * .. Note::		  For RF8256 only
164  *		 The total count of RTL8256(Zebra4) register is around 36 bit it only employs
165  *		 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10])
166  *		 to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration
167  *		 programming guide" for more details.
168  *		 Thus, we define a sub-finction for RTL8526 register address conversion
169  *	       ===========================================================
170  *		 Register Mode		RegCTL[1]		RegCTL[0]		Note
171  *							(Reg00[12])		(Reg00[10])
172  *	       ===========================================================
173  *		 Reg_Mode0				0				x			Reg 0 ~15(0x0 ~ 0xf)
174  *	       ------------------------------------------------------------------
175  *		 Reg_Mode1				1				0			Reg 16 ~30(0x1 ~ 0xf)
176  *	       ------------------------------------------------------------------
177  *		 Reg_Mode2				1				1			Reg 31 ~ 45(0x1 ~ 0xf)
178  *	       ------------------------------------------------------------------
179  *
180  *2008/09/02	MH	Add 92S RF definition
181  *
182  *
183  *
184  */
185 static void phy_RFSerialWrite_8723B(
186 	struct adapter *Adapter,
187 	enum rf_path eRFPath,
188 	u32 Offset,
189 	u32 Data
190 )
191 {
192 	u32 DataAndAddr = 0;
193 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
194 	struct bb_register_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
195 	u32 NewOffset;
196 
197 	Offset &= 0xff;
198 
199 	/*  */
200 	/*  Switch page for 8256 RF IC */
201 	/*  */
202 	NewOffset = Offset;
203 
204 	/*  */
205 	/*  Put write addr in [5:0]  and write data in [31:16] */
206 	/*  */
207 	DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff;	/*  T65 RF */
208 	/*  */
209 	/*  Write Operation */
210 	/*  */
211 	PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
212 }
213 
214 
215 /**
216  * PHY_QueryRFReg_8723B - Query "Specific bits" to RF register (page 8~).
217  * @Adapter:
218  * @eRFPath:	Radio path of A/B/C/D
219  * @RegAddr:	The target address to be read
220  * @BitMask:	The target bit position in the target address
221  *				to be read
222  *
223  * Return:	Readback value
224  *
225  * .. Note::	This function is equal to "GetRFRegSetting" in PHY
226  *			programming guide
227  */
228 u32 PHY_QueryRFReg_8723B(
229 	struct adapter *Adapter,
230 	u8 eRFPath,
231 	u32 RegAddr,
232 	u32 BitMask
233 )
234 {
235 	u32 Original_Value, BitShift;
236 
237 	Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr);
238 	BitShift =  phy_CalculateBitShift(BitMask);
239 
240 	return (Original_Value & BitMask) >> BitShift;
241 }
242 
243 /**
244  * PHY_SetRFReg_8723B - Write "Specific bits" to RF register (page 8~).
245  * @Adapter:
246  * @eRFPath:	Radio path of A/B/C/D
247  * @RegAddr:	The target address to be modified
248  * @BitMask:	The target bit position in the target address
249  *				to be modified
250  * @Data:	The new register Data in the target bit position
251  *								of the target address
252  *
253  * .. Note::	This function is equal to "PutRFRegSetting" in PHY
254  *			programming guide.
255  */
256 void PHY_SetRFReg_8723B(
257 	struct adapter *Adapter,
258 	u8 eRFPath,
259 	u32 RegAddr,
260 	u32 BitMask,
261 	u32 Data
262 )
263 {
264 	u32 Original_Value, BitShift;
265 
266 	/*  RF data is 12 bits only */
267 	if (BitMask != bRFRegOffsetMask) {
268 		Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr);
269 		BitShift =  phy_CalculateBitShift(BitMask);
270 		Data = ((Original_Value & (~BitMask)) | (Data<<BitShift));
271 	}
272 
273 	phy_RFSerialWrite_8723B(Adapter, eRFPath, RegAddr, Data);
274 }
275 
276 
277 /*  */
278 /*  3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */
279 /*  */
280 
281 
282 /*-----------------------------------------------------------------------------
283  * PHY_MACConfig8192C - Condig MAC by header file or parameter file.
284  *
285  * Revised History:
286  *  When		Who		Remark
287  *  08/12/2008	MHC		Create Version 0.
288  *
289  *---------------------------------------------------------------------------
290  */
291 s32 PHY_MACConfig8723B(struct adapter *Adapter)
292 {
293 	struct hal_com_data	*pHalData = GET_HAL_DATA(Adapter);
294 
295 	ODM_ReadAndConfig_MP_8723B_MAC_REG(&pHalData->odmpriv);
296 	return _SUCCESS;
297 }
298 
299 /**
300  * phy_InitBBRFRegisterDefinition - Initialize Register definition offset for
301  *									Radio Path A/B/C/D
302  * @Adapter:
303  *
304  * .. Note::		The initialization value is constant and it should never be changes
305  */
306 static void phy_InitBBRFRegisterDefinition(struct adapter *Adapter)
307 {
308 	struct hal_com_data		*pHalData = GET_HAL_DATA(Adapter);
309 
310 	/*  RF Interface Sowrtware Control */
311 	pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /*  16 LSBs if read 32-bit from 0x870 */
312 	pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /*  16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
313 
314 	/*  RF Interface Output (and Enable) */
315 	pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /*  16 LSBs if read 32-bit from 0x860 */
316 	pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /*  16 LSBs if read 32-bit from 0x864 */
317 
318 	/*  RF Interface (Output and)  Enable */
319 	pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /*  16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
320 	pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /*  16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
321 
322 	pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */
323 	pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
324 
325 	pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;  /* wire control parameter2 */
326 	pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;  /* wire control parameter2 */
327 
328 	/*  Tranceiver Readback LSSI/HSPI mode */
329 	pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
330 	pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
331 	pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
332 	pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
333 
334 }
335 
336 static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
337 {
338 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
339 
340 	/*  Read Tx Power Limit File */
341 	PHY_InitTxPowerLimit(Adapter);
342 	if (
343 		Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
344 		(Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
345 	) {
346 		ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
347 					   CONFIG_RF_TXPWR_LMT, 0);
348 	}
349 
350 	/*  */
351 	/*  1. Read PHY_REG.TXT BB INIT!! */
352 	/*  */
353 	ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG);
354 
355 	/*  If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
356 	PHY_InitTxPowerByRate(Adapter);
357 	if (
358 		Adapter->registrypriv.RegEnableTxPowerByRate == 1 ||
359 		(Adapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory != 2)
360 	) {
361 		ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv,
362 					   CONFIG_BB_PHY_REG_PG);
363 
364 		if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE)
365 			PHY_TxPowerByRateConfiguration(Adapter);
366 
367 		if (
368 			Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
369 			(Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
370 		)
371 			PHY_ConvertTxPowerLimitToPowerIndex(Adapter);
372 	}
373 
374 	/*  */
375 	/*  2. Read BB AGC table Initialization */
376 	/*  */
377 	ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB);
378 
379 	return _SUCCESS;
380 }
381 
382 
383 int PHY_BBConfig8723B(struct adapter *Adapter)
384 {
385 	int	rtStatus = _SUCCESS;
386 	struct hal_com_data	*pHalData = GET_HAL_DATA(Adapter);
387 	u32 RegVal;
388 	u8 CrystalCap;
389 
390 	phy_InitBBRFRegisterDefinition(Adapter);
391 
392 	/*  Enable BB and RF */
393 	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
394 	rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal|BIT13|BIT0|BIT1));
395 
396 	rtw_write32(Adapter, 0x948, 0x280);	/*  Others use Antenna S1 */
397 
398 	rtw_write8(Adapter, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
399 
400 	msleep(1);
401 
402 	PHY_SetRFReg(Adapter, RF_PATH_A, 0x1, 0xfffff, 0x780);
403 
404 	rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_PPLL|FEN_PCIEA|FEN_DIO_PCIE|FEN_BB_GLB_RSTn|FEN_BBRSTB);
405 
406 	rtw_write8(Adapter, REG_AFE_XTAL_CTRL+1, 0x80);
407 
408 	/*  */
409 	/*  Config BB and AGC */
410 	/*  */
411 	rtStatus = phy_BB8723b_Config_ParaFile(Adapter);
412 
413 	/*  0x2C[23:18] = 0x2C[17:12] = CrystalCap */
414 	CrystalCap = pHalData->CrystalCap & 0x3F;
415 	PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000, (CrystalCap | (CrystalCap << 6)));
416 
417 	return rtStatus;
418 }
419 
420 static void phy_LCK_8723B(struct adapter *Adapter)
421 {
422 	PHY_SetRFReg(Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0);
423 	PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, 0x8C01);
424 	mdelay(200);
425 	PHY_SetRFReg(Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0);
426 }
427 
428 int PHY_RFConfig8723B(struct adapter *Adapter)
429 {
430 	int rtStatus = _SUCCESS;
431 
432 	/*  */
433 	/*  RF config */
434 	/*  */
435 	rtStatus = PHY_RF6052_Config8723B(Adapter);
436 
437 	phy_LCK_8723B(Adapter);
438 
439 	return rtStatus;
440 }
441 
442 /**************************************************************************************************************
443  *   Description:
444  *       The low-level interface to set TxAGC , called by both MP and Normal Driver.
445  *
446  *                                                                                    <20120830, Kordan>
447  **************************************************************************************************************/
448 
449 void PHY_SetTxPowerIndex(
450 	struct adapter *Adapter,
451 	u32 PowerIndex,
452 	u8 RFPath,
453 	u8 Rate
454 )
455 {
456 	if (RFPath == RF_PATH_A || RFPath == RF_PATH_B) {
457 		switch (Rate) {
458 		case MGN_1M:
459 			PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, PowerIndex);
460 			break;
461 		case MGN_2M:
462 			PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte1, PowerIndex);
463 			break;
464 		case MGN_5_5M:
465 			PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte2, PowerIndex);
466 			break;
467 		case MGN_11M:
468 			PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte3, PowerIndex);
469 			break;
470 
471 		case MGN_6M:
472 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte0, PowerIndex);
473 			break;
474 		case MGN_9M:
475 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte1, PowerIndex);
476 			break;
477 		case MGN_12M:
478 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte2, PowerIndex);
479 			break;
480 		case MGN_18M:
481 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate18_06, bMaskByte3, PowerIndex);
482 			break;
483 
484 		case MGN_24M:
485 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte0, PowerIndex);
486 			break;
487 		case MGN_36M:
488 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte1, PowerIndex);
489 			break;
490 		case MGN_48M:
491 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte2, PowerIndex);
492 			break;
493 		case MGN_54M:
494 			PHY_SetBBReg(Adapter, rTxAGC_A_Rate54_24, bMaskByte3, PowerIndex);
495 			break;
496 
497 		case MGN_MCS0:
498 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte0, PowerIndex);
499 			break;
500 		case MGN_MCS1:
501 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte1, PowerIndex);
502 			break;
503 		case MGN_MCS2:
504 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte2, PowerIndex);
505 			break;
506 		case MGN_MCS3:
507 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte3, PowerIndex);
508 			break;
509 
510 		case MGN_MCS4:
511 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte0, PowerIndex);
512 			break;
513 		case MGN_MCS5:
514 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte1, PowerIndex);
515 			break;
516 		case MGN_MCS6:
517 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte2, PowerIndex);
518 			break;
519 		case MGN_MCS7:
520 			PHY_SetBBReg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte3, PowerIndex);
521 			break;
522 
523 		default:
524 			break;
525 		}
526 	}
527 }
528 
529 u8 PHY_GetTxPowerIndex(
530 	struct adapter *padapter,
531 	u8 RFPath,
532 	u8 Rate,
533 	enum channel_width BandWidth,
534 	u8 Channel
535 )
536 {
537 	struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
538 	s8 txPower = 0, powerDiffByRate = 0, limit = 0;
539 
540 	txPower = (s8) PHY_GetTxPowerIndexBase(padapter, RFPath, Rate, BandWidth, Channel);
541 	powerDiffByRate = PHY_GetTxPowerByRate(padapter, RF_PATH_A, Rate);
542 
543 	limit = phy_get_tx_pwr_lmt(
544 		padapter,
545 		padapter->registrypriv.RegPwrTblSel,
546 		pHalData->CurrentChannelBW,
547 		RFPath,
548 		Rate,
549 		pHalData->CurrentChannel
550 	);
551 
552 	powerDiffByRate = powerDiffByRate > limit ? limit : powerDiffByRate;
553 	txPower += powerDiffByRate;
554 
555 	txPower += PHY_GetTxPowerTrackingOffset(padapter, RFPath, Rate);
556 
557 	if (txPower > MAX_POWER_INDEX)
558 		txPower = MAX_POWER_INDEX;
559 
560 	return (u8) txPower;
561 }
562 
563 void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel)
564 {
565 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
566 	struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
567 	struct fat_t *pDM_FatTable = &pDM_Odm->DM_FatTable;
568 	u8 RFPath = RF_PATH_A;
569 
570 	if (pHalData->AntDivCfg) {/*  antenna diversity Enable */
571 		RFPath = ((pDM_FatTable->RxIdleAnt == MAIN_ANT) ? RF_PATH_A : RF_PATH_B);
572 	} else { /*  antenna diversity disable */
573 		RFPath = pHalData->ant_path;
574 	}
575 
576 	PHY_SetTxPowerLevelByPath(Adapter, Channel, RFPath);
577 }
578 
579 void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel)
580 {
581 }
582 
583 static void phy_SetRegBW_8723B(
584 	struct adapter *Adapter, enum channel_width CurrentBW
585 )
586 {
587 	u16 RegRfMod_BW, u2tmp = 0;
588 	RegRfMod_BW = rtw_read16(Adapter, REG_TRXPTCL_CTL_8723B);
589 
590 	switch (CurrentBW) {
591 	case CHANNEL_WIDTH_20:
592 		rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (RegRfMod_BW & 0xFE7F)); /*  BIT 7 = 0, BIT 8 = 0 */
593 		break;
594 
595 	case CHANNEL_WIDTH_40:
596 		u2tmp = RegRfMod_BW | BIT7;
597 		rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (u2tmp & 0xFEFF)); /*  BIT 7 = 1, BIT 8 = 0 */
598 		break;
599 
600 	default:
601 		break;
602 	}
603 }
604 
605 static u8 phy_GetSecondaryChnl_8723B(struct adapter *Adapter)
606 {
607 	u8 SCSettingOf40 = 0, SCSettingOf20 = 0;
608 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
609 
610 	if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
611 		if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
612 			SCSettingOf20 = HT_DATA_SC_20_UPPER_OF_40MHZ;
613 		else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
614 			SCSettingOf20 = HT_DATA_SC_20_LOWER_OF_40MHZ;
615 	}
616 
617 	return  (SCSettingOf40 << 4) | SCSettingOf20;
618 }
619 
620 static void phy_PostSetBwMode8723B(struct adapter *Adapter)
621 {
622 	u8 SubChnlNum = 0;
623 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
624 
625 
626 	/* 3 Set Reg668 Reg440 BW */
627 	phy_SetRegBW_8723B(Adapter, pHalData->CurrentChannelBW);
628 
629 	/* 3 Set Reg483 */
630 	SubChnlNum = phy_GetSecondaryChnl_8723B(Adapter);
631 	rtw_write8(Adapter, REG_DATA_SC_8723B, SubChnlNum);
632 
633 	/* 3 */
634 	/* 3<2>Set PHY related register */
635 	/* 3 */
636 	switch (pHalData->CurrentChannelBW) {
637 	/* 20 MHz channel*/
638 	case CHANNEL_WIDTH_20:
639 		PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0);
640 
641 		PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0);
642 
643 		PHY_SetBBReg(Adapter, rOFDM0_TxPseudoNoiseWgt, (BIT31|BIT30), 0x0);
644 		break;
645 
646 	/* 40 MHz channel*/
647 	case CHANNEL_WIDTH_40:
648 		PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1);
649 
650 		PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1);
651 
652 		/*  Set Control channel to upper or lower. These settings are required only for 40MHz */
653 		PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, (pHalData->nCur40MhzPrimeSC>>1));
654 
655 		PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, pHalData->nCur40MhzPrimeSC);
656 
657 		PHY_SetBBReg(Adapter, 0x818, (BIT26|BIT27), (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
658 		break;
659 	default:
660 		break;
661 	}
662 
663 	/* 3<3>Set RF related register */
664 	PHY_RF6052SetBandwidth8723B(Adapter, pHalData->CurrentChannelBW);
665 }
666 
667 static void phy_SwChnl8723B(struct adapter *padapter)
668 {
669 	struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
670 	u8 channelToSW = pHalData->CurrentChannel;
671 
672 	if (pHalData->rf_chip == RF_PSEUDO_11N)
673 		return;
674 	pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff00) | channelToSW);
675 	PHY_SetRFReg(padapter, RF_PATH_A, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
676 	PHY_SetRFReg(padapter, RF_PATH_B, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
677 }
678 
679 static void phy_SwChnlAndSetBwMode8723B(struct adapter *Adapter)
680 {
681 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
682 
683 	if (Adapter->bDriverStopped || Adapter->bSurpriseRemoved)
684 		return;
685 
686 	if (pHalData->bSwChnl) {
687 		phy_SwChnl8723B(Adapter);
688 		pHalData->bSwChnl = false;
689 	}
690 
691 	if (pHalData->bSetChnlBW) {
692 		phy_PostSetBwMode8723B(Adapter);
693 		pHalData->bSetChnlBW = false;
694 	}
695 
696 	PHY_SetTxPowerLevel8723B(Adapter, pHalData->CurrentChannel);
697 }
698 
699 static void PHY_HandleSwChnlAndSetBW8723B(
700 	struct adapter *Adapter,
701 	bool bSwitchChannel,
702 	bool bSetBandWidth,
703 	u8 ChannelNum,
704 	enum channel_width ChnlWidth,
705 	enum extchnl_offset ExtChnlOffsetOf40MHz,
706 	enum extchnl_offset ExtChnlOffsetOf80MHz,
707 	u8 CenterFrequencyIndex1
708 )
709 {
710 	/* static bool		bInitialzed = false; */
711 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
712 	u8 tmpChannel = pHalData->CurrentChannel;
713 	enum channel_width tmpBW = pHalData->CurrentChannelBW;
714 	u8 tmpnCur40MhzPrimeSC = pHalData->nCur40MhzPrimeSC;
715 	u8 tmpnCur80MhzPrimeSC = pHalData->nCur80MhzPrimeSC;
716 	u8 tmpCenterFrequencyIndex1 = pHalData->CurrentCenterFrequencyIndex1;
717 
718 	/* check is swchnl or setbw */
719 	if (!bSwitchChannel && !bSetBandWidth)
720 		return;
721 
722 	/* skip change for channel or bandwidth is the same */
723 	if (bSwitchChannel) {
724 		{
725 			if (HAL_IsLegalChannel(Adapter, ChannelNum))
726 				pHalData->bSwChnl = true;
727 		}
728 	}
729 
730 	if (bSetBandWidth)
731 		pHalData->bSetChnlBW = true;
732 
733 	if (!pHalData->bSetChnlBW && !pHalData->bSwChnl)
734 		return;
735 
736 
737 	if (pHalData->bSwChnl) {
738 		pHalData->CurrentChannel = ChannelNum;
739 		pHalData->CurrentCenterFrequencyIndex1 = ChannelNum;
740 	}
741 
742 
743 	if (pHalData->bSetChnlBW) {
744 		pHalData->CurrentChannelBW = ChnlWidth;
745 		pHalData->nCur40MhzPrimeSC = ExtChnlOffsetOf40MHz;
746 		pHalData->nCur80MhzPrimeSC = ExtChnlOffsetOf80MHz;
747 		pHalData->CurrentCenterFrequencyIndex1 = CenterFrequencyIndex1;
748 	}
749 
750 	/* Switch workitem or set timer to do switch channel or setbandwidth operation */
751 	if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) {
752 		phy_SwChnlAndSetBwMode8723B(Adapter);
753 	} else {
754 		if (pHalData->bSwChnl) {
755 			pHalData->CurrentChannel = tmpChannel;
756 			pHalData->CurrentCenterFrequencyIndex1 = tmpChannel;
757 		}
758 
759 		if (pHalData->bSetChnlBW) {
760 			pHalData->CurrentChannelBW = tmpBW;
761 			pHalData->nCur40MhzPrimeSC = tmpnCur40MhzPrimeSC;
762 			pHalData->nCur80MhzPrimeSC = tmpnCur80MhzPrimeSC;
763 			pHalData->CurrentCenterFrequencyIndex1 = tmpCenterFrequencyIndex1;
764 		}
765 	}
766 }
767 
768 void PHY_SetBWMode8723B(
769 	struct adapter *Adapter,
770 	enum channel_width Bandwidth, /*  20M or 40M */
771 	unsigned char Offset /*  Upper, Lower, or Don't care */
772 )
773 {
774 	struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
775 
776 	PHY_HandleSwChnlAndSetBW8723B(Adapter, false, true, pHalData->CurrentChannel, Bandwidth, Offset, Offset, pHalData->CurrentChannel);
777 }
778 
779 /*  Call after initialization */
780 void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel)
781 {
782 	PHY_HandleSwChnlAndSetBW8723B(Adapter, true, false, channel, 0, 0, 0, channel);
783 }
784 
785 void PHY_SetSwChnlBWMode8723B(
786 	struct adapter *Adapter,
787 	u8 channel,
788 	enum channel_width Bandwidth,
789 	u8 Offset40,
790 	u8 Offset80
791 )
792 {
793 	PHY_HandleSwChnlAndSetBW8723B(Adapter, true, true, channel, Bandwidth, Offset40, Offset80, channel);
794 }
795