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