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