1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTL8723A_REDESC_C_
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <rtl8723a_hal.h>
27 static s32 translate2dbm(u8 signal_strength_idx)
29 s32 signal_power; // in dBm.
32 // Translate to dBm (x=0.5y-95).
33 signal_power = (s32)((signal_strength_idx + 1) >> 1);
39 static u8 evm_db2percentage(s8 value)
42 // -33dB~0dB to 0%~99%
49 RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("EVMdbToPercentage92S Value=%d / %x \n", ret_val, ret_val));
56 ret_val = 0 - ret_val;
66 static s32 signal_scale_mapping(_adapter *padapter, s32 cur_sig )
71 if(cur_sig >= 51 && cur_sig <= 100)
75 else if(cur_sig >= 41 && cur_sig <= 50)
77 ret_sig = 80 + ((cur_sig - 40)*2);
79 else if(cur_sig >= 31 && cur_sig <= 40)
81 ret_sig = 66 + (cur_sig - 30);
83 else if(cur_sig >= 21 && cur_sig <= 30)
85 ret_sig = 54 + (cur_sig - 20);
87 else if(cur_sig >= 10 && cur_sig <= 20)
89 ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
91 else if(cur_sig >= 5 && cur_sig <= 9)
93 ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
95 else if(cur_sig >= 1 && cur_sig <= 4)
97 ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
104 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
106 if(pHalData->CustomerID == RT_CID_819x_Lenovo)
108 // Step 1. Scale mapping.
109 // 20100611 Joseph: Re-tunning RSSI presentation for Lenovo.
110 // 20100426 Joseph: Modify Signal strength mapping.
111 // This modification makes the RSSI indication similar to Intel solution.
112 // 20100414 Joseph: Tunning RSSI for Lenovo according to RTL8191SE.
113 if(cur_sig >= 54 && cur_sig <= 100)
117 else if(cur_sig>=42 && cur_sig <= 53 )
121 else if(cur_sig>=36 && cur_sig <= 41 )
123 ret_sig = 74 + ((cur_sig - 36) *20)/6;
125 else if(cur_sig>=33 && cur_sig <= 35 )
127 ret_sig = 65 + ((cur_sig - 33) *8)/2;
129 else if(cur_sig>=18 && cur_sig <= 32 )
131 ret_sig = 62 + ((cur_sig - 18) *2)/15;
133 else if(cur_sig>=15 && cur_sig <= 17 )
135 ret_sig = 33 + ((cur_sig - 15) *28)/2;
137 else if(cur_sig>=10 && cur_sig <= 14 )
141 else if(cur_sig>=8 && cur_sig <= 9 )
145 else if(cur_sig <= 8 )
152 // Step 1. Scale mapping.
153 if(cur_sig >= 61 && cur_sig <= 100)
155 ret_sig = 90 + ((cur_sig - 60) / 4);
157 else if(cur_sig >= 41 && cur_sig <= 60)
159 ret_sig = 78 + ((cur_sig - 40) / 2);
161 else if(cur_sig >= 31 && cur_sig <= 40)
163 ret_sig = 66 + (cur_sig - 30);
165 else if(cur_sig >= 21 && cur_sig <= 30)
167 ret_sig = 54 + (cur_sig - 20);
169 else if(cur_sig >= 5 && cur_sig <= 20)
171 ret_sig = 42 + (((cur_sig - 5) * 2) / 3);
173 else if(cur_sig == 4)
177 else if(cur_sig == 3)
181 else if(cur_sig == 2)
185 else if(cur_sig == 1)
201 void rtl8192c_query_rx_phy_status(union recv_frame *prframe, struct phy_stat *pphy_stat)
203 PHY_STS_OFDM_8192CD_T *pOfdm_buf;
204 PHY_STS_CCK_8192CD_T *pCck_buf;
205 u8 i, max_spatial_stream, evm;
206 s8 rx_pwr[4], rx_pwr_all = 0;
208 u32 rssi,total_rssi=0;
209 u8 bcck_rate=0, rf_rx_num = 0, cck_highpwr = 0;
210 _adapter *padapter = prframe->u.hdr.adapter;
211 struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
212 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
213 struct dm_priv *pdmpriv = &pHalData->dmpriv;
217 #ifdef CONFIG_HW_ANTENNA_DIVERSITY
218 PHY_RX_DRIVER_INFO_8192CD *pDrvInfo = ((PHY_RX_DRIVER_INFO_8192CD *)pphy_stat);
219 u8 bant1_sel = (pDrvInfo->ANTSEL == 1)?_TRUE:_FALSE;
222 // DBG_8192C("\n%s pphy_stat is NULL, Return\n",__FUNCTION__);
226 // Record it for next packet processing
227 bcck_rate=(pattrib->mcs_rate<=3? 1:0);
232 #ifdef CONFIG_HW_ANTENNA_DIVERSITY
233 if(bant1_sel == _TRUE)
234 pHalData->CCK_Ant1_Cnt++;
236 pHalData->CCK_Ant2_Cnt++;
239 // CCK Driver info Structure is not the same as OFDM packet.
240 pCck_buf = (PHY_STS_CCK_8192CD_T *)pphy_stat;
241 //Adapter->RxStats.NumQryPhyStatusCCK++;
244 // (1)Hardware does not provide RSSI for CCK
245 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
248 if(adapter_to_pwrctl(padapter)->rf_pwrstate == rf_on)
249 cck_highpwr = (u8)pHalData->bCckHighPower;
251 cck_highpwr = _FALSE;
255 report = pCck_buf->cck_agc_rpt&0xc0;
259 // 03312009 modified by cosa
260 // Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion
261 // Note: different RF with the different RNA gain.
263 rx_pwr_all = (-46) - (pCck_buf->cck_agc_rpt & 0x3e);
266 rx_pwr_all = (-26) - (pCck_buf->cck_agc_rpt & 0x3e);
269 rx_pwr_all = (-12) - (pCck_buf->cck_agc_rpt & 0x3e);
272 rx_pwr_all = (16) - (pCck_buf->cck_agc_rpt & 0x3e);
278 report = pCck_buf->cck_agc_rpt & 0x60;
283 rx_pwr_all = (-46) - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ;
286 rx_pwr_all = (-26)- ((pCck_buf->cck_agc_rpt & 0x1f)<<1);
289 rx_pwr_all = (-12) - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ;
292 rx_pwr_all = (16) - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ;
297 pwdb_all= query_rx_pwr_percentage(rx_pwr_all);
298 if(pHalData->CustomerID == RT_CID_819x_Lenovo)
300 // CCK gain is smaller than OFDM/MCS gain,
301 // so we add gain diff by experiences, the val is 6
305 // modify the offset to make the same gain index with OFDM.
306 if(pwdb_all > 34 && pwdb_all <= 42)
308 else if(pwdb_all > 26 && pwdb_all <= 34)
310 else if(pwdb_all > 14 && pwdb_all <= 26)
312 else if(pwdb_all > 4 && pwdb_all <= 14)
316 pattrib->RxPWDBAll = pwdb_all; //for DIG/rate adaptive
317 pattrib->RecvSignalPower = rx_pwr_all; //dBM
318 padapter->recvpriv.rxpwdb = rx_pwr_all;
320 // (3) Get Signal Quality (EVM)
322 //if(bPacketMatchBSSID)
326 if(pHalData->CustomerID == RT_CID_819x_Lenovo)
328 // mapping to 5 bars for vista signal strength
329 // signal quality in driver will be displayed to signal strength
333 else if(pwdb_all >= 35 && pwdb_all < 50)
335 else if(pwdb_all >= 22 && pwdb_all < 35)
337 else if(pwdb_all >= 18 && pwdb_all < 22)
350 sq = pCck_buf->SQ_rpt;
352 if(pCck_buf->SQ_rpt > 64)
354 else if (pCck_buf->SQ_rpt < 20)
357 sq = ((64-sq) * 100) / 44;
362 pattrib->signal_qual=sq;
363 pattrib->rx_mimo_signal_qual[0]=sq;
364 pattrib->rx_mimo_signal_qual[1]=(-1);
370 #ifdef CONFIG_HW_ANTENNA_DIVERSITY
371 if(bant1_sel == _TRUE)
372 pHalData->OFDM_Ant1_Cnt++;
374 pHalData->OFDM_Ant2_Cnt++;
376 pdmpriv->OFDM_Pkt_Cnt++;
378 pOfdm_buf = (PHY_STS_OFDM_8192CD_T *)pphy_stat;
381 // (1)Get RSSI per-path
383 for(i=0; i<pHalData->NumTotalRFPath; i++)
385 // 2008/01/30 MH we will judge RF RX path now.
386 if (pHalData->bRFPathRxEnable[i])
391 rx_pwr[i] = ((pOfdm_buf->trsw_gain_X[i]&0x3F)*2) - 110;
393 /* Translate DBM to percentage. */
394 rssi=query_rx_pwr_percentage(rx_pwr[i]);
397 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("RF-%d RXPWR=%x RSSI=%d\n", i, rx_pwr[i], rssi));
399 //Get Rx snr value in DB
400 tmp_rxsnr = pOfdm_buf->rxsnr_X[i];
401 rx_snrX = (s8)(tmp_rxsnr);
403 padapter->recvpriv.RxSNRdB[i] = (int)rx_snrX;
405 /* Record Signal Strength for next packet */
406 //if(bPacketMatchBSSID)
408 //pRfd->Status.RxMIMOSignalStrength[i] =(u1Byte) RSSI;
410 //The following is for lenovo signal strength in vista
411 if(pHalData->CustomerID == RT_CID_819x_Lenovo)
417 // mapping to 5 bars for vista signal strength
418 // signal quality in driver will be displayed to signal strength
422 else if(rssi >= 35 && rssi < 50)
424 else if(rssi >= 22 && rssi < 35)
426 else if(rssi >= 18 && rssi < 22)
430 //DbgPrint("ofdm/mcs RSSI=%d\n", RSSI);
431 //pRfd->Status.SignalQuality = SQ;
432 //DbgPrint("ofdm/mcs SQ = %d\n", pRfd->Status.SignalQuality);
440 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive),average
442 rx_pwr_all = (((pOfdm_buf->pwdb_all ) >> 1 )& 0x7f) -110;//for OFDM Average RSSI
443 pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
445 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("PWDB_ALL=%d\n", pwdb_all));
447 pattrib->RxPWDBAll = pwdb_all; //for DIG/rate adaptive
448 pattrib->RecvSignalPower = rx_pwr_all;//dBM
449 padapter->recvpriv.rxpwdb = rx_pwr_all;
453 if(pHalData->CustomerID != RT_CID_819x_Lenovo)
455 if(pattrib->rxht && pattrib->mcs_rate >=20 && pattrib->mcs_rate<=27)
456 max_spatial_stream = 2; //both spatial stream make sense
458 max_spatial_stream = 1; //only spatial stream 1 makes sense
460 for(i=0; i<max_spatial_stream; i++)
462 // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment
463 // fill most significant bit to "zero" when doing shifting operation which may change a negative
464 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
465 evm = evm_db2percentage( (pOfdm_buf->rxevm_X[i]/*/ 2*/));//dbm
467 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("RXRATE=%x RXEVM=%x EVM=%s%d\n",
468 pattrib->mcs_rate, pOfdm_buf->rxevm_X[i], "%",evm));
470 //if(bPacketMatchBSSID)
472 if(i==0) // Fill value in RFD, Get the first spatial stream only
474 pattrib->signal_qual = (u8)(evm & 0xff);
476 pattrib->rx_mimo_signal_qual[i] = (u8)(evm & 0xff);
483 // 4. Record rx statistics for debug
489 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
490 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
493 pattrib->signal_strength=(u8)signal_scale_mapping(padapter, pwdb_all);
499 pattrib->signal_strength= (u8)(signal_scale_mapping(padapter, total_rssi/=rf_rx_num));
502 //DBG_8192C("%s,rx_pwr_all(%d),RxPWDBAll(%d)\n",__FUNCTION__,rx_pwr_all,pattrib->RxPWDBAll);
508 static void process_rssi(_adapter *padapter,union recv_frame *prframe)
510 u32 last_rssi, tmp_val;
511 struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
512 #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
513 struct signal_stat * signal_stat = &padapter->recvpriv.signal_strength_data;
514 #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
516 //DBG_8192C("process_rssi=> pattrib->rssil(%d) signal_strength(%d)\n ",pattrib->RecvSignalPower,pattrib->signal_strength);
517 //if(pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon)
520 #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
521 if(signal_stat->update_req) {
522 signal_stat->total_num = 0;
523 signal_stat->total_val = 0;
524 signal_stat->update_req = 0;
527 signal_stat->total_num++;
528 signal_stat->total_val += pattrib->phy_info.SignalStrength;
529 signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
530 #else //CONFIG_NEW_SIGNAL_STAT_PROCESS
532 //Adapter->RxStats.RssiCalculateCnt++; //For antenna Test
533 if(padapter->recvpriv.signal_strength_data.total_num++ >= PHY_RSSI_SLID_WIN_MAX)
535 padapter->recvpriv.signal_strength_data.total_num = PHY_RSSI_SLID_WIN_MAX;
536 last_rssi = padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index];
537 padapter->recvpriv.signal_strength_data.total_val -= last_rssi;
539 padapter->recvpriv.signal_strength_data.total_val +=pattrib->phy_info.SignalStrength;
541 padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index++] = pattrib->phy_info.SignalStrength;
542 if(padapter->recvpriv.signal_strength_data.index >= PHY_RSSI_SLID_WIN_MAX)
543 padapter->recvpriv.signal_strength_data.index = 0;
546 tmp_val = padapter->recvpriv.signal_strength_data.total_val/padapter->recvpriv.signal_strength_data.total_num;
548 if(padapter->recvpriv.is_signal_dbg) {
549 padapter->recvpriv.signal_strength= padapter->recvpriv.signal_strength_dbg;
550 padapter->recvpriv.rssi=(s8)translate2dbm((u8)padapter->recvpriv.signal_strength_dbg);
552 padapter->recvpriv.signal_strength= tmp_val;
553 padapter->recvpriv.rssi=(s8)translate2dbm((u8)tmp_val);
556 RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("UI RSSI = %d, ui_rssi.TotalVal = %d, ui_rssi.TotalNum = %d\n", tmp_val, padapter->recvpriv.signal_strength_data.total_val,padapter->recvpriv.signal_strength_data.total_num));
557 #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
560 }// Process_UI_RSSI_8192C
563 static void process_PWDB(_adapter *padapter, union recv_frame *prframe)
565 int UndecoratedSmoothedPWDB;
566 int UndecoratedSmoothedCCK;
567 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
568 struct dm_priv *pdmpriv = &pHalData->dmpriv;
569 struct rx_pkt_attrib *pattrib= &prframe->u.hdr.attrib;
570 struct sta_info *psta = prframe->u.hdr.psta;
571 u8 isCCKrate=(pattrib->mcs_rate<=3? 1:0);
576 UndecoratedSmoothedPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
577 UndecoratedSmoothedCCK = psta->rssi_stat.UndecoratedSmoothedCCK;
581 UndecoratedSmoothedPWDB = pdmpriv->UndecoratedSmoothedPWDB;
582 UndecoratedSmoothedCCK = pdmpriv->UndecoratedSmoothedCCK;
585 //if(pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon)
590 if(UndecoratedSmoothedPWDB < 0) // initialize
592 UndecoratedSmoothedPWDB = pattrib->RxPWDBAll;
595 if(pattrib->RxPWDBAll > (u32)UndecoratedSmoothedPWDB)
597 UndecoratedSmoothedPWDB =
598 ( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) +
599 (pattrib->RxPWDBAll)) /(Rx_Smooth_Factor);
601 UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB + 1;
605 UndecoratedSmoothedPWDB =
606 ( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) +
607 (pattrib->RxPWDBAll)) /(Rx_Smooth_Factor);
613 if(UndecoratedSmoothedCCK < 0) // initialize
615 UndecoratedSmoothedCCK = pattrib->RxPWDBAll;
618 if(pattrib->RxPWDBAll > (u32)UndecoratedSmoothedCCK)
620 UndecoratedSmoothedCCK =
621 ( ((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
622 (pattrib->RxPWDBAll)) /(Rx_Smooth_Factor);
624 UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
628 UndecoratedSmoothedCCK =
629 ( ((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
630 (pattrib->RxPWDBAll)) /(Rx_Smooth_Factor);
638 //psta->UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;//todo:
639 pdmpriv->UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
641 if(pdmpriv->RSSI_Select == RSSI_OFDM)
642 psta->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
643 else if(pdmpriv->RSSI_Select == RSSI_CCK)
644 psta->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedCCK;
646 psta->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
650 //pdmpriv->UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
652 if(pdmpriv->RSSI_Select == RSSI_OFDM)
653 pdmpriv->UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
654 else if(pdmpriv->RSSI_Select == RSSI_CCK)
655 pdmpriv->UndecoratedSmoothedPWDB = UndecoratedSmoothedCCK;
657 pdmpriv->UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
660 //UpdateRxSignalStatistics8192C(padapter, prframe);
666 static void process_link_qual(_adapter *padapter,union recv_frame *prframe)
668 u32 last_evm=0, tmpVal;
669 struct rx_pkt_attrib *pattrib;
670 #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
671 struct signal_stat * signal_stat;
672 #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
674 if(prframe == NULL || padapter==NULL){
678 pattrib = &prframe->u.hdr.attrib;
679 #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
680 signal_stat = &padapter->recvpriv.signal_qual_data;
681 #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
683 //DBG_8192C("process_link_qual=> pattrib->signal_qual(%d)\n ",pattrib->signal_qual);
685 #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
686 if(signal_stat->update_req) {
687 signal_stat->total_num = 0;
688 signal_stat->total_val = 0;
689 signal_stat->update_req = 0;
692 signal_stat->total_num++;
693 signal_stat->total_val += pattrib->phy_info.SignalQuality;
694 signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
696 #else //CONFIG_NEW_SIGNAL_STAT_PROCESS
697 if(pattrib->phy_info.SignalQuality != 0)
700 // 1. Record the general EVM to the sliding window.
702 if(padapter->recvpriv.signal_qual_data.total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX)
704 padapter->recvpriv.signal_qual_data.total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
705 last_evm = padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index];
706 padapter->recvpriv.signal_qual_data.total_val -= last_evm;
708 padapter->recvpriv.signal_qual_data.total_val += pattrib->phy_info.SignalQuality;
710 padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index++] = pattrib->phy_info.SignalQuality;
711 if(padapter->recvpriv.signal_qual_data.index >= PHY_LINKQUALITY_SLID_WIN_MAX)
712 padapter->recvpriv.signal_qual_data.index = 0;
714 RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Total SQ=%d pattrib->signal_qual= %d\n", padapter->recvpriv.signal_qual_data.total_val, pattrib->phy_info.SignalQuality));
716 // <1> Showed on UI for user, in percentage.
717 tmpVal = padapter->recvpriv.signal_qual_data.total_val/padapter->recvpriv.signal_qual_data.total_num;
718 padapter->recvpriv.signal_qual=(u8)tmpVal;
723 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" pattrib->signal_qual =%d\n", pattrib->phy_info.SignalQuality));
725 #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
727 }// Process_UiLinkQuality8192S
730 //void rtl8192c_process_phy_info(_adapter *padapter, union recv_frame *prframe)
731 void rtl8192c_process_phy_info(_adapter *padapter, void *prframe)
733 union recv_frame *precvframe = (union recv_frame *)prframe;
737 process_rssi(padapter, precvframe);
741 //process_PWDB(padapter, precvframe);
743 //UpdateRxSignalStatistics8192C(Adapter, pRfd);
747 process_link_qual(padapter, precvframe);