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