diff options
8 files changed, 138 insertions, 14 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index eee48817d4d7..6ff554ba0250 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -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; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c index 9f40d261ac71..5a5b7fa4283c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c @@ -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), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c index e9bc94edfa79..9dfeeaa74927 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c @@ -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), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index bc0ec72d0126..973a02afc82b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -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), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c index 552763a2215c..8d8eb16a0970 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c @@ -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), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 9bfcb1e12183..9214c1d3b644 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -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), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 3bd9e5370b23..51cb22ee55cd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -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 && diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 190bc0e8dc33..04bf77959fba 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -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 |