wifi: rtl8xxxu: Fix the CCK RSSI calculation

The CCK RSSI calculation is incorrect for the RTL8723BU, RTL8192EU,
and RTL8188FU. Add new functions for these chips with code copied from
their vendor drivers. Use the old code only for the RTL8723AU and
RTL8192CU.

I didn't notice any difference in the reported signal strength with my
RTL8188FU, but I didn't look very hard either.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/926c838f-4997-698b-4da9-44582e2af99a@gmail.com
This commit is contained in:
Bitterblue Smith 2022-11-01 22:33:09 +02:00 committed by Kalle Valo
parent 57b328bc79
commit 2ad2a813b8
8 changed files with 138 additions and 14 deletions

View File

@ -1395,6 +1395,7 @@ struct rtl8xxxu_priv {
u32 ep_tx_normal_queue:1;
u32 ep_tx_low_queue:1;
u32 rx_buf_aggregation:1;
u32 cck_agc_report_type:1;
u8 default_crystal_cap;
unsigned int pipe_interrupt;
unsigned int pipe_in;
@ -1499,6 +1500,7 @@ struct rtl8xxxu_fileops {
bool short_preamble, bool ampdu_enable,
u32 rts_rate);
void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
int writeN_block_size;
int rx_agg_buf_size;
char tx_desc_size;
@ -1609,6 +1611,7 @@ void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8192cu_fops;

View File

@ -1658,6 +1658,37 @@ static void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
cfo->crystal_cap = crystal_cap;
}
static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
{
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
lna_idx = (cck_agc_rpt & 0xE0) >> 5;
vga_idx = cck_agc_rpt & 0x1F;
switch (lna_idx) {
case 7:
if (vga_idx <= 27)
rx_pwr_all = -100 + 2 * (27 - vga_idx);
else
rx_pwr_all = -100;
break;
case 5:
rx_pwr_all = -74 + 2 * (21 - vga_idx);
break;
case 3:
rx_pwr_all = -60 + 2 * (20 - vga_idx);
break;
case 1:
rx_pwr_all = -44 + 2 * (19 - vga_idx);
break;
default:
break;
}
return rx_pwr_all;
}
struct rtl8xxxu_fileops rtl8188fu_fops = {
.parse_efuse = rtl8188fu_parse_efuse,
.load_firmware = rtl8188fu_load_firmware,
@ -1682,6 +1713,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
.set_crystal_cap = rtl8188f_set_crystal_cap,
.cck_rssi = rtl8188f_cck_rssi,
.writeN_block_size = 128,
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),

View File

@ -561,6 +561,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.update_rate_mask = rtl8xxxu_update_rate_mask,
.report_connect = rtl8xxxu_gen1_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
.cck_rssi = rtl8723a_cck_rssi,
.writeN_block_size = 128,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),

View File

@ -1670,6 +1670,28 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8);
}
static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
{
static const s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44};
static const s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36};
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
s8 lna_gain = 0;
lna_idx = (cck_agc_rpt & 0xE0) >> 5;
vga_idx = cck_agc_rpt & 0x1F;
if (priv->cck_agc_report_type == 0)
lna_gain = lna_gain_table_0[lna_idx];
else
lna_gain = lna_gain_table_1[lna_idx];
rx_pwr_all = lna_gain - (2 * vga_idx);
return rx_pwr_all;
}
struct rtl8xxxu_fileops rtl8192eu_fops = {
.parse_efuse = rtl8192eu_parse_efuse,
.load_firmware = rtl8192eu_load_firmware,
@ -1691,6 +1713,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
.set_crystal_cap = rtl8723a_set_crystal_cap,
.cck_rssi = rtl8192e_cck_rssi,
.writeN_block_size = 128,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),

View File

@ -386,6 +386,28 @@ void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
cfo->crystal_cap = crystal_cap;
}
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
{
s8 rx_pwr_all = 0x00;
switch (cck_agc_rpt & 0xc0) {
case 0xc0:
rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
break;
case 0x80:
rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
break;
case 0x40:
rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
break;
case 0x00:
rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
break;
}
return rx_pwr_all;
}
struct rtl8xxxu_fileops rtl8723au_fops = {
.parse_efuse = rtl8723au_parse_efuse,
.load_firmware = rtl8723au_load_firmware,
@ -408,6 +430,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
.report_connect = rtl8xxxu_gen1_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
.set_crystal_cap = rtl8723a_set_crystal_cap,
.cck_rssi = rtl8723a_cck_rssi,
.writeN_block_size = 1024,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),

View File

@ -1639,6 +1639,34 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv)
rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32);
}
static s8 rtl8723b_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
{
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
lna_idx = (cck_agc_rpt & 0xE0) >> 5;
vga_idx = cck_agc_rpt & 0x1F;
switch (lna_idx) {
case 6:
rx_pwr_all = -34 - (2 * vga_idx);
break;
case 4:
rx_pwr_all = -14 - (2 * vga_idx);
break;
case 1:
rx_pwr_all = 6 - (2 * vga_idx);
break;
case 0:
rx_pwr_all = 16 - (2 * vga_idx);
break;
default:
break;
}
return rx_pwr_all;
}
struct rtl8xxxu_fileops rtl8723bu_fops = {
.parse_efuse = rtl8723bu_parse_efuse,
.load_firmware = rtl8723bu_load_firmware,
@ -1663,6 +1691,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
.set_crystal_cap = rtl8723a_set_crystal_cap,
.cck_rssi = rtl8723b_cck_rssi,
.writeN_block_size = 1024,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),

View File

@ -4318,6 +4318,29 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val32 &= 0xfff00fff;
val32 |= 0x0007e000;
rtl8xxxu_write32(priv, REG_AFE_MISC, val32);
/*
* 0x824[9] = 0x82C[9] = 0xA80[7] those registers setting
* should be equal or CCK RSSI report may be incorrect
*/
val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2);
priv->cck_agc_report_type = val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_HSSI_PARM2);
if (priv->cck_agc_report_type != (bool)(val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR)) {
if (priv->cck_agc_report_type)
val32 |= FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
else
val32 &= ~FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM2, val32);
}
val32 = rtl8xxxu_read32(priv, REG_AGC_RPT);
if (priv->cck_agc_report_type)
val32 |= AGC_RPT_CCK;
else
val32 &= ~AGC_RPT_CCK;
rtl8xxxu_write32(priv, REG_AGC_RPT, val32);
}
/* Initialise the center frequency offset tracking */
@ -5307,20 +5330,7 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
*/
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
switch (cck_agc_rpt & 0xc0) {
case 0xc0:
rx_status->signal = -46 - (cck_agc_rpt & 0x3e);
break;
case 0x80:
rx_status->signal = -26 - (cck_agc_rpt & 0x3e);
break;
case 0x40:
rx_status->signal = -12 - (cck_agc_rpt & 0x3e);
break;
case 0x00:
rx_status->signal = 16 - (cck_agc_rpt & 0x3e);
break;
}
rx_status->signal = priv->fops->cck_rssi(priv, cck_agc_rpt);
} else {
bool parse_cfo = priv->fops->set_crystal_cap &&
priv->vif &&

View File

@ -960,6 +960,9 @@
#define CCK_PD_TYPE1_LV3_TH 0xdd
#define CCK_PD_TYPE1_LV4_TH 0xed
#define REG_AGC_RPT 0xa80
#define AGC_RPT_CCK BIT(7)
#define REG_CONFIG_ANT_A 0x0b68
#define REG_CONFIG_ANT_B 0x0b6c