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_MP(ic, txt) (ODM_ReadAndConfig_MP_##ic##txt(pDM_Odm)) 11#define READ_AND_CONFIG READ_AND_CONFIG_MP 12 13static u8 odm_query_rx_pwr_percentage(s8 ant_power) 14{ 15 if ((ant_power <= -100) || (ant_power >= 20)) 16 return 0; 17 else if (ant_power >= 0) 18 return 100; 19 else 20 return 100 + ant_power; 21 22} 23 24s32 odm_signal_scale_mapping(struct dm_odm_t *dm_odm, s32 curr_sig) 25{ 26 s32 ret_sig = 0; 27 28 if (dm_odm->SupportInterface == ODM_ITRF_SDIO) { 29 if (curr_sig >= 51 && curr_sig <= 100) 30 ret_sig = 100; 31 else if (curr_sig >= 41 && curr_sig <= 50) 32 ret_sig = 80 + ((curr_sig - 40)*2); 33 else if (curr_sig >= 31 && curr_sig <= 40) 34 ret_sig = 66 + (curr_sig - 30); 35 else if (curr_sig >= 21 && curr_sig <= 30) 36 ret_sig = 54 + (curr_sig - 20); 37 else if (curr_sig >= 10 && curr_sig <= 20) 38 ret_sig = 42 + (((curr_sig - 10) * 2) / 3); 39 else if (curr_sig >= 5 && curr_sig <= 9) 40 ret_sig = 22 + (((curr_sig - 5) * 3) / 2); 41 else if (curr_sig >= 1 && curr_sig <= 4) 42 ret_sig = 6 + (((curr_sig - 1) * 3) / 2); 43 else 44 ret_sig = curr_sig; 45 } 46 47 return ret_sig; 48} 49 50static u8 odm_evm_db_to_percentage(s8 value) 51{ 52 /* */ 53 /* -33dB~0dB to 0%~99% */ 54 /* */ 55 s8 ret_val; 56 57 ret_val = value; 58 ret_val /= 2; 59 60 if (ret_val >= 0) 61 ret_val = 0; 62 if (ret_val <= -33) 63 ret_val = -33; 64 65 ret_val = 0 - ret_val; 66 ret_val *= 3; 67 68 if (ret_val == 99) 69 ret_val = 100; 70 71 return ret_val; 72} 73 74static s8 odm_cck_rssi(u8 lna_idx, u8 vga_idx) 75{ 76 s8 rx_pwr_all = 0x00; 77 78 switch (lna_idx) { 79 /* 46 53 73 95 201301231630 */ 80 /* 46 53 77 99 201301241630 */ 81 82 case 6: 83 rx_pwr_all = -34 - (2 * vga_idx); 84 break; 85 case 4: 86 rx_pwr_all = -14 - (2 * vga_idx); 87 break; 88 case 1: 89 rx_pwr_all = 6 - (2 * vga_idx); 90 break; 91 case 0: 92 rx_pwr_all = 16 - (2 * vga_idx); 93 break; 94 default: 95 /* rx_pwr_all = -53+(2*(31-VGA_idx)); */ 96 break; 97 } 98 return rx_pwr_all; 99} 100 101static void odm_rx_phy_status_parsing(struct dm_odm_t *dm_odm, 102 struct odm_phy_info *phy_info, 103 u8 *phy_status, 104 struct odm_packet_info *pkt_info) 105{ 106 u8 i; 107 s8 rx_pwr[4], rx_pwr_all = 0; 108 u8 evm, pwdb_all = 0, pwdb_all_bt; 109 u8 rssi, total_rssi = 0; 110 bool is_cck_rate = false; 111 u8 rf_rx_num = 0; 112 u8 lna_idx, vga_idx; 113 struct phy_status_rpt_8192cd_t *phy_sta_rpt = (struct phy_status_rpt_8192cd_t *)phy_status; 114 115 is_cck_rate = pkt_info->data_rate <= DESC_RATE11M; 116 phy_info->rx_mimo_signal_quality[RF_PATH_A] = -1; 117 phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1; 118 119 120 if (is_cck_rate) { 121 u8 cck_agc_rpt; 122 123 dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++; 124 125 /* 126 * (1)Hardware does not provide RSSI for CCK/ 127 * (2)PWDB, Average PWDB calculated by 128 * hardware (for rate adaptive) 129 */ 130 131 cck_agc_rpt = phy_sta_rpt->cck_agc_rpt_ofdm_cfosho_a; 132 133 /* 134 * 2011.11.28 LukeLee: 88E use different LNA & VGA gain table 135 * The RSSI formula should be modified according to the gain table 136 */ 137 lna_idx = ((cck_agc_rpt & 0xE0)>>5); 138 vga_idx = (cck_agc_rpt & 0x1F); 139 rx_pwr_all = odm_cck_rssi(lna_idx, vga_idx); 140 pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all); 141 if (pwdb_all > 100) 142 pwdb_all = 100; 143 144 phy_info->rx_pwd_ba11 = pwdb_all; 145 phy_info->bt_rx_rssi_percentage = pwdb_all; 146 phy_info->recv_signal_power = rx_pwr_all; 147 148 /* (3) Get Signal Quality (EVM) */ 149 150 /* if (pPktinfo->bPacketMatchBSSID) */ 151 { 152 u8 sq, sq_rpt; 153 154 if (phy_info->rx_pwd_ba11 > 40 && !dm_odm->bInHctTest) 155 sq = 100; 156 else { 157 sq_rpt = phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all; 158 159 if (sq_rpt > 64) 160 sq = 0; 161 else if (sq_rpt < 20) 162 sq = 100; 163 else 164 sq = ((64-sq_rpt) * 100) / 44; 165 166 } 167 168 phy_info->signal_quality = sq; 169 phy_info->rx_mimo_signal_quality[RF_PATH_A] = sq; 170 phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1; 171 } 172 } else { /* is OFDM rate */ 173 dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++; 174 175 /* 176 * (1)Get RSSI for HT rate 177 */ 178 179 for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { 180 /* 2008/01/30 MH we will judge RF RX path now. */ 181 if (dm_odm->RFPathRxEnable & BIT(i)) 182 rf_rx_num++; 183 /* else */ 184 /* continue; */ 185 186 rx_pwr[i] = ((phy_sta_rpt->path_agc[i].gain & 0x3F) * 2) - 110; 187 188 phy_info->rx_pwr[i] = rx_pwr[i]; 189 190 /* Translate DBM to percentage. */ 191 rssi = odm_query_rx_pwr_percentage(rx_pwr[i]); 192 total_rssi += rssi; 193 194 phy_info->rx_mimo_signal_strength[i] = (u8)rssi; 195 196 /* Get Rx snr value in DB */ 197 phy_info->rx_snr[i] = dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(phy_sta_rpt->path_rxsnr[i]/2); 198 } 199 200 /* 201 * (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) 202 */ 203 rx_pwr_all = ((phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all >> 1) & 0x7f) - 110; 204 205 pwdb_all_bt = pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all); 206 207 phy_info->rx_pwd_ba11 = pwdb_all; 208 phy_info->bt_rx_rssi_percentage = pwdb_all_bt; 209 phy_info->rx_power = rx_pwr_all; 210 phy_info->recv_signal_power = rx_pwr_all; 211 212 /* 213 * (3)EVM of HT rate 214 * 215 * Only spatial stream 1 makes sense 216 * 217 * Do not use shift operation like "rx_evmX >>= 1" 218 * because the compiler of free build environment 219 * fill most significant bit to "zero" when doing 220 * shifting operation which may change a negative 221 * value to positive one, then the dbm value (which 222 * is supposed to be negative) is not correct 223 * anymore. 224 */ 225 evm = odm_evm_db_to_percentage(phy_sta_rpt->stream_rxevm[0]); /* dbm */ 226 227 /* Fill value in RFD, Get the first spatial stream only */ 228 phy_info->signal_quality = (u8)(evm & 0xff); 229 230 phy_info->rx_mimo_signal_quality[RF_PATH_A] = (u8)(evm & 0xff); 231 232 odm_parsing_cfo(dm_odm, pkt_info, phy_sta_rpt->path_cfotail); 233 } 234 235 /* 236 * UI BSS List signal strength(in percentage), make it good 237 * looking, from 0~100. 238 * It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). 239 */ 240 if (is_cck_rate) { 241 phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, pwdb_all)); 242 } else { 243 if (rf_rx_num != 0) { 244 phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num)); 245 } 246 } 247} 248 249static void odm_Process_RSSIForDM( 250 struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo, struct odm_packet_info *pPktinfo 251) 252{ 253 254 s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK, UndecoratedSmoothedOFDM, RSSI_Ave; 255 u8 isCCKrate = 0; 256 u8 RSSI_max, RSSI_min, i; 257 u32 OFDM_pkt = 0; 258 u32 Weighting = 0; 259 PSTA_INFO_T pEntry; 260 261 262 if (pPktinfo->station_id == 0xFF) 263 return; 264 265 pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->station_id]; 266 267 if (!IS_STA_VALID(pEntry)) 268 return; 269 270 if ((!pPktinfo->bssid_match)) 271 return; 272 273 if (pPktinfo->is_beacon) 274 pDM_Odm->PhyDbgInfo.NumQryBeaconPkt++; 275 276 isCCKrate = ((pPktinfo->data_rate <= DESC_RATE11M)) ? true : false; 277 pDM_Odm->RxRate = pPktinfo->data_rate; 278 279 /* Statistic for antenna/path diversity------------------ */ 280 if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { 281 282 } 283 284 /* Smart Antenna Debug Message------------------ */ 285 286 UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; 287 UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; 288 UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; 289 290 if (pPktinfo->to_self || pPktinfo->is_beacon) { 291 292 if (!isCCKrate) { /* ofdm rate */ 293 if (pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] == 0) { 294 RSSI_Ave = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; 295 pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; 296 pDM_Odm->RSSI_B = 0; 297 } else { 298 pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; 299 pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; 300 301 if ( 302 pPhyInfo->rx_mimo_signal_strength[RF_PATH_A] > 303 pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] 304 ) { 305 RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; 306 RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; 307 } else { 308 RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; 309 RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; 310 } 311 312 if ((RSSI_max-RSSI_min) < 3) 313 RSSI_Ave = RSSI_max; 314 else if ((RSSI_max-RSSI_min) < 6) 315 RSSI_Ave = RSSI_max - 1; 316 else if ((RSSI_max-RSSI_min) < 10) 317 RSSI_Ave = RSSI_max - 2; 318 else 319 RSSI_Ave = RSSI_max - 3; 320 } 321 322 /* 1 Process OFDM RSSI */ 323 if (UndecoratedSmoothedOFDM <= 0) /* initialize */ 324 UndecoratedSmoothedOFDM = pPhyInfo->rx_pwd_ba11; 325 else { 326 if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedOFDM) { 327 UndecoratedSmoothedOFDM = 328 ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) + 329 RSSI_Ave)/Rx_Smooth_Factor; 330 UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; 331 } else { 332 UndecoratedSmoothedOFDM = 333 ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) + 334 RSSI_Ave)/Rx_Smooth_Factor; 335 } 336 } 337 338 pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0; 339 340 } else { 341 RSSI_Ave = pPhyInfo->rx_pwd_ba11; 342 pDM_Odm->RSSI_A = (u8) pPhyInfo->rx_pwd_ba11; 343 pDM_Odm->RSSI_B = 0; 344 345 /* 1 Process CCK RSSI */ 346 if (UndecoratedSmoothedCCK <= 0) /* initialize */ 347 UndecoratedSmoothedCCK = pPhyInfo->rx_pwd_ba11; 348 else { 349 if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedCCK) { 350 UndecoratedSmoothedCCK = 351 ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) + 352 pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor; 353 UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; 354 } else { 355 UndecoratedSmoothedCCK = 356 ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) + 357 pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor; 358 } 359 } 360 pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1; 361 } 362 363 /* if (pEntry) */ 364 { 365 /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ 366 if (pEntry->rssi_stat.ValidBit >= 64) 367 pEntry->rssi_stat.ValidBit = 64; 368 else 369 pEntry->rssi_stat.ValidBit++; 370 371 for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) 372 OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0; 373 374 if (pEntry->rssi_stat.ValidBit == 64) { 375 Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4); 376 UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6; 377 } else { 378 if (pEntry->rssi_stat.ValidBit != 0) 379 UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit; 380 else 381 UndecoratedSmoothedPWDB = 0; 382 } 383 384 pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; 385 pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; 386 pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; 387 } 388 389 } 390} 391 392 393/* */ 394/* Endianness before calling this API */ 395/* */ 396void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info, 397 u8 *phy_status, struct odm_packet_info *pkt_info) 398{ 399 400 odm_rx_phy_status_parsing(dm_odm, phy_info, phy_status, pkt_info); 401 402 if (!dm_odm->RSSI_test) 403 odm_Process_RSSIForDM(dm_odm, phy_info, pkt_info); 404} 405 406/* */ 407/* If you want to add a new IC, Please follow below template and generate a new one. */ 408/* */ 409/* */ 410 411enum hal_status ODM_ConfigRFWithHeaderFile( 412 struct dm_odm_t *pDM_Odm, 413 enum ODM_RF_Config_Type ConfigType, 414 enum rf_path eRFPath 415) 416{ 417 if (ConfigType == CONFIG_RF_RADIO) 418 READ_AND_CONFIG(8723B, _RadioA); 419 else if (ConfigType == CONFIG_RF_TXPWR_LMT) 420 READ_AND_CONFIG(8723B, _TXPWR_LMT); 421 422 return HAL_STATUS_SUCCESS; 423} 424 425enum hal_status ODM_ConfigRFWithTxPwrTrackHeaderFile(struct dm_odm_t *pDM_Odm) 426{ 427 if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO) 428 READ_AND_CONFIG(8723B, _TxPowerTrack_SDIO); 429 430 return HAL_STATUS_SUCCESS; 431} 432 433enum hal_status ODM_ConfigBBWithHeaderFile( 434 struct dm_odm_t *pDM_Odm, enum ODM_BB_Config_Type ConfigType 435) 436{ 437 if (ConfigType == CONFIG_BB_PHY_REG) 438 READ_AND_CONFIG(8723B, _PHY_REG); 439 else if (ConfigType == CONFIG_BB_AGC_TAB) 440 READ_AND_CONFIG(8723B, _AGC_TAB); 441 else if (ConfigType == CONFIG_BB_PHY_REG_PG) 442 READ_AND_CONFIG(8723B, _PHY_REG_PG); 443 444 return HAL_STATUS_SUCCESS; 445} 446 447