diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 6161db5fcba6..297da821704b 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1835,6 +1835,20 @@ struct rtw_phy_cond { #define BRANCH_ENDIF 3 }; +struct rtw_phy_cond2 { +#ifdef __LITTLE_ENDIAN + u8 type_glna; + u8 type_gpa; + u8 type_alna; + u8 type_apa; +#else + u8 type_apa; + u8 type_alna; + u8 type_gpa; + u8 type_glna; +#endif +}; + struct rtw_fifo_conf { /* tx fifo information */ u16 rsvd_boundary; @@ -1916,6 +1930,7 @@ struct rtw_hal { u8 oem_id; u8 pkg_type; struct rtw_phy_cond phy_cond; + struct rtw_phy_cond2 phy_cond2; bool rfe_btg; u8 ps_mode; diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 0020ff6a50f8..db36276ccabc 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -18,7 +18,10 @@ struct phy_cfg_pair { }; union phy_table_tile { - struct rtw_phy_cond cond; + struct { + struct rtw_phy_cond cond; + struct rtw_phy_cond2 cond2; + } __packed; struct phy_cfg_pair cfg; }; @@ -1041,7 +1044,8 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) { struct rtw_hal *hal = &rtwdev->hal; struct rtw_efuse *efuse = &rtwdev->efuse; - struct rtw_phy_cond cond = {0}; + struct rtw_phy_cond cond = {}; + struct rtw_phy_cond2 cond2 = {}; cond.cut = hal->cut_version ? hal->cut_version : 15; cond.pkg = pkg ? pkg : 15; @@ -1061,15 +1065,34 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) break; } - hal->phy_cond = cond; + if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A || + rtwdev->chip->id == RTW_CHIP_TYPE_8821A) { + cond.rfe = 0; + cond.rfe |= efuse->ext_lna_2g; + cond.rfe |= efuse->ext_pa_2g << 1; + cond.rfe |= efuse->ext_lna_5g << 2; + cond.rfe |= efuse->ext_pa_5g << 3; + cond.rfe |= efuse->btcoex << 4; - rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x\n", *((u32 *)&hal->phy_cond)); + cond2.type_alna = efuse->alna_type; + cond2.type_glna = efuse->glna_type; + cond2.type_apa = efuse->apa_type; + cond2.type_gpa = efuse->gpa_type; + } + + hal->phy_cond = cond; + hal->phy_cond2 = cond2; + + rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x cond2=0x%08x\n", + *((u32 *)&hal->phy_cond), *((u32 *)&hal->phy_cond2)); } -static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) +static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond, + struct rtw_phy_cond2 cond2) { struct rtw_hal *hal = &rtwdev->hal; struct rtw_phy_cond drv_cond = hal->phy_cond; + struct rtw_phy_cond2 drv_cond2 = hal->phy_cond2; if (cond.cut && cond.cut != drv_cond.cut) return false; @@ -1080,8 +1103,29 @@ static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) if (cond.intf && cond.intf != drv_cond.intf) return false; - if (cond.rfe != drv_cond.rfe) - return false; + if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A || + rtwdev->chip->id == RTW_CHIP_TYPE_8821A) { + if (!(cond.rfe & 0x0f)) + return true; + + if ((cond.rfe & drv_cond.rfe) != cond.rfe) + return false; + + if ((cond.rfe & BIT(0)) && cond2.type_glna != drv_cond2.type_glna) + return false; + + if ((cond.rfe & BIT(1)) && cond2.type_gpa != drv_cond2.type_gpa) + return false; + + if ((cond.rfe & BIT(2)) && cond2.type_alna != drv_cond2.type_alna) + return false; + + if ((cond.rfe & BIT(3)) && cond2.type_apa != drv_cond2.type_apa) + return false; + } else { + if (cond.rfe != drv_cond.rfe) + return false; + } return true; } @@ -1090,7 +1134,8 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) { const union phy_table_tile *p = tbl->data; const union phy_table_tile *end = p + tbl->size / 2; - struct rtw_phy_cond pos_cond = {0}; + struct rtw_phy_cond pos_cond = {}; + struct rtw_phy_cond2 pos_cond2 = {}; bool is_matched = true, is_skipped = false; BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair)); @@ -1109,11 +1154,12 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) case BRANCH_ELIF: default: pos_cond = p->cond; + pos_cond2 = p->cond2; break; } } else if (p->cond.neg) { if (!is_skipped) { - if (check_positive(rtwdev, pos_cond)) { + if (check_positive(rtwdev, pos_cond, pos_cond2)) { is_matched = true; is_skipped = true; } else {