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