1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 /******************************************************************************
23 * Module: rtl8192c_rf6052.c ( Source C File)
25 * Note: Provide RF 6052 series relative API.
36 * 09/25/2008 MHC Create initial version.
37 * 11/05/2008 MHC Add API for tw power setting.
40 ******************************************************************************/
42 #define _RTL8188E_RF6052_C_
44 #include <osdep_service.h>
45 #include <drv_types.h>
47 #include <rtl8188e_hal.h>
49 /*---------------------------Define Local Constant---------------------------*/
50 /* Define local structure for debug!!!!! */
52 /* Shadow register value */
54 /* Compare or not flag */
56 /* Record If it had ever modified unpredicted */
64 /*---------------------------Define Local Constant---------------------------*/
67 /*------------------------Define global variable-----------------------------*/
69 /*------------------------Define local variable------------------------------*/
71 /*-----------------------------------------------------------------------------
72 * Function: RF_ChangeTxPath
74 * Overview: For RL6052, we must change some RF settign for 1T or 2T.
76 * Input: u16 DataRate 0x80-8f, 0x90-9f
84 * 09/25/2008 MHC Create Version 0.
85 * Firmwaer support the utility later.
87 *---------------------------------------------------------------------------*/
88 void rtl8188e_RF_ChangeTxPath(struct adapter *Adapter, u16 DataRate)
90 /* We do not support gain table change inACUT now !!!! Delete later !!! */
91 } /* RF_ChangeTxPath */
94 /*-----------------------------------------------------------------------------
95 * Function: PHY_RF6052SetBandwidth()
97 * Overview: This function is called by SetBWModeCallback8190Pci() only
99 * Input: struct adapter *Adapter
100 * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
106 * Note: For RF type 0222D
107 *---------------------------------------------------------------------------*/
108 void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter,
109 enum ht_channel_width Bandwidth)
111 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
114 case HT_CHANNEL_WIDTH_20:
115 pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10) | BIT(11));
116 PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
118 case HT_CHANNEL_WIDTH_40:
119 pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10));
120 PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
127 /*-----------------------------------------------------------------------------
128 * Function: PHY_RF6052SetCckTxPower
140 * 11/05/2008 MHC Simulate 8192series..
142 *---------------------------------------------------------------------------*/
145 rtl8188e_PHY_RF6052SetCckTxPower(
146 struct adapter *Adapter,
149 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
150 struct dm_priv *pdmpriv = &pHalData->dmpriv;
151 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
152 u32 TxAGC[2] = {0, 0}, tmpval = 0, pwrtrac_value;
153 bool TurboScanOff = false;
157 /* FOR CE ,must disable turbo scan */
161 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
162 TxAGC[RF_PATH_A] = 0x3f3f3f3f;
163 TxAGC[RF_PATH_B] = 0x3f3f3f3f;
165 TurboScanOff = true;/* disable turbo scan */
168 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
170 pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
171 (pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
172 /* 2010/10/18 MH For external PA module. We need to limit power index to be less than 0x20. */
173 if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA)
178 /* Driver dynamic Tx power shall not affect Tx power.
179 * It shall be determined by power training mechanism.
180 i * Currently, we cannot fully disable driver dynamic
181 * tx power mechanism because it is referenced by BT
183 * In the future, two mechanism shall be separated from
184 * each other and maintained independently. */
185 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
186 TxAGC[RF_PATH_A] = 0x10101010;
187 TxAGC[RF_PATH_B] = 0x10101010;
188 } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
189 TxAGC[RF_PATH_A] = 0x00000000;
190 TxAGC[RF_PATH_B] = 0x00000000;
192 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
194 pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
195 (pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
197 if (pHalData->EEPROMRegulatory == 0) {
198 tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
199 (pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8);
200 TxAGC[RF_PATH_A] += tmpval;
202 tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
203 (pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24);
204 TxAGC[RF_PATH_B] += tmpval;
208 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
209 ptr = (u8 *)(&(TxAGC[idx1]));
210 for (idx2 = 0; idx2 < 4; idx2++) {
211 if (*ptr > RF6052_MAX_TX_PWR)
212 *ptr = RF6052_MAX_TX_PWR;
216 ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
218 if (direction == 1) {
219 /* Increase TX power */
220 TxAGC[0] += pwrtrac_value;
221 TxAGC[1] += pwrtrac_value;
222 } else if (direction == 2) {
223 /* Decrease TX power */
224 TxAGC[0] -= pwrtrac_value;
225 TxAGC[1] -= pwrtrac_value;
228 /* rf-A cck tx power */
229 tmpval = TxAGC[RF_PATH_A]&0xff;
230 PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
231 tmpval = TxAGC[RF_PATH_A]>>8;
232 PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
234 /* rf-B cck tx power */
235 tmpval = TxAGC[RF_PATH_B]>>24;
236 PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
237 tmpval = TxAGC[RF_PATH_B]&0x00ffffff;
238 PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
239 } /* PHY_RF6052SetCckTxPower */
242 /* powerbase0 for OFDM rates */
243 /* powerbase1 for HT MCS rates */
245 static void getpowerbase88e(struct adapter *Adapter, u8 *pPowerLevelOFDM,
246 u8 *pPowerLevelBW20, u8 *pPowerLevelBW40, u8 Channel, u32 *OfdmBase, u32 *MCSBase)
248 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
249 u32 powerBase0, powerBase1;
252 for (i = 0; i < 2; i++) {
253 powerBase0 = pPowerLevelOFDM[i];
255 powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
256 *(OfdmBase+i) = powerBase0;
258 for (i = 0; i < pHalData->NumTotalRFPath; i++) {
259 /* Check HT20 to HT40 diff */
260 if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
261 powerlevel[i] = pPowerLevelBW20[i];
263 powerlevel[i] = pPowerLevelBW40[i];
264 powerBase1 = powerlevel[i];
265 powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
266 *(MCSBase+i) = powerBase1;
269 static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
270 u8 index, u32 *powerBase0, u32 *powerBase1,
273 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
274 struct dm_priv *pdmpriv = &pHalData->dmpriv;
275 u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
277 u32 writeVal, customer_limit, rf;
278 u8 Regulatory = pHalData->EEPROMRegulatory;
280 /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
282 for (rf = 0; rf < 2; rf++) {
283 switch (Regulatory) {
284 case 0: /* Realtek better performance */
285 /* increase power diff defined by Realtek for large power */
287 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
288 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
290 case 1: /* Realtek regulatory */
291 /* increase power diff defined by Realtek for regulatory */
292 if (pHalData->pwrGroupCnt == 1)
294 if (pHalData->pwrGroupCnt >= pHalData->PGMaxGroup) {
295 if (Channel < 3) /* Channel 1-2 */
297 else if (Channel < 6) /* Channel 3-5 */
299 else if (Channel < 9) /* Channel 6-8 */
301 else if (Channel < 12) /* Channel 9-11 */
303 else if (Channel < 14) /* Channel 12-13 */
305 else if (Channel == 14) /* Channel 14 */
308 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
309 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
311 case 2: /* Better regulatory */
312 /* don't increase any power diff */
313 writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
315 case 3: /* Customer defined power diff. */
316 /* increase power diff defined by customer. */
320 pwr_diff = pHalData->TxPwrLegacyHtDiff[rf][Channel-1];
321 else if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
322 pwr_diff = pHalData->TxPwrHt20Diff[rf][Channel-1];
324 if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
325 customer_pwr_limit = pHalData->PwrGroupHT40[rf][Channel-1];
327 customer_pwr_limit = pHalData->PwrGroupHT20[rf][Channel-1];
329 if (pwr_diff >= customer_pwr_limit)
332 pwr_diff = customer_pwr_limit - pwr_diff;
334 for (i = 0; i < 4; i++) {
335 pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)]&(0x7f<<(i*8)))>>(i*8));
337 if (pwr_diff_limit[i] > pwr_diff)
338 pwr_diff_limit[i] = pwr_diff;
340 customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) |
341 (pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]);
342 writeVal = customer_limit + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
346 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
347 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
350 /* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
351 /* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
352 /* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
353 /* 92d do not need this */
354 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
355 writeVal = 0x14141414;
356 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
357 writeVal = 0x00000000;
359 /* 20100628 Joseph: High power mode for BT-Coexist mechanism. */
360 /* This mechanism is only applied when Driver-Highpower-Mechanism is OFF. */
361 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1)
362 writeVal = writeVal - 0x06060606;
363 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2)
365 *(pOutWriteVal+rf) = writeVal;
368 static void writeOFDMPowerReg88E(struct adapter *Adapter, u8 index, u32 *pValue)
370 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
371 u16 regoffset_a[6] = {
372 rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
373 rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
374 rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12};
375 u16 regoffset_b[6] = {
376 rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
377 rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
378 rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12};
379 u8 i, rf, pwr_val[4];
383 for (rf = 0; rf < 2; rf++) {
384 writeVal = pValue[rf];
385 for (i = 0; i < 4; i++) {
386 pwr_val[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8));
387 if (pwr_val[i] > RF6052_MAX_TX_PWR)
388 pwr_val[i] = RF6052_MAX_TX_PWR;
390 writeVal = (pwr_val[3]<<24) | (pwr_val[2]<<16) | (pwr_val[1]<<8) | pwr_val[0];
393 regoffset = regoffset_a[index];
395 regoffset = regoffset_b[index];
397 PHY_SetBBReg(Adapter, regoffset, bMaskDWord, writeVal);
399 /* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
400 if (((pHalData->rf_type == RF_2T2R) &&
401 (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs15_Mcs12)) ||
402 ((pHalData->rf_type != RF_2T2R) &&
403 (regoffset == rTxAGC_A_Mcs07_Mcs04 || regoffset == rTxAGC_B_Mcs07_Mcs04))) {
404 writeVal = pwr_val[3];
405 if (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_A_Mcs07_Mcs04)
407 if (regoffset == rTxAGC_B_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs07_Mcs04)
409 for (i = 0; i < 3; i++) {
411 writeVal = (writeVal > 8) ? (writeVal-8) : 0;
413 writeVal = (writeVal > 6) ? (writeVal-6) : 0;
414 rtw_write8(Adapter, (u32)(regoffset+i), (u8)writeVal);
420 /*-----------------------------------------------------------------------------
421 * Function: PHY_RF6052SetOFDMTxPower
423 * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for
424 * different channel and read original value in TX power register area from
425 * 0xe00. We increase offset and original value to be correct tx pwr.
435 * 11/05/2008 MHC Simulate 8192 series method.
436 * 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to
437 * A/B pwr difference or legacy/HT pwr diff.
438 * 2. We concern with path B legacy/HT OFDM difference.
439 * 01/22/2009 MHC Support new EPRO format from SD3.
441 *---------------------------------------------------------------------------*/
444 rtl8188e_PHY_RF6052SetOFDMTxPower(
445 struct adapter *Adapter,
451 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
452 u32 writeVal[2], powerBase0[2], powerBase1[2], pwrtrac_value;
456 getpowerbase88e(Adapter, pPowerLevelOFDM, pPowerLevelBW20, pPowerLevelBW40, Channel, &powerBase0[0], &powerBase1[0]);
458 /* 2012/04/23 MH According to power tracking value, we need to revise OFDM tx power. */
459 /* This is ued to fix unstable power tracking mode. */
460 ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 0, &direction, &pwrtrac_value);
462 for (index = 0; index < 6; index++) {
463 get_rx_power_val_by_reg(Adapter, Channel, index,
464 &powerBase0[0], &powerBase1[0],
467 if (direction == 1) {
468 writeVal[0] += pwrtrac_value;
469 writeVal[1] += pwrtrac_value;
470 } else if (direction == 2) {
471 writeVal[0] -= pwrtrac_value;
472 writeVal[1] -= pwrtrac_value;
474 writeOFDMPowerReg88E(Adapter, index, &writeVal[0]);
478 static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
480 struct bb_reg_def *pPhyReg;
481 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
484 int rtStatus = _SUCCESS;
486 /* 3----------------------------------------------------------------- */
487 /* 3 <2> Initialize RF */
488 /* 3----------------------------------------------------------------- */
489 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
490 pPhyReg = &pHalData->PHYRegDef[eRFPath];
492 /*----Store original RFENV control type----*/
496 u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
500 u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16);
503 /*----Set RF_ENV enable----*/
504 PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
505 rtw_udelay_os(1);/* PlatformStallExecution(1); */
507 /*----Set RF_ENV output high----*/
508 PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
509 rtw_udelay_os(1);/* PlatformStallExecution(1); */
511 /* Set bit number of Address and Data for RF register */
512 PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
513 rtw_udelay_os(1);/* PlatformStallExecution(1); */
515 PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
516 rtw_udelay_os(1);/* PlatformStallExecution(1); */
518 /*----Initialize RF fom connfiguration file----*/
521 if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum ODM_RF_RADIO_PATH)eRFPath, (enum ODM_RF_RADIO_PATH)eRFPath))
525 if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum ODM_RF_RADIO_PATH)eRFPath, (enum ODM_RF_RADIO_PATH)eRFPath))
533 /*----Restore RFENV control type----*/;
537 PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
541 PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
544 if (rtStatus != _SUCCESS)
545 goto phy_RF6052_Config_ParaFile_Fail;
549 phy_RF6052_Config_ParaFile_Fail:
553 int PHY_RF6052_Config8188E(struct adapter *Adapter)
555 struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
556 int rtStatus = _SUCCESS;
559 /* Initialize general global value */
561 /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
562 if (pHalData->rf_type == RF_1T1R)
563 pHalData->NumTotalRFPath = 1;
565 pHalData->NumTotalRFPath = 2;
568 /* Config BB and RF */
570 rtStatus = phy_RF6052_Config_ParaFile(Adapter);