File Index
Files and directories
Sign in
FILE

rtl8723b_phycfg.c

File preview with syntax highlighting.

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