wifi: rtw89: fw: load TX power track tables from fw_element
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 13 Dec 2023 00:50:49 +0000 (08:50 +0800)
committerKalle Valo <kvalo@kernel.org>
Fri, 15 Dec 2023 13:38:25 +0000 (15:38 +0200)
The TX power track tables are used to define compensation power reflected
to thermal value. Currently, we have 16 (2 * 4 * 2) tables made by
combinations of
  {negative/positive thermal value, 2GHz/2GHz-CCK/5GHz/6GHz, path A/B}

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20231213005054.10568-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/phy.h

index b1e498ad149e4a6793df93f7e96833af1e3afa39..e5dd51f79a6f4fa8a3f7727f2a07880c0f65b876 100644 (file)
@@ -17,6 +17,7 @@ struct rtw89_pci_info;
 struct rtw89_mac_gen_def;
 struct rtw89_phy_gen_def;
 struct rtw89_efuse_block_cfg;
+struct rtw89_fw_txpwr_track_cfg;
 
 extern const struct ieee80211_ops rtw89_ops;
 
@@ -38,6 +39,8 @@ extern const struct ieee80211_ops rtw89_ops;
 #define RSSI_FACTOR 1
 #define RTW89_RSSI_RAW_TO_DBM(rssi) ((s8)((rssi) >> RSSI_FACTOR) - MAX_RSSI)
 #define RTW89_TX_DIV_RSSI_RAW_TH (2 << RSSI_FACTOR)
+#define DELTA_SWINGIDX_SIZE 30
+
 #define RTW89_RADIOTAP_ROOM_HE sizeof(struct ieee80211_radiotap_he)
 #define RTW89_RADIOTAP_ROOM_EHT \
        (sizeof(struct ieee80211_radiotap_tlv) + \
@@ -3948,6 +3951,7 @@ struct rtw89_fw_elm_info {
        struct rtw89_phy_table *bb_gain;
        struct rtw89_phy_table *rf_radio[RF_PATH_MAX];
        struct rtw89_phy_table *rf_nctl;
+       struct rtw89_fw_txpwr_track_cfg *txpwr_trk;
 };
 
 struct rtw89_fw_info {
index 81034b6ce4b040bce70da9a30fac16f7e232e2d8..f9727c00d8b9751fb06b2b14f377ec7d0d2a4512 100644 (file)
@@ -659,6 +659,72 @@ setup:
        return 0;
 }
 
+static
+int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
+                                      const struct rtw89_fw_element_hdr *elm,
+                                      const union rtw89_fw_element_arg arg)
+{
+       struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       u32 needed_bitmap = 0;
+       u32 offset = 0;
+       int subband;
+       u32 bitmap;
+       int type;
+
+       if (chip->support_bands & BIT(NL80211_BAND_6GHZ))
+               needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ;
+       if (chip->support_bands & BIT(NL80211_BAND_5GHZ))
+               needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_5GHZ;
+       if (chip->support_bands & BIT(NL80211_BAND_2GHZ))
+               needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_2GHZ;
+
+       bitmap = le32_to_cpu(elm->u.txpwr_trk.bitmap);
+
+       if ((bitmap & needed_bitmap) != needed_bitmap) {
+               rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %0x8x\n",
+                          needed_bitmap, bitmap);
+               return -ENOENT;
+       }
+
+       elm_info->txpwr_trk = kzalloc(sizeof(*elm_info->txpwr_trk), GFP_KERNEL);
+       if (!elm_info->txpwr_trk)
+               return -ENOMEM;
+
+       for (type = 0; bitmap; type++, bitmap >>= 1) {
+               if (!(bitmap & BIT(0)))
+                       continue;
+
+               if (type >= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_START &&
+                   type <= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_MAX)
+                       subband = 4;
+               else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_START &&
+                        type <= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_MAX)
+                       subband = 3;
+               else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_START &&
+                        type <= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_MAX)
+                       subband = 1;
+               else
+                       break;
+
+               elm_info->txpwr_trk->delta[type] = &elm->u.txpwr_trk.contents[offset];
+
+               offset += subband;
+               if (offset * DELTA_SWINGIDX_SIZE > le32_to_cpu(elm->size))
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       rtw89_warn(rtwdev, "unexpected txpwr trk offset %d over size %d\n",
+                  offset, le32_to_cpu(elm->size));
+       kfree(elm_info->txpwr_trk);
+       elm_info->txpwr_trk = NULL;
+
+       return -EFAULT;
+}
+
 static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
        [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
                                        { .fw_type = RTW89_FW_BBMCU0 }, NULL},
@@ -711,6 +777,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
                rtw89_fw_recognize_txpwr_from_elm,
                { .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt_ru.conf) }, NULL,
        },
+       [RTW89_FW_ELEMENT_ID_TXPWR_TRK] = {
+               rtw89_build_txpwr_trk_tbl_from_elm, {}, "PWR_TRK",
+       },
 };
 
 int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
@@ -1144,6 +1213,8 @@ static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev)
        for (i = 0; i < ARRAY_SIZE(elm_info->rf_radio); i++)
                rtw89_free_phy_tbl_from_elm(elm_info->rf_radio[i]);
        rtw89_free_phy_tbl_from_elm(elm_info->rf_nctl);
+
+       kfree(elm_info->txpwr_trk);
 }
 
 void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
index 2b2d142844655f88d8550cfb990e654187d8385c..033ea4467876051fa6a01bf869d2370db842509e 100644 (file)
@@ -3426,6 +3426,7 @@ enum rtw89_fw_element_id {
        RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_6GHZ = 15,
        RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT = 16,
        RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU = 17,
+       RTW89_FW_ELEMENT_ID_TXPWR_TRK = 18,
 
        RTW89_FW_ELEMENT_ID_NUM,
 };
@@ -3446,6 +3447,7 @@ enum rtw89_fw_element_id {
                                             BIT(RTW89_FW_ELEMENT_ID_RADIO_A) | \
                                             BIT(RTW89_FW_ELEMENT_ID_RADIO_B) | \
                                             BIT(RTW89_FW_ELEMENT_ID_RF_NCTL) | \
+                                            BIT(RTW89_FW_ELEMENT_ID_TXPWR_TRK) | \
                                             BITS_OF_RTW89_TXPWR_FW_ELEMENTS)
 
 struct __rtw89_fw_txpwr_element {
@@ -3457,6 +3459,59 @@ struct __rtw89_fw_txpwr_element {
        u8 content[];
 } __packed;
 
+enum rtw89_fw_txpwr_trk_type {
+       __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_START = 0,
+       RTW89_FW_TXPWR_TRK_TYPE_6GB_N = 0,
+       RTW89_FW_TXPWR_TRK_TYPE_6GB_P = 1,
+       RTW89_FW_TXPWR_TRK_TYPE_6GA_N = 2,
+       RTW89_FW_TXPWR_TRK_TYPE_6GA_P = 3,
+       __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_MAX = 3,
+
+       __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_START = 4,
+       RTW89_FW_TXPWR_TRK_TYPE_5GB_N = 4,
+       RTW89_FW_TXPWR_TRK_TYPE_5GB_P = 5,
+       RTW89_FW_TXPWR_TRK_TYPE_5GA_N = 6,
+       RTW89_FW_TXPWR_TRK_TYPE_5GA_P = 7,
+       __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_MAX = 7,
+
+       __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_START = 8,
+       RTW89_FW_TXPWR_TRK_TYPE_2GB_N = 8,
+       RTW89_FW_TXPWR_TRK_TYPE_2GB_P = 9,
+       RTW89_FW_TXPWR_TRK_TYPE_2GA_N = 10,
+       RTW89_FW_TXPWR_TRK_TYPE_2GA_P = 11,
+       RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N = 12,
+       RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P = 13,
+       RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N = 14,
+       RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P = 15,
+       __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_MAX = 15,
+
+       RTW89_FW_TXPWR_TRK_TYPE_NR,
+};
+
+struct rtw89_fw_txpwr_track_cfg {
+       const s8 (*delta[RTW89_FW_TXPWR_TRK_TYPE_NR])[DELTA_SWINGIDX_SIZE];
+};
+
+#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ \
+       (BIT(RTW89_FW_TXPWR_TRK_TYPE_6GB_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_6GB_P) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_6GA_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_6GA_P))
+#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_5GHZ \
+       (BIT(RTW89_FW_TXPWR_TRK_TYPE_5GB_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_5GB_P) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_5GA_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_5GA_P))
+#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_2GHZ \
+       (BIT(RTW89_FW_TXPWR_TRK_TYPE_2GB_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2GB_P) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2GA_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2GA_P) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N) | \
+        BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P))
+
 struct rtw89_fw_element_hdr {
        __le32 id; /* enum rtw89_fw_element_id */
        __le32 size; /* exclude header size */
@@ -3477,6 +3532,11 @@ struct rtw89_fw_element_hdr {
                                __le32 data;
                        } __packed regs[];
                } __packed reg2;
+               struct {
+                       __le32 bitmap; /* bitmap of enum rtw89_fw_txpwr_trk_type */
+                       __le32 rsvd;
+                       s8 contents[][DELTA_SWINGIDX_SIZE];
+               } __packed txpwr_trk;
                struct __rtw89_fw_txpwr_element txpwr;
        } __packed u;
 } __packed;
index d6363defcde6197de23d2f0bf6816bb73c7a29e5..6792b73e9ca34e5185665e6caacc1c16b92ab1ad 100644 (file)
@@ -291,8 +291,6 @@ struct rtw89_txpwr_byrate_cfg {
        u32 data;
 };
 
-#define DELTA_SWINGIDX_SIZE 30
-
 struct rtw89_txpwr_track_cfg {
        const s8 (*delta_swingidx_6gb_n)[DELTA_SWINGIDX_SIZE];
        const s8 (*delta_swingidx_6gb_p)[DELTA_SWINGIDX_SIZE];