linux/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2007 - 2011 Realtek Corporation. */
   3
   4/******************************************************************************
   5 *
   6 *
   7 * Module:      rtl8192c_rf6052.c       ( Source C File)
   8 *
   9 * Note:        Provide RF 6052 series relative API.
  10 *
  11 * Function:
  12 *
  13 * Export:
  14 *
  15 * Abbrev:
  16 *
  17 * History:
  18 * Data                 Who             Remark
  19 *
  20 * 09/25/2008   MHC             Create initial version.
  21 * 11/05/2008   MHC             Add API for tw power setting.
  22 *
  23 *
  24******************************************************************************/
  25
  26#define _RTL8188E_RF6052_C_
  27
  28#include "../include/osdep_service.h"
  29#include "../include/drv_types.h"
  30#include "../include/rtl8188e_hal.h"
  31
  32/*-----------------------------------------------------------------------------
  33 * Function:    PHY_RF6052SetBandwidth()
  34 *
  35 * Overview:    This function is called by SetBWModeCallback8190Pci() only
  36 *
  37 * Input:       struct adapter *Adapter
  38 *                      WIRELESS_BANDWIDTH_E    Bandwidth       20M or 40M
  39 *
  40 * Output:      NONE
  41 *
  42 * Return:      NONE
  43 *
  44 * Note:                For RF type 0222D
  45 *---------------------------------------------------------------------------*/
  46void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter,
  47                                     enum ht_channel_width Bandwidth)
  48{
  49        struct hal_data_8188e *pHalData = &Adapter->haldata;
  50
  51        switch (Bandwidth) {
  52        case HT_CHANNEL_WIDTH_20:
  53                pHalData->RfRegChnlVal = ((pHalData->RfRegChnlVal & 0xfffff3ff) | BIT(10) | BIT(11));
  54                rtl8188e_PHY_SetRFReg(Adapter, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal);
  55                break;
  56        case HT_CHANNEL_WIDTH_40:
  57                pHalData->RfRegChnlVal = ((pHalData->RfRegChnlVal & 0xfffff3ff) | BIT(10));
  58                rtl8188e_PHY_SetRFReg(Adapter, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal);
  59                break;
  60        default:
  61                break;
  62        }
  63}
  64
  65/*-----------------------------------------------------------------------------
  66 * Function:    PHY_RF6052SetCckTxPower
  67 *
  68 * Overview:
  69 *
  70 * Input:       NONE
  71 *
  72 * Output:      NONE
  73 *
  74 * Return:      NONE
  75 *
  76 * Revised History:
  77 * When                 Who             Remark
  78 * 11/05/2008   MHC             Simulate 8192series..
  79 *
  80 *---------------------------------------------------------------------------*/
  81
  82void
  83rtl8188e_PHY_RF6052SetCckTxPower(
  84                struct adapter *Adapter,
  85                u8 *pPowerlevel)
  86{
  87        struct hal_data_8188e *pHalData = &Adapter->haldata;
  88        struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
  89        u32 TxAGC[2] = {0, 0}, tmpval = 0, pwrtrac_value;
  90        u8 idx1, idx2;
  91        u8 *ptr;
  92        u8 direction;
  93
  94        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
  95                TxAGC[RF_PATH_A] = 0x3f3f3f3f;
  96                TxAGC[RF_PATH_B] = 0x3f3f3f3f;
  97
  98                for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
  99                        TxAGC[idx1] =
 100                                pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) |
 101                                (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24);
 102                }
 103        } else {
 104                for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
 105                        TxAGC[idx1] =
 106                                pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) |
 107                                (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24);
 108                }
 109                if (pHalData->EEPROMRegulatory == 0) {
 110                        tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
 111                                        (pHalData->MCSTxPowerLevelOriginalOffset[0][7] << 8);
 112                        TxAGC[RF_PATH_A] += tmpval;
 113
 114                        tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
 115                                        (pHalData->MCSTxPowerLevelOriginalOffset[0][15] << 24);
 116                        TxAGC[RF_PATH_B] += tmpval;
 117                }
 118        }
 119        for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
 120                ptr = (u8 *)(&TxAGC[idx1]);
 121                for (idx2 = 0; idx2 < 4; idx2++) {
 122                        if (*ptr > RF6052_MAX_TX_PWR)
 123                                *ptr = RF6052_MAX_TX_PWR;
 124                        ptr++;
 125                }
 126        }
 127        ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
 128
 129        if (direction == 1) {
 130                /*  Increase TX power */
 131                TxAGC[0] += pwrtrac_value;
 132                TxAGC[1] += pwrtrac_value;
 133        } else if (direction == 2) {
 134                /*  Decrease TX power */
 135                TxAGC[0] -=  pwrtrac_value;
 136                TxAGC[1] -=  pwrtrac_value;
 137        }
 138
 139        /*  rf-A cck tx power */
 140        tmpval = TxAGC[RF_PATH_A] & 0xff;
 141        rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
 142        tmpval = TxAGC[RF_PATH_A] >> 8;
 143        rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
 144
 145        /*  rf-B cck tx power */
 146        tmpval = TxAGC[RF_PATH_B] >> 24;
 147        rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
 148        tmpval = TxAGC[RF_PATH_B] & 0x00ffffff;
 149        rtl8188e_PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
 150}       /* PHY_RF6052SetCckTxPower */
 151
 152/*  */
 153/*  powerbase0 for OFDM rates */
 154/*  powerbase1 for HT MCS rates */
 155/*  */
 156static void getpowerbase88e(struct adapter *Adapter, u8 *pPowerLevelOFDM,
 157                            u8 *pPowerLevelBW20, u8 *pPowerLevelBW40, u8 Channel, u32 *OfdmBase, u32 *MCSBase)
 158{
 159        struct hal_data_8188e *pHalData = &Adapter->haldata;
 160        u32 powerBase0, powerBase1;
 161        u8 i;
 162
 163        for (i = 0; i < 2; i++) {
 164                powerBase0 = pPowerLevelOFDM[i];
 165
 166                powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0;
 167                *(OfdmBase + i) = powerBase0;
 168        }
 169
 170        /* Check HT20 to HT40 diff */
 171        if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
 172                powerBase1 = pPowerLevelBW20[0];
 173        else
 174                powerBase1 = pPowerLevelBW40[0];
 175        powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
 176        *MCSBase = powerBase1;
 177}
 178
 179static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
 180                                    u8 index, u32 *powerBase0, u32 *powerBase1,
 181                                    u32 *pOutWriteVal)
 182{
 183        struct hal_data_8188e *pHalData = &Adapter->haldata;
 184        u8      i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
 185        s8      pwr_diff = 0;
 186        u32     writeVal, customer_limit, rf;
 187        u8      Regulatory = pHalData->EEPROMRegulatory;
 188
 189        /*  Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
 190
 191        for (rf = 0; rf < 2; rf++) {
 192                switch (Regulatory) {
 193                case 0: /*  Realtek better performance */
 194                                /*  increase power diff defined by Realtek for large power */
 195                        chnlGroup = 0;
 196                        writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
 197                                ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 198                        break;
 199                case 1: /*  Realtek regulatory */
 200                        /*  increase power diff defined by Realtek for regulatory */
 201                        if (pHalData->pwrGroupCnt == 1)
 202                                chnlGroup = 0;
 203                        if (pHalData->pwrGroupCnt >= MAX_PG_GROUP) {
 204                                if (Channel < 3)                        /*  Channel 1-2 */
 205                                        chnlGroup = 0;
 206                                else if (Channel < 6)           /*  Channel 3-5 */
 207                                        chnlGroup = 1;
 208                                else     if (Channel < 9)               /*  Channel 6-8 */
 209                                        chnlGroup = 2;
 210                                else if (Channel < 12)          /*  Channel 9-11 */
 211                                        chnlGroup = 3;
 212                                else if (Channel < 14)          /*  Channel 12-13 */
 213                                        chnlGroup = 4;
 214                                else if (Channel == 14)         /*  Channel 14 */
 215                                        chnlGroup = 5;
 216                        }
 217                        writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
 218                                        ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 219                        break;
 220                case 2: /*  Better regulatory */
 221                                /*  don't increase any power diff */
 222                        writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 223                        break;
 224                case 3: /*  Customer defined power diff. */
 225                                /*  increase power diff defined by customer. */
 226                        chnlGroup = 0;
 227
 228                        if (index < 2)
 229                                pwr_diff = pHalData->TxPwrLegacyHtDiff[rf][Channel - 1];
 230                        else if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
 231                                pwr_diff = pHalData->TxPwrHt20Diff[rf][Channel - 1];
 232
 233                        if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
 234                                customer_pwr_limit = pHalData->PwrGroupHT40[rf][Channel - 1];
 235                        else
 236                                customer_pwr_limit = pHalData->PwrGroupHT20[rf][Channel - 1];
 237
 238                        if (pwr_diff >= customer_pwr_limit)
 239                                pwr_diff = 0;
 240                        else
 241                                pwr_diff = customer_pwr_limit - pwr_diff;
 242
 243                        for (i = 0; i < 4; i++) {
 244                                pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> (i * 8));
 245
 246                                if (pwr_diff_limit[i] > pwr_diff)
 247                                        pwr_diff_limit[i] = pwr_diff;
 248                        }
 249                        customer_limit = (pwr_diff_limit[3] << 24) | (pwr_diff_limit[2] << 16) |
 250                                         (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
 251                        writeVal = customer_limit + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 252                        break;
 253                default:
 254                        chnlGroup = 0;
 255                        writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
 256                                        ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 257                        break;
 258                }
 259
 260                *(pOutWriteVal + rf) = writeVal;
 261        }
 262}
 263static void writeOFDMPowerReg88E(struct adapter *Adapter, u8 index, u32 *pValue)
 264{
 265        u16 regoffset_a[6] = {
 266                rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
 267                rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
 268                rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12};
 269        u16 regoffset_b[6] = {
 270                rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
 271                rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
 272                rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12};
 273        u8 i, rf, pwr_val[4];
 274        u32 writeVal;
 275        u16 regoffset;
 276
 277        for (rf = 0; rf < 2; rf++) {
 278                writeVal = pValue[rf];
 279                for (i = 0; i < 4; i++) {
 280                        pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> (i * 8));
 281                        if (pwr_val[i]  > RF6052_MAX_TX_PWR)
 282                                pwr_val[i]  = RF6052_MAX_TX_PWR;
 283                }
 284                writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | (pwr_val[1] << 8) | pwr_val[0];
 285
 286                if (rf == 0)
 287                        regoffset = regoffset_a[index];
 288                else
 289                        regoffset = regoffset_b[index];
 290
 291                rtl8188e_PHY_SetBBReg(Adapter, regoffset, bMaskDWord, writeVal);
 292
 293                /*  201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
 294                if (regoffset == rTxAGC_A_Mcs07_Mcs04 || regoffset == rTxAGC_B_Mcs07_Mcs04) {
 295                        writeVal = pwr_val[3];
 296                        if (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_A_Mcs07_Mcs04)
 297                                regoffset = 0xc90;
 298                        if (regoffset == rTxAGC_B_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs07_Mcs04)
 299                                regoffset = 0xc98;
 300                        for (i = 0; i < 3; i++) {
 301                                if (i != 2)
 302                                        writeVal = (writeVal > 8) ? (writeVal - 8) : 0;
 303                                else
 304                                        writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
 305                                rtw_write8(Adapter, (u32)(regoffset + i), (u8)writeVal);
 306                        }
 307                }
 308        }
 309}
 310
 311/*-----------------------------------------------------------------------------
 312 * Function:    PHY_RF6052SetOFDMTxPower
 313 *
 314 * Overview:    For legacy and HY OFDM, we must read EEPROM TX power index for
 315 *                      different channel and read original value in TX power register area from
 316 *                      0xe00. We increase offset and original value to be correct tx pwr.
 317 *
 318 * Input:       NONE
 319 *
 320 * Output:      NONE
 321 *
 322 * Return:      NONE
 323 *
 324 * Revised History:
 325 * When                 Who             Remark
 326 * 11/05/2008   MHC             Simulate 8192 series method.
 327 * 01/06/2009   MHC             1. Prevent Path B tx power overflow or underflow dure to
 328 *                                              A/B pwr difference or legacy/HT pwr diff.
 329 *                                              2. We concern with path B legacy/HT OFDM difference.
 330 * 01/22/2009   MHC             Support new EPRO format from SD3.
 331 *
 332 *---------------------------------------------------------------------------*/
 333
 334void
 335rtl8188e_PHY_RF6052SetOFDMTxPower(
 336                struct adapter *Adapter,
 337                u8 *pPowerLevelOFDM,
 338                u8 *pPowerLevelBW20,
 339                u8 *pPowerLevelBW40,
 340                u8 Channel)
 341{
 342        struct hal_data_8188e *pHalData = &Adapter->haldata;
 343        u32 writeVal[2], powerBase0[2], powerBase1[2], pwrtrac_value;
 344        u8 direction;
 345        u8 index = 0;
 346
 347        getpowerbase88e(Adapter, pPowerLevelOFDM, pPowerLevelBW20, pPowerLevelBW40, Channel, &powerBase0[0], &powerBase1[0]);
 348
 349        /*  2012/04/23 MH According to power tracking value, we need to revise OFDM tx power. */
 350        /*  This is ued to fix unstable power tracking mode. */
 351        ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 0, &direction, &pwrtrac_value);
 352
 353        for (index = 0; index < 6; index++) {
 354                get_rx_power_val_by_reg(Adapter, Channel, index,
 355                                        &powerBase0[0], &powerBase1[0],
 356                                        &writeVal[0]);
 357
 358                if (direction == 1) {
 359                        writeVal[0] += pwrtrac_value;
 360                        writeVal[1] += pwrtrac_value;
 361                } else if (direction == 2) {
 362                        writeVal[0] -= pwrtrac_value;
 363                        writeVal[1] -= pwrtrac_value;
 364                }
 365                writeOFDMPowerReg88E(Adapter, index, &writeVal[0]);
 366        }
 367}
 368
 369static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
 370{
 371        struct bb_reg_def *pPhyReg;
 372        struct hal_data_8188e *pHalData = &Adapter->haldata;
 373        u32 u4RegValue = 0;
 374        int rtStatus = _SUCCESS;
 375
 376        /* Initialize RF */
 377
 378        pPhyReg = &pHalData->PHYRegDef;
 379
 380        /*----Store original RFENV control type----*/
 381        u4RegValue = rtl8188e_PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
 382
 383        /*----Set RF_ENV enable----*/
 384        rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
 385        udelay(1);/* PlatformStallExecution(1); */
 386
 387        /*----Set RF_ENV output high----*/
 388        rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
 389        udelay(1);/* PlatformStallExecution(1); */
 390
 391        /* Set bit number of Address and Data for RF register */
 392        rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /*  Set 1 to 4 bits for 8255 */
 393        udelay(1);/* PlatformStallExecution(1); */
 394
 395        rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0);    /*  Set 0 to 12  bits for 8255 */
 396        udelay(1);/* PlatformStallExecution(1); */
 397
 398        /*----Initialize RF fom connfiguration file----*/
 399        if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv))
 400                rtStatus = _FAIL;
 401
 402        /*----Restore RFENV control type----*/;
 403        rtl8188e_PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
 404
 405        return rtStatus;
 406}
 407
 408int PHY_RF6052_Config8188E(struct adapter *Adapter)
 409{
 410        int rtStatus = _SUCCESS;
 411
 412        /*  */
 413        /*  Config BB and RF */
 414        /*  */
 415        rtStatus = phy_RF6052_Config_ParaFile(Adapter);
 416        return rtStatus;
 417}
 418