1/****************************************************************************** 2 * 3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 4 * 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. 8 * 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 12 * more details. 13 * 14 ******************************************************************************/ 15 16/* */ 17/* include files */ 18/* */ 19 20#include "odm_precomp.h" 21 22static u8 odm_QueryRxPwrPercentage(s8 AntPower) 23{ 24 if ((AntPower <= -100) || (AntPower >= 20)) 25 return 0; 26 else if (AntPower >= 0) 27 return 100; 28 else 29 return 100 + AntPower; 30} 31 32static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig) 33{ 34 s32 RetSig = 0; 35 36 if ((pDM_Odm->SupportInterface == ODM_ITRF_USB) || (pDM_Odm->SupportInterface == ODM_ITRF_SDIO)) { 37 if (CurrSig >= 51 && CurrSig <= 100) 38 RetSig = 100; 39 else if (CurrSig >= 41 && CurrSig <= 50) 40 RetSig = 80 + ((CurrSig - 40)*2); 41 else if (CurrSig >= 31 && CurrSig <= 40) 42 RetSig = 66 + (CurrSig - 30); 43 else if (CurrSig >= 21 && CurrSig <= 30) 44 RetSig = 54 + (CurrSig - 20); 45 else if (CurrSig >= 10 && CurrSig <= 20) 46 RetSig = 42 + (((CurrSig - 10) * 2) / 3); 47 else if (CurrSig >= 5 && CurrSig <= 9) 48 RetSig = 22 + (((CurrSig - 5) * 3) / 2); 49 else if (CurrSig >= 1 && CurrSig <= 4) 50 RetSig = 6 + (((CurrSig - 1) * 3) / 2); 51 else 52 RetSig = CurrSig; 53 } 54 return RetSig; 55} 56 57static s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig) 58{ 59 return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig); 60} 61 62static u8 63odm_EVMdbToPercentage( 64 s8 Value 65 ) 66{ 67 /* */ 68 /* -33dB~0dB to 0%~99% */ 69 /* */ 70 s8 ret_val; 71 72 ret_val = Value; 73 74 if (ret_val >= 0) 75 ret_val = 0; 76 if (ret_val <= -33) 77 ret_val = -33; 78 79 ret_val = 0 - ret_val; 80 ret_val *= 3; 81 82 if (ret_val == 99) 83 ret_val = 100; 84 85 return ret_val; 86} 87 88static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, 89 struct phy_info *pPhyInfo, 90 u8 *pPhyStatus, 91 struct odm_packet_info *pPktinfo) 92{ 93 struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus; 94 u8 i, Max_spatial_stream; 95 s8 rx_pwr[4], rx_pwr_all = 0; 96 u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT; 97 u8 RSSI, total_rssi = 0; 98 u8 isCCKrate = 0; 99 u8 rf_rx_num = 0; 100 u8 cck_highpwr = 0; 101 102 isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; 103 pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1; 104 pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; 105 106 if (isCCKrate) { 107 u8 report; 108 u8 cck_agc_rpt; 109 110 pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++; 111 /* (1)Hardware does not provide RSSI for CCK */ 112 /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ 113 114 cck_highpwr = pDM_Odm->bCckHighPower; 115 116 cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; 117 118 /* The RSSI formula should be modified according to the gain table */ 119 if (!cck_highpwr) { 120 report = (cck_agc_rpt & 0xc0)>>6; 121 switch (report) { 122 /* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */ 123 /* Note: different RF with the different RNA gain. */ 124 case 0x3: 125 rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); 126 break; 127 case 0x2: 128 rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); 129 break; 130 case 0x1: 131 rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); 132 break; 133 case 0x0: 134 rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); 135 break; 136 } 137 } else { 138 report = (cck_agc_rpt & 0x60)>>5; 139 switch (report) { 140 case 0x3: 141 rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ; 142 break; 143 case 0x2: 144 rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1); 145 break; 146 case 0x1: 147 rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1) ; 148 break; 149 case 0x0: 150 rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1) ; 151 break; 152 } 153 } 154 155 PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); 156 157 /* Modification for ext-LNA board */ 158 if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { 159 if ((cck_agc_rpt>>7) == 0) { 160 PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6); 161 } else { 162 if (PWDB_ALL > 38) 163 PWDB_ALL -= 16; 164 else 165 PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12); 166 } 167 168 /* CCK modification */ 169 if (PWDB_ALL > 25 && PWDB_ALL <= 60) 170 PWDB_ALL += 6; 171 } else { /* Modification for int-LNA board */ 172 if (PWDB_ALL > 99) 173 PWDB_ALL -= 8; 174 else if (PWDB_ALL > 50 && PWDB_ALL <= 68) 175 PWDB_ALL += 4; 176 } 177 pPhyInfo->RxPWDBAll = PWDB_ALL; 178 pPhyInfo->BTRxRSSIPercentage = PWDB_ALL; 179 pPhyInfo->RecvSignalPower = rx_pwr_all; 180 /* (3) Get Signal Quality (EVM) */ 181 if (pPktinfo->bPacketMatchBSSID) { 182 u8 SQ, SQ_rpt; 183 184 SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all; 185 186 if (SQ_rpt > 64) 187 SQ = 0; 188 else if (SQ_rpt < 20) 189 SQ = 100; 190 else 191 SQ = ((64-SQ_rpt) * 100) / 44; 192 193 pPhyInfo->SignalQuality = SQ; 194 pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ; 195 pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; 196 } 197 } else { /* is OFDM rate */ 198 pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++; 199 200 /* (1)Get RSSI for HT rate */ 201 202 for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { 203 /* 2008/01/30 MH we will judge RF RX path now. */ 204 if (pDM_Odm->RFPathRxEnable & BIT(i)) 205 rf_rx_num++; 206 207 rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110; 208 209 pPhyInfo->RxPwr[i] = rx_pwr[i]; 210 211 /* Translate DBM to percentage. */ 212 RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]); 213 total_rssi += RSSI; 214 215 /* Modification for ext-LNA board */ 216 if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { 217 if ((pPhyStaRpt->path_agc[i].trsw) == 1) 218 RSSI = (RSSI > 94) ? 100 : (RSSI+6); 219 else 220 RSSI = (RSSI <= 16) ? (RSSI>>3) : (RSSI-16); 221 222 if ((RSSI <= 34) && (RSSI >= 4)) 223 RSSI -= 4; 224 } 225 226 pPhyInfo->RxMIMOSignalStrength[i] = (u8) RSSI; 227 228 /* Get Rx snr value in DB */ 229 pPhyInfo->RxSNR[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2); 230 } 231 232 /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ 233 rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f)-110; 234 235 PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); 236 PWDB_ALL_BT = PWDB_ALL; 237 238 pPhyInfo->RxPWDBAll = PWDB_ALL; 239 pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT; 240 pPhyInfo->RxPower = rx_pwr_all; 241 pPhyInfo->RecvSignalPower = rx_pwr_all; 242 243 /* (3)EVM of HT rate */ 244 if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15) 245 Max_spatial_stream = 2; /* both spatial stream make sense */ 246 else 247 Max_spatial_stream = 1; /* only spatial stream 1 makes sense */ 248 249 for (i = 0; i < Max_spatial_stream; i++) { 250 /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */ 251 /* fill most significant bit to "zero" when doing shifting operation which may change a negative */ 252 /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */ 253 EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */ 254 255 if (pPktinfo->bPacketMatchBSSID) { 256 if (i == RF_PATH_A) { 257 /* Fill value in RFD, Get the first spatial stream only */ 258 pPhyInfo->SignalQuality = (u8)(EVM & 0xff); 259 } 260 pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff); 261 } 262 } 263 } 264 /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */ 265 /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */ 266 if (isCCKrate) { 267 pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */ 268 } else { 269 if (rf_rx_num != 0) 270 pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num)); 271 } 272} 273 274void odm_Init_RSSIForDM23a(struct dm_odm_t *pDM_Odm) 275{ 276} 277 278static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm, 279 struct phy_info *pPhyInfo, 280 struct odm_packet_info *pPktinfo) 281{ 282 s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK; 283 s32 UndecoratedSmoothedOFDM, RSSI_Ave; 284 u8 isCCKrate = 0; 285 u8 RSSI_max, RSSI_min, i; 286 u32 OFDM_pkt = 0; 287 u32 Weighting = 0; 288 struct sta_info *pEntry; 289 290 if (pPktinfo->StationID == 0xFF) 291 return; 292 293 pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID]; 294 if (!pEntry) 295 return; 296 if ((!pPktinfo->bPacketMatchBSSID)) 297 return; 298 299 isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; 300 301 /* Smart Antenna Debug Message------------------*/ 302 303 UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; 304 UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; 305 UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; 306 307 if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) { 308 if (!isCCKrate) { /* ofdm rate */ 309 if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) { 310 RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; 311 } else { 312 if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) { 313 RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; 314 RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; 315 } else { 316 RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; 317 RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; 318 } 319 if ((RSSI_max - RSSI_min) < 3) 320 RSSI_Ave = RSSI_max; 321 else if ((RSSI_max - RSSI_min) < 6) 322 RSSI_Ave = RSSI_max - 1; 323 else if ((RSSI_max - RSSI_min) < 10) 324 RSSI_Ave = RSSI_max - 2; 325 else 326 RSSI_Ave = RSSI_max - 3; 327 } 328 329 /* 1 Process OFDM RSSI */ 330 if (UndecoratedSmoothedOFDM <= 0) { 331 /* initialize */ 332 UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll; 333 } else { 334 if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) { 335 UndecoratedSmoothedOFDM = 336 (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + 337 (RSSI_Ave)) / (Rx_Smooth_Factor); 338 UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; 339 } else { 340 UndecoratedSmoothedOFDM = 341 (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + 342 (RSSI_Ave)) / (Rx_Smooth_Factor); 343 } 344 } 345 pEntry->rssi_stat.PacketMap = 346 (pEntry->rssi_stat.PacketMap<<1) | BIT(0); 347 } else { 348 RSSI_Ave = pPhyInfo->RxPWDBAll; 349 350 /* 1 Process CCK RSSI */ 351 if (UndecoratedSmoothedCCK <= 0) { 352 /* initialize */ 353 UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll; 354 } else { 355 if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) { 356 UndecoratedSmoothedCCK = 357 (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + 358 (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); 359 UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; 360 } else { 361 UndecoratedSmoothedCCK = 362 (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + 363 (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); 364 } 365 } 366 pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1; 367 } 368 369 /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ 370 if (pEntry->rssi_stat.ValidBit >= 64) 371 pEntry->rssi_stat.ValidBit = 64; 372 else 373 pEntry->rssi_stat.ValidBit++; 374 375 for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) 376 OFDM_pkt += 377 (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0); 378 379 if (pEntry->rssi_stat.ValidBit == 64) { 380 Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4); 381 UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6; 382 } else { 383 if (pEntry->rssi_stat.ValidBit != 0) 384 UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit; 385 else 386 UndecoratedSmoothedPWDB = 0; 387 } 388 pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; 389 pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; 390 pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; 391 } 392} 393 394/* Endianness before calling this API */ 395static void ODM_PhyStatusQuery23a_92CSeries(struct dm_odm_t *pDM_Odm, 396 struct phy_info *pPhyInfo, 397 u8 *pPhyStatus, 398 struct odm_packet_info *pPktinfo) 399{ 400 odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo, 401 pPhyStatus, pPktinfo); 402 403 odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo); 404} 405 406void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct phy_info *pPhyInfo, 407 u8 *pPhyStatus, struct odm_packet_info *pPktinfo) 408{ 409 ODM_PhyStatusQuery23a_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo); 410} 411