root/drivers/staging/rtl8188eu/hal/rf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtl88eu_phy_rf6052_set_bandwidth
  2. rtl88eu_phy_rf6052_set_cck_txpower
  3. getpowerbase88e
  4. get_rx_power_val_by_reg
  5. write_ofdm_pwr_reg
  6. rtl88eu_phy_rf6052_set_ofdm_txpower

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   5  *
   6  ******************************************************************************/
   7 
   8 #include <osdep_service.h>
   9 #include <drv_types.h>
  10 #include <phy.h>
  11 #include <rf.h>
  12 #include <rtl8188e_hal.h>
  13 
  14 void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
  15                                       enum ht_channel_width bandwidth)
  16 {
  17         struct hal_data_8188e *hal_data = adapt->HalData;
  18 
  19         switch (bandwidth) {
  20         case HT_CHANNEL_WIDTH_20:
  21                 hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
  22                                               0xfffff3ff) | BIT(10) | BIT(11));
  23                 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
  24                                hal_data->RfRegChnlVal[0]);
  25                 break;
  26         case HT_CHANNEL_WIDTH_40:
  27                 hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
  28                                               0xfffff3ff) | BIT(10));
  29                 phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
  30                                hal_data->RfRegChnlVal[0]);
  31                 break;
  32         default:
  33                 break;
  34         }
  35 }
  36 
  37 void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel)
  38 {
  39         struct hal_data_8188e *hal_data = adapt->HalData;
  40         struct dm_priv *pdmpriv = &hal_data->dmpriv;
  41         struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
  42         u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value;
  43         u8 idx1, idx2;
  44         u8 *ptr;
  45         u8 direction;
  46 
  47         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
  48                 tx_agc[RF_PATH_A] = 0x3f3f3f3f;
  49                 tx_agc[RF_PATH_B] = 0x3f3f3f3f;
  50                 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
  51                         tx_agc[idx1] = powerlevel[idx1] |
  52                                       (powerlevel[idx1]<<8) |
  53                                       (powerlevel[idx1]<<16) |
  54                                       (powerlevel[idx1]<<24);
  55                 }
  56         } else {
  57                 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
  58                         tx_agc[RF_PATH_A] = 0x10101010;
  59                         tx_agc[RF_PATH_B] = 0x10101010;
  60                 } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
  61                         tx_agc[RF_PATH_A] = 0x00000000;
  62                         tx_agc[RF_PATH_B] = 0x00000000;
  63                 } else {
  64                         for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
  65                                 tx_agc[idx1] = powerlevel[idx1] |
  66                                                (powerlevel[idx1]<<8) |
  67                                                (powerlevel[idx1]<<16) |
  68                                                (powerlevel[idx1]<<24);
  69                         }
  70                         if (hal_data->EEPROMRegulatory == 0) {
  71                                 tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][6] +
  72                                          (hal_data->MCSTxPowerLevelOriginalOffset[0][7]<<8);
  73                                 tx_agc[RF_PATH_A] += tmpval;
  74 
  75                                 tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][14] +
  76                                          (hal_data->MCSTxPowerLevelOriginalOffset[0][15]<<24);
  77                                 tx_agc[RF_PATH_B] += tmpval;
  78                         }
  79                 }
  80         }
  81         for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
  82                 ptr = (u8 *)(&(tx_agc[idx1]));
  83                 for (idx2 = 0; idx2 < 4; idx2++) {
  84                         if (*ptr > RF6052_MAX_TX_PWR)
  85                                 *ptr = RF6052_MAX_TX_PWR;
  86                         ptr++;
  87                 }
  88         }
  89         rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
  90                                         &pwrtrac_value);
  91 
  92         if (direction == 1) {
  93                 /*  Increase TX power */
  94                 tx_agc[0] += pwrtrac_value;
  95                 tx_agc[1] += pwrtrac_value;
  96         } else if (direction == 2) {
  97                 /*  Decrease TX power */
  98                 tx_agc[0] -=  pwrtrac_value;
  99                 tx_agc[1] -=  pwrtrac_value;
 100         }
 101 
 102         /*  rf-A cck tx power */
 103         tmpval = tx_agc[RF_PATH_A]&0xff;
 104         phy_set_bb_reg(adapt, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
 105         tmpval = tx_agc[RF_PATH_A]>>8;
 106         phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
 107 
 108         /*  rf-B cck tx power */
 109         tmpval = tx_agc[RF_PATH_B]>>24;
 110         phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
 111         tmpval = tx_agc[RF_PATH_B]&0x00ffffff;
 112         phy_set_bb_reg(adapt, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
 113 }
 114 
 115 /*  powerbase0 for OFDM rates */
 116 /*  powerbase1 for HT MCS rates */
 117 static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm,
 118                             u8 *pwr_level_bw20, u8 *pwr_level_bw40,
 119                             u8 channel, u32 *ofdmbase, u32 *mcs_base)
 120 {
 121         u32 powerbase0, powerbase1;
 122         u8 i, powerlevel[2];
 123 
 124         for (i = 0; i < 2; i++) {
 125                 powerbase0 = pwr_level_ofdm[i];
 126 
 127                 powerbase0 = (powerbase0<<24) | (powerbase0<<16) |
 128                              (powerbase0<<8) | powerbase0;
 129                 *(ofdmbase+i) = powerbase0;
 130         }
 131         /* Check HT20 to HT40 diff */
 132         if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
 133                 powerlevel[0] = pwr_level_bw20[0];
 134         else
 135                 powerlevel[0] = pwr_level_bw40[0];
 136         powerbase1 = powerlevel[0];
 137         powerbase1 = (powerbase1<<24) | (powerbase1<<16) |
 138                      (powerbase1<<8) | powerbase1;
 139         *mcs_base = powerbase1;
 140 }
 141 static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel,
 142                                     u8 index, u32 *powerbase0, u32 *powerbase1,
 143                                     u32 *out_val)
 144 {
 145         struct hal_data_8188e *hal_data = adapt->HalData;
 146         struct dm_priv  *pdmpriv = &hal_data->dmpriv;
 147         u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
 148         s8 pwr_diff = 0;
 149         u32 write_val, customer_limit, rf;
 150         u8 regulatory = hal_data->EEPROMRegulatory;
 151 
 152         /*  Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
 153 
 154         for (rf = 0; rf < 2; rf++) {
 155                 u8 j = index + (rf ? 8 : 0);
 156 
 157                 switch (regulatory) {
 158                 case 0:
 159                         chnlGroup = 0;
 160                         write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
 161                                 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
 162                         break;
 163                 case 1: /*  Realtek regulatory */
 164                         /*  increase power diff defined by Realtek for regulatory */
 165                         if (hal_data->pwrGroupCnt == 1)
 166                                 chnlGroup = 0;
 167                         if (hal_data->pwrGroupCnt >= hal_data->PGMaxGroup)
 168                                 Hal_GetChnlGroup88E(channel, &chnlGroup);
 169 
 170                         write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
 171                                         ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
 172                         break;
 173                 case 2: /*  Better regulatory */
 174                                 /*  don't increase any power diff */
 175                         write_val = (index < 2) ? powerbase0[rf] : powerbase1[rf];
 176                         break;
 177                 case 3: /*  Customer defined power diff. */
 178                                 /*  increase power diff defined by customer. */
 179                         chnlGroup = 0;
 180 
 181                         if (index < 2)
 182                                 pwr_diff = hal_data->TxPwrLegacyHtDiff[rf][channel-1];
 183                         else if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
 184                                 pwr_diff = hal_data->TxPwrHt20Diff[rf][channel-1];
 185 
 186                         if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
 187                                 customer_pwr_limit = hal_data->PwrGroupHT40[rf][channel-1];
 188                         else
 189                                 customer_pwr_limit = hal_data->PwrGroupHT20[rf][channel-1];
 190 
 191                         if (pwr_diff >= customer_pwr_limit)
 192                                 pwr_diff = 0;
 193                         else
 194                                 pwr_diff = customer_pwr_limit - pwr_diff;
 195 
 196                         for (i = 0; i < 4; i++) {
 197                                 pwr_diff_limit[i] = (u8)((hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] &
 198                                                          (0x7f << (i * 8))) >> (i * 8));
 199 
 200                                 if (pwr_diff_limit[i] > pwr_diff)
 201                                         pwr_diff_limit[i] = pwr_diff;
 202                         }
 203                         customer_limit = (pwr_diff_limit[3]<<24) |
 204                                          (pwr_diff_limit[2]<<16) |
 205                                          (pwr_diff_limit[1]<<8) |
 206                                          (pwr_diff_limit[0]);
 207                         write_val = customer_limit + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
 208                         break;
 209                 default:
 210                         chnlGroup = 0;
 211                         write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] +
 212                                         ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
 213                         break;
 214                 }
 215 /*  20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
 216 /*  Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
 217 /*  In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
 218                 /* 92d do not need this */
 219                 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
 220                         write_val = 0x14141414;
 221                 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
 222                         write_val = 0x00000000;
 223 
 224                 *(out_val+rf) = write_val;
 225         }
 226 }
 227 
 228 static void write_ofdm_pwr_reg(struct adapter *adapt, u8 index, u32 *pvalue)
 229 {
 230         u16 regoffset_a[6] = { rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
 231                                rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
 232                                rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 };
 233         u16 regoffset_b[6] = { rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
 234                                rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
 235                                rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 };
 236         u8 i, rf, pwr_val[4];
 237         u32 write_val;
 238         u16 regoffset;
 239 
 240         for (rf = 0; rf < 2; rf++) {
 241                 write_val = pvalue[rf];
 242                 for (i = 0; i < 4; i++) {
 243                         pwr_val[i] = (u8)((write_val & (0x7f<<(i*8)))>>(i*8));
 244                         if (pwr_val[i]  > RF6052_MAX_TX_PWR)
 245                                 pwr_val[i]  = RF6052_MAX_TX_PWR;
 246                 }
 247                 write_val = (pwr_val[3]<<24) | (pwr_val[2]<<16) |
 248                             (pwr_val[1]<<8) | pwr_val[0];
 249 
 250                 if (rf == 0)
 251                         regoffset = regoffset_a[index];
 252                 else
 253                         regoffset = regoffset_b[index];
 254 
 255                 phy_set_bb_reg(adapt, regoffset, bMaskDWord, write_val);
 256         }
 257 }
 258 
 259 void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
 260                                          u8 *pwr_level_ofdm,
 261                                          u8 *pwr_level_bw20,
 262                                          u8 *pwr_level_bw40, u8 channel)
 263 {
 264         u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value;
 265         u8 direction;
 266         u8 index = 0;
 267 
 268         getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40,
 269                         channel, &powerbase0[0], &powerbase1[0]);
 270 
 271         rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0,
 272                                         &direction, &pwrtrac_value);
 273 
 274         for (index = 0; index < 6; index++) {
 275                 get_rx_power_val_by_reg(adapt, channel, index,
 276                                         &powerbase0[0], &powerbase1[0],
 277                                         &write_val[0]);
 278 
 279                 if (direction == 1) {
 280                         write_val[0] += pwrtrac_value;
 281                         write_val[1] += pwrtrac_value;
 282                 } else if (direction == 2) {
 283                         write_val[0] -= pwrtrac_value;
 284                         write_val[1] -= pwrtrac_value;
 285                 }
 286                 write_ofdm_pwr_reg(adapt, index, &write_val[0]);
 287         }
 288 }

/* [<][>][^][v][top][bottom][index][help] */