// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2010 Realtek Corporation.*/
#include "../wifi.h"
#include "../pci.h"
#include "../base.h"
#include "../stats.h"
#include "reg.h"
#include "def.h"
#include "trx.h"
#include "led.h"
#include "dm.h"
#include "phy.h"
#include "fw.h"
static u8 _rtl8821ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
{
__le16 fc = rtl_get_fc(skb);
if (unlikely(ieee80211_is_beacon(fc)))
return QSLT_BEACON;
if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
return QSLT_MGNT;
return skb->priority;
}
static u16 odm_cfo(s8 value)
{
int ret_val;
if (value < 0) {
ret_val = 0 - value;
ret_val = (ret_val << 1) + (ret_val >> 1);
/* set bit12 as 1 for negative cfo */
ret_val = ret_val | BIT(12);
} else {
ret_val = value;
ret_val = (ret_val << 1) + (ret_val >> 1);
}
return ret_val;
}
static u8 _rtl8821ae_evm_dbm_jaguar(s8 value)
{
s8 ret_val = value;
/* -33dB~0dB to 33dB ~ 0dB*/
if (ret_val == -128)
ret_val = 127;
else if (ret_val < 0)
ret_val = 0 - ret_val;
ret_val = ret_val >> 1;
return ret_val;
}
static void query_rxphystatus(struct ieee80211_hw *hw,
struct rtl_stats *pstatus, __le32 *pdesc,
struct rx_fwinfo_8821ae *p_drvinfo,
bool bpacket_match_bssid,
bool bpacket_toself, bool packet_beacon)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo;
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct rtl_phy *rtlphy = &rtlpriv->phy;
s8 rx_pwr_all = 0, rx_pwr[4];
u8 rf_rx_num = 0, evm, evmdbm, pwdb_all;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
bool is_cck = pstatus->is_cck;
u8 lan_idx, vga_idx;
/* Record it for next packet processing */
pstatus->packet_matchbssid = bpacket_match_bssid;
pstatus->packet_toself = bpacket_toself;
pstatus->packet_beacon = packet_beacon;
pstatus->rx_mimo_signalquality[0] = -1;
pstatus->rx_mimo_signalquality[1] = -1;
if (is_cck) {
u8 cck_highpwr;
u8 cck_agc_rpt;
cck_agc_rpt = p_phystrpt->cfosho[0];
/* (1)Hardware does not provide RSSI for CCK
* (2)PWDB, Average PWDB calculated by
* hardware (for rate adaptive)
*/
cck_highpwr = (u8)rtlphy->cck_high_power;
lan_idx = ((cck_agc_rpt & 0xE0) >> 5);
vga_idx = (cck_agc_rpt & 0x1f);
if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) {
switch (lan_idx) {
case 7:
if (vga_idx <= 27)
/*VGA_idx = 27~2*/
rx_pwr_all = -100 + 2*(27-vga_idx);
else
rx_pwr_all = -100;
break;
case 6:
/*VGA_idx = 2~0*/
rx_pwr_all = -48 + 2*(2-vga_idx);
break;
case 5:
/*VGA_idx = 7~5*/
rx_pwr_all = -42 + 2*(7-vga_idx);
break;
case 4:
/*VGA_idx = 7~4*/
rx_pwr_all = -36 + 2*(7-vga_idx);
break;
case 3:
/*VGA_idx = 7~0*/
rx_pwr_all = -24 + 2*(7-vga_idx);
break;
case 2:
if (cck_highpwr)
/*VGA_idx = 5~0*/
rx_pwr_all = -12 + 2*(5-vga_idx);
else
rx_pwr_all = -6 + 2*(5-vga_idx);
break;
case 1:
rx_pwr_all = 8-2*vga_idx;
break;
case 0:
rx_pwr_all = 14-2*vga_idx;
break;
default:
break;
}
rx_pwr_all += 6;
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
if (!cck_highpwr) {
if (pwdb_all >= 80)
pwdb_all =
((pwdb_all - 80)<<1) +
((pwdb_all - 80)>>1) + 80;
else if ((pwdb_all <= 78) && (pwdb_all >= 20))
pwdb_all += 3;
if (pwdb_all > 100)
pwdb_all = 100;
}
} else { /* 8821 */
s8 pout = -6;
switch (lan_idx) {
case 5:
rx_pwr_all = pout - 32 - (2*vga_idx);
break;
case 4:
rx_pwr_all = pout - 24 - (2*vga_idx);
break;
case 2:
rx_pwr_all = pout - 11 - (2*vga_idx);
break;
case 1:
rx_pwr_all = pout + 5 - (2*vga_idx);
break;
case 0:
rx_pwr_all = pout + 21 - (2*vga_idx);
break;
}
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
}
pstatus->rx_pwdb_all = pwdb_all;
pstatus->recvsignalpower = rx_pwr_all;
/* (3) Get Signal Quality (EVM) */
if (bpacket_match_bssid) {
u8 sq;
if (<