linux/drivers/staging/rtl8188eu/hal/odm_hwconfig.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7
   8#include "odm_precomp.h"
   9
  10#define READ_AND_CONFIG     READ_AND_CONFIG_MP
  11
  12#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(dm_odm))
  13#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(dm_odm))
  14
  15static u8 odm_query_rxpwrpercentage(s8 antpower)
  16{
  17        if ((antpower <= -100) || (antpower >= 20))
  18                return 0;
  19        else if (antpower >= 0)
  20                return 100;
  21        else
  22                return 100 + antpower;
  23}
  24
  25/*  2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. */
  26/*  IF other SW team do not support the feature, remove this section.?? */
  27static s32 odm_signal_scale_mapping(struct odm_dm_struct *dm_odm, s32 currsig)
  28{
  29        s32 retsig = 0;
  30
  31        if (currsig >= 51 && currsig <= 100)
  32                retsig = 100;
  33        else if (currsig >= 41 && currsig <= 50)
  34                retsig = 80 + ((currsig - 40) * 2);
  35        else if (currsig >= 31 && currsig <= 40)
  36                retsig = 66 + (currsig - 30);
  37        else if (currsig >= 21 && currsig <= 30)
  38                retsig = 54 + (currsig - 20);
  39        else if (currsig >= 10 && currsig <= 20)
  40                retsig = 42 + (((currsig - 10) * 2) / 3);
  41        else if (currsig >= 5 && currsig <= 9)
  42                retsig = 22 + (((currsig - 5) * 3) / 2);
  43        else if (currsig >= 1 && currsig <= 4)
  44                retsig = 6 + (((currsig - 1) * 3) / 2);
  45        else
  46                retsig = currsig;
  47
  48        return retsig;
  49}
  50
  51static u8 odm_evm_db_to_percentage(s8 value)
  52{
  53        /*  -33dB~0dB to 0%~99% */
  54        s8 ret_val = clamp(-value, 0, 33) * 3;
  55
  56        if (ret_val == 99)
  57                ret_val = 100;
  58
  59        return ret_val;
  60}
  61
  62static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
  63                        struct odm_phy_status_info *pPhyInfo,
  64                        u8 *pPhyStatus,
  65                        struct odm_per_pkt_info *pPktinfo)
  66{
  67        struct sw_ant_switch *pDM_SWAT_Table = &dm_odm->DM_SWAT_Table;
  68        u8 i, max_spatial_stream;
  69        s8 rx_pwr[4], rx_pwr_all = 0;
  70        u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
  71        u8 RSSI, total_rssi = 0;
  72        bool is_cck_rate;
  73        u8 rf_rx_num = 0;
  74        u8 cck_highpwr = 0;
  75        u8 LNA_idx, VGA_idx;
  76
  77        struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
  78
  79        is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
  80                      pPktinfo->Rate <= DESC92C_RATE11M;
  81
  82        pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
  83        pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
  84
  85        if (is_cck_rate) {
  86                u8 cck_agc_rpt;
  87
  88                dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
  89                /*  (1)Hardware does not provide RSSI for CCK */
  90                /*  (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
  91
  92                cck_highpwr = dm_odm->bCckHighPower;
  93
  94                cck_agc_rpt =  pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a;
  95
  96                /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
  97                /* The RSSI formula should be modified according to the gain table */
  98                /* In 88E, cck_highpwr is always set to 1 */
  99                LNA_idx = (cck_agc_rpt & 0xE0) >> 5;
 100                VGA_idx = cck_agc_rpt & 0x1F;
 101                switch (LNA_idx) {
 102                case 7:
 103                        if (VGA_idx <= 27)
 104                                rx_pwr_all = -100 + 2 * (27 - VGA_idx); /* VGA_idx = 27~2 */
 105                        else
 106                                rx_pwr_all = -100;
 107                        break;
 108                case 6:
 109                        rx_pwr_all = -48 + 2 * (2 - VGA_idx); /* VGA_idx = 2~0 */
 110                        break;
 111                case 5:
 112                        rx_pwr_all = -42 + 2 * (7 - VGA_idx); /* VGA_idx = 7~5 */
 113                        break;
 114                case 4:
 115                        rx_pwr_all = -36 + 2 * (7 - VGA_idx); /* VGA_idx = 7~4 */
 116                        break;
 117                case 3:
 118                        rx_pwr_all = -24 + 2 * (7 - VGA_idx); /* VGA_idx = 7~0 */
 119                        break;
 120                case 2:
 121                        if (cck_highpwr)
 122                                rx_pwr_all = -12 + 2 * (5 - VGA_idx); /* VGA_idx = 5~0 */
 123                        else
 124                                rx_pwr_all = -6 + 2 * (5 - VGA_idx);
 125                        break;
 126                case 1:
 127                        rx_pwr_all = 8 - 2 * VGA_idx;
 128                        break;
 129                case 0:
 130                        rx_pwr_all = 14 - 2 * VGA_idx;
 131                        break;
 132                default:
 133                        break;
 134                }
 135                rx_pwr_all += 6;
 136                PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
 137                if (!cck_highpwr) {
 138                        if (PWDB_ALL >= 80)
 139                                PWDB_ALL = ((PWDB_ALL - 80) << 1) + ((PWDB_ALL - 80) >> 1) + 80;
 140                        else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20))
 141                                PWDB_ALL += 3;
 142                        if (PWDB_ALL > 100)
 143                                PWDB_ALL = 100;
 144                }
 145
 146                pPhyInfo->RxPWDBAll = PWDB_ALL;
 147                pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
 148                pPhyInfo->RecvSignalPower = rx_pwr_all;
 149                /*  (3) Get Signal Quality (EVM) */
 150                if (pPktinfo->bPacketMatchBSSID) {
 151                        u8 SQ, SQ_rpt;
 152
 153                        if (pPhyInfo->RxPWDBAll > 40 && !dm_odm->bInHctTest) {
 154                                SQ = 100;
 155                        } else {
 156                                SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
 157
 158                                if (SQ_rpt > 64)
 159                                        SQ = 0;
 160                                else if (SQ_rpt < 20)
 161                                        SQ = 100;
 162                                else
 163                                        SQ = ((64 - SQ_rpt) * 100) / 44;
 164                        }
 165                        pPhyInfo->SignalQuality = SQ;
 166                        pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
 167                        pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
 168                }
 169        } else { /* is OFDM rate */
 170                dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
 171
 172                /*  (1)Get RSSI for HT rate */
 173
 174                for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
 175                        /*  2008/01/30 MH we will judge RF RX path now. */
 176                        if (dm_odm->RFPathRxEnable & BIT(i))
 177                                rf_rx_num++;
 178
 179                        rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F) * 2) - 110;
 180
 181                        pPhyInfo->RxPwr[i] = rx_pwr[i];
 182
 183                        /* Translate DBM to percentage. */
 184                        RSSI = odm_query_rxpwrpercentage(rx_pwr[i]);
 185                        total_rssi += RSSI;
 186
 187                        /* Modification for ext-LNA board */
 188                        if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
 189                                if ((pPhyStaRpt->path_agc[i].trsw) == 1)
 190                                        RSSI = (RSSI > 94) ? 100 : (RSSI + 6);
 191                                else
 192                                        RSSI = (RSSI <= 16) ? (RSSI >> 3) : (RSSI - 16);
 193
 194                                if ((RSSI <= 34) && (RSSI >= 4))
 195                                        RSSI -= 4;
 196                        }
 197
 198                        pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI;
 199
 200                        /* Get Rx snr value in DB */
 201                        pPhyInfo->RxSNR[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
 202                        dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
 203                }
 204                /*  (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
 205                rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110;
 206
 207                PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
 208                PWDB_ALL_BT = PWDB_ALL;
 209
 210                pPhyInfo->RxPWDBAll = PWDB_ALL;
 211                pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
 212                pPhyInfo->RxPower = rx_pwr_all;
 213                pPhyInfo->RecvSignalPower = rx_pwr_all;
 214
 215                /*  (3)EVM of HT rate */
 216                if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
 217                        max_spatial_stream = 2; /* both spatial stream make sense */
 218                else
 219                        max_spatial_stream = 1; /* only spatial stream 1 makes sense */
 220
 221                for (i = 0; i < max_spatial_stream; i++) {
 222                        /*  Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
 223                        /*  fill most significant bit to "zero" when doing shifting operation which may change a negative */
 224                        /*  value to positive one, then the dbm value (which is supposed to be negative)  is not correct anymore. */
 225                        EVM = odm_evm_db_to_percentage((pPhyStaRpt->stream_rxevm[i]));  /* dbm */
 226
 227                        if (pPktinfo->bPacketMatchBSSID) {
 228                                if (i == RF_PATH_A) /*  Fill value in RFD, Get the first spatial stream only */
 229                                        pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
 230                                pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
 231                        }
 232                }
 233        }
 234        /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
 235        /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
 236        if (is_cck_rate) {
 237                pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */
 238        } else {
 239                if (rf_rx_num != 0)
 240                        pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num));
 241        }
 242
 243        /* For 92C/92D HW (Hybrid) Antenna Diversity */
 244        pDM_SWAT_Table->antsel = pPhyStaRpt->ant_sel;
 245        /* For 88E HW Antenna Diversity */
 246        dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel;
 247        dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b;
 248        dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2;
 249}
 250
 251static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
 252                                  struct odm_phy_status_info *pPhyInfo,
 253                                  struct odm_per_pkt_info *pPktinfo)
 254{
 255        s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
 256        s32 UndecoratedSmoothedOFDM, RSSI_Ave;
 257        bool is_cck_rate;
 258        u8 RSSI_max, RSSI_min, i;
 259        u32 OFDM_pkt = 0;
 260        u32 Weighting = 0;
 261        struct sta_info *pEntry;
 262        u8 antsel_tr_mux;
 263        struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable;
 264
 265        if (pPktinfo->StationID == 0xFF)
 266                return;
 267        pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID];
 268        if (!IS_STA_VALID(pEntry))
 269                return;
 270        if ((!pPktinfo->bPacketMatchBSSID))
 271                return;
 272
 273        is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
 274                      pPktinfo->Rate <= DESC92C_RATE11M;
 275
 276        /* Smart Antenna Debug Message------------------  */
 277
 278        if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) {
 279                if (pDM_FatTable->FAT_State == FAT_TRAINING_STATE) {
 280                        if (pPktinfo->bPacketToSelf) {
 281                                antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
 282                                                (pDM_FatTable->antsel_rx_keep_1 << 1) |
 283                                                pDM_FatTable->antsel_rx_keep_0;
 284                                pDM_FatTable->antSumRSSI[antsel_tr_mux] += pPhyInfo->RxPWDBAll;
 285                                pDM_FatTable->antRSSIcnt[antsel_tr_mux]++;
 286                        }
 287                }
 288        } else if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) {
 289                if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
 290                        antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
 291                                        (pDM_FatTable->antsel_rx_keep_1 << 1) | pDM_FatTable->antsel_rx_keep_0;
 292                        rtl88eu_dm_ant_sel_statistics(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll);
 293                }
 294        }
 295        /* Smart Antenna Debug Message------------------ */
 296
 297        UndecoratedSmoothedCCK =  pEntry->rssi_stat.UndecoratedSmoothedCCK;
 298        UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
 299        UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
 300
 301        if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
 302                if (!is_cck_rate) { /* ofdm rate */
 303                        if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
 304                                RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
 305                        } else {
 306                                if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
 307                                        RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
 308                                        RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
 309                                } else {
 310                                        RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
 311                                        RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
 312                                }
 313                                if ((RSSI_max - RSSI_min) < 3)
 314                                        RSSI_Ave = RSSI_max;
 315                                else if ((RSSI_max - RSSI_min) < 6)
 316                                        RSSI_Ave = RSSI_max - 1;
 317                                else if ((RSSI_max - RSSI_min) < 10)
 318                                        RSSI_Ave = RSSI_max - 2;
 319                                else
 320                                        RSSI_Ave = RSSI_max - 3;
 321                        }
 322
 323                        /* 1 Process OFDM RSSI */
 324                        if (UndecoratedSmoothedOFDM <= 0) {     /*  initialize */
 325                                UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
 326                        } else {
 327                                if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
 328                                        UndecoratedSmoothedOFDM =
 329                                                        (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
 330                                                        (RSSI_Ave)) / (Rx_Smooth_Factor);
 331                                        UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
 332                                } else {
 333                                        UndecoratedSmoothedOFDM =
 334                                                        (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
 335                                                        (RSSI_Ave)) / (Rx_Smooth_Factor);
 336                                }
 337                        }
 338
 339                        pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap << 1) | BIT(0);
 340
 341                } else {
 342                        RSSI_Ave = pPhyInfo->RxPWDBAll;
 343
 344                        /* 1 Process CCK RSSI */
 345                        if (UndecoratedSmoothedCCK <= 0) {      /*  initialize */
 346                                UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
 347                        } else {
 348                                if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
 349                                        UndecoratedSmoothedCCK =
 350                                                        ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
 351                                                        pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
 352                                        UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
 353                                } else {
 354                                        UndecoratedSmoothedCCK =
 355                                                        ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
 356                                                        pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
 357                                }
 358                        }
 359                        pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap << 1;
 360                }
 361                /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
 362                if (pEntry->rssi_stat.ValidBit >= 64)
 363                        pEntry->rssi_stat.ValidBit = 64;
 364                else
 365                        pEntry->rssi_stat.ValidBit++;
 366
 367                for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
 368                        OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap >> i) & BIT(0);
 369
 370                if (pEntry->rssi_stat.ValidBit == 64) {
 371                        Weighting = min_t(u32, OFDM_pkt << 4, 64);
 372                        UndecoratedSmoothedPWDB = (Weighting * UndecoratedSmoothedOFDM + (64 - Weighting) * UndecoratedSmoothedCCK) >> 6;
 373                } else {
 374                        if (pEntry->rssi_stat.ValidBit != 0)
 375                                UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM +
 376                                                          (pEntry->rssi_stat.ValidBit - OFDM_pkt) *
 377                                                          UndecoratedSmoothedCCK) / pEntry->rssi_stat.ValidBit;
 378                        else
 379                                UndecoratedSmoothedPWDB = 0;
 380                }
 381                pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
 382                pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
 383                pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
 384        }
 385}
 386
 387/*  Endianness before calling this API */
 388void ODM_PhyStatusQuery(struct odm_dm_struct *dm_odm,
 389                        struct odm_phy_status_info *pPhyInfo,
 390                        u8 *pPhyStatus, struct odm_per_pkt_info *pPktinfo)
 391{
 392        odm_RxPhyStatus92CSeries_Parsing(dm_odm, pPhyInfo, pPhyStatus,
 393                                         pPktinfo);
 394        if (dm_odm->RSSI_test)
 395                ;/*  Select the packets to do RSSI checking for antenna switching. */
 396        else
 397                odm_Process_RSSIForDM(dm_odm, pPhyInfo, pPktinfo);
 398}
 399