aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw88/rtw8821c.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c116
1 files changed, 96 insertions, 20 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index fbfd85439d1f..33c6cf1206c8 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -15,12 +15,23 @@
#include "debug.h"
#include "bf.h"
+static const s8 lna_gain_table_0[8] = {22, 8, -6, -22, -31, -40, -46, -52};
+static const s8 lna_gain_table_1[16] = {10, 6, 2, -2, -6, -10, -14, -17,
+ -20, -24, -28, -31, -34, -37, -40, -44};
+
static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8821c_efuse *map)
{
ether_addr_copy(efuse->addr, map->e.mac_addr);
}
+enum rtw8821ce_rf_set {
+ SWITCH_TO_BTG,
+ SWITCH_TO_WLG,
+ SWITCH_TO_WLA,
+ SWITCH_TO_BT,
+};
+
static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
@@ -224,6 +235,40 @@ static void rtw8821c_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}
+static void rtw8821c_switch_rf_set(struct rtw_dev *rtwdev, u8 rf_set)
+{
+ u32 reg;
+
+ rtw_write32_set(rtwdev, REG_DMEM_CTRL, BIT_WL_RST);
+ rtw_write32_set(rtwdev, REG_SYS_CTRL, BIT_FEN_EN);
+
+ reg = rtw_read32(rtwdev, REG_RFECTL);
+ switch (rf_set) {
+ case SWITCH_TO_BTG:
+ reg |= B_BTG_SWITCH;
+ reg &= ~(B_CTRL_SWITCH | B_WL_SWITCH | B_WLG_SWITCH |
+ B_WLA_SWITCH);
+ rtw_write32_mask(rtwdev, REG_ENRXCCA, MASKBYTE2, BTG_CCA);
+ rtw_write32_mask(rtwdev, REG_ENTXCCK, MASKLWORD, BTG_LNA);
+ break;
+ case SWITCH_TO_WLG:
+ reg |= B_WL_SWITCH | B_WLG_SWITCH;
+ reg &= ~(B_BTG_SWITCH | B_CTRL_SWITCH | B_WLA_SWITCH);
+ rtw_write32_mask(rtwdev, REG_ENRXCCA, MASKBYTE2, WLG_CCA);
+ rtw_write32_mask(rtwdev, REG_ENTXCCK, MASKLWORD, WLG_LNA);
+ break;
+ case SWITCH_TO_WLA:
+ reg |= B_WL_SWITCH | B_WLA_SWITCH;
+ reg &= ~(B_BTG_SWITCH | B_CTRL_SWITCH | B_WLG_SWITCH);
+ break;
+ case SWITCH_TO_BT:
+ default:
+ break;
+ }
+
+ rtw_write32(rtwdev, REG_RFECTL, reg);
+}
+
static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
{
u32 rf_reg18;
@@ -257,9 +302,14 @@ static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
}
if (channel <= 14) {
+ if (rtwdev->efuse.rfe_option == 0)
+ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG);
+ else if (rtwdev->efuse.rfe_option == 2)
+ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_BTG);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x1);
rtw_write_rf(rtwdev, RF_PATH_A, 0x64, 0xf, 0xf);
} else {
+ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLA);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x0);
}
@@ -426,17 +476,49 @@ static void rtw8821c_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw8821c_set_channel_rxdfir(rtwdev, bw);
}
+static s8 get_cck_rx_pwr(struct rtw_dev *rtwdev, u8 lna_idx, u8 vga_idx)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ const s8 *lna_gain_table;
+ int lna_gain_table_size;
+ s8 rx_pwr_all = 0;
+ s8 lna_gain = 0;
+
+ if (efuse->rfe_option == 0) {
+ lna_gain_table = lna_gain_table_0;
+ lna_gain_table_size = ARRAY_SIZE(lna_gain_table_0);
+ } else {
+ lna_gain_table = lna_gain_table_1;
+ lna_gain_table_size = ARRAY_SIZE(lna_gain_table_1);
+ }
+
+ if (lna_idx >= lna_gain_table_size) {
+ rtw_info(rtwdev, "incorrect lna index (%d)\n", lna_idx);
+ return -120;
+ }
+
+ lna_gain = lna_gain_table[lna_idx];
+ rx_pwr_all = lna_gain - 2 * vga_idx;
+
+ return rx_pwr_all;
+}
+
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
- s8 min_rx_power = -120;
- u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
+ s8 rx_power;
+ u8 lna_idx = 0;
+ u8 vga_idx = 0;
- pkt_stat->rx_power[RF_PATH_A] = pwdb - 100;
+ vga_idx = GET_PHY_STAT_P0_VGA(phy_status);
+ lna_idx = FIELD_PREP(BIT_LNA_H_MASK, GET_PHY_STAT_P0_LNA_H(phy_status)) |
+ FIELD_PREP(BIT_LNA_L_MASK, GET_PHY_STAT_P0_LNA_L(phy_status));
+ rx_power = get_cck_rx_pwr(rtwdev, lna_idx, vga_idx);
+
+ pkt_stat->rx_power[RF_PATH_A] = rx_power;
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
- pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
- min_rx_power);
+ pkt_stat->signal_power = rx_power;
}
static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
@@ -719,8 +801,8 @@ static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
regval = (!polarity_inverse ? 0x1 : 0x2);
}
- rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
- regval);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
+ regval);
break;
case COEX_SWITCH_CTRL_BY_PTA:
rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
@@ -730,8 +812,8 @@ static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
PTA_CTRL_PIN);
regval = (!polarity_inverse ? 0x2 : 0x1);
- rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
- regval);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
+ regval);
break;
case COEX_SWITCH_CTRL_BY_ANTDIV:
rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
@@ -757,11 +839,11 @@ static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
}
if (ctrl_type == COEX_SWITCH_CTRL_BY_BT) {
- rtw_write32_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
- rtw_write32_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
+ rtw_write8_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
+ rtw_write8_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
} else {
- rtw_write32_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
- rtw_write32_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
+ rtw_write8_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
+ rtw_write8_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
}
}
@@ -1022,12 +1104,6 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
u8 pd[CCK_PD_LV_MAX] = {3, 7, 13, 13, 13};
u8 cck_n_rx;
- if (dm_info->min_rssi > 60) {
- new_lvl = 4;
- pd[4] = 0x1d;
- goto set_cck_pd;
- }
-
rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n",
dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl);
@@ -1044,7 +1120,6 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
-set_cck_pd:
dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl;
rtw_write32_mask(rtwdev, REG_PWRTH, 0x3f0000, pd[new_lvl]);
rtw_write32_mask(rtwdev, REG_PWRTH2, 0x1f0000,
@@ -1421,6 +1496,7 @@ static const struct rtw_intf_phy_para_table phy_para_table_8821c = {
static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
[0] = RTW_DEF_RFE(8821c, 0, 0),
+ [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
};
static struct rtw_hw_reg rtw8821c_dig[] = {