From: Tzu-En Huang <tehuang@xxxxxxxxxxx> Compared with 8822b, 8822c writes TX AGC table by reference and difference. These values can be calculated after we have a complete tx power table. Hence, driver needs to maintain a tx power table and collects the indexes before writing them into the tx agc table to let 8822b and 8822c chips share the same configuration flow. Signed-off-by: Tzu-En Huang <tehuang@xxxxxxxxxxx> Signed-off-by: Yan-Hsuan Chuang <yhchuang@xxxxxxxxxxx> --- drivers/net/wireless/realtek/rtw88/main.h | 6 +- drivers/net/wireless/realtek/rtw88/phy.c | 83 ++++++++++++++------------- drivers/net/wireless/realtek/rtw88/phy.h | 9 +++ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 43 ++++++++------ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 77 ++++++++++++++++++++++++- 5 files changed, 156 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index a660651..1a98747 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -614,8 +614,7 @@ struct rtw_chip_ops { u32 addr, u32 mask); bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, u32 addr, u32 mask, u32 data); - void (*set_tx_power_index)(struct rtw_dev *rtwdev, u8 power_index, - u8 rf_path, u8 rate); + void (*set_tx_power_index)(struct rtw_dev *rtwdev); int (*rsvd_page_dump)(struct rtw_dev *rtwdev, u8 *buf, u32 offset, u32 size); void (*set_antenna)(struct rtw_dev *rtwdev, u8 antenna_tx, @@ -810,6 +809,7 @@ struct rtw_chip_info { u8 dig_min; u8 txgi_factor; bool is_pwr_by_rate_dec; + u8 max_power_index; bool ht_supported; bool vht_supported; @@ -995,6 +995,8 @@ struct rtw_hal { [RTW_CHANNEL_WIDTH_MAX] [RTW_RATE_SECTION_MAX] [RTW_MAX_CHANNEL_NUM_5G]; + s8 tx_pwr_tbl[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; }; struct rtw_dev { diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 79f25e8..9b5b8bf 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -818,33 +818,41 @@ void rtw_phy_load_tables(struct rtw_dev *rtwdev) #define RTW_MAX_POWER_INDEX 0x3F -static u8 cck_rates[] = {DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, DESC_RATE11M}; -static u8 ofdm_rates[] = {DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, - DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, - DESC_RATE48M, DESC_RATE54M}; -static u8 ht_1s_rates[] = {DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, - DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, - DESC_RATEMCS6, DESC_RATEMCS7}; -static u8 ht_2s_rates[] = {DESC_RATEMCS8, DESC_RATEMCS9, DESC_RATEMCS10, - DESC_RATEMCS11, DESC_RATEMCS12, DESC_RATEMCS13, - DESC_RATEMCS14, DESC_RATEMCS15}; -static u8 vht_1s_rates[] = {DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, - DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, - DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, - DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, - DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9}; -static u8 vht_2s_rates[] = {DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, - DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, - DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, - DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, - DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9}; -static u8 cck_size = ARRAY_SIZE(cck_rates); -static u8 ofdm_size = ARRAY_SIZE(ofdm_rates); -static u8 ht_1s_size = ARRAY_SIZE(ht_1s_rates); -static u8 ht_2s_size = ARRAY_SIZE(ht_2s_rates); -static u8 vht_1s_size = ARRAY_SIZE(vht_1s_rates); -static u8 vht_2s_size = ARRAY_SIZE(vht_2s_rates); - +u8 cck_rates[] = {DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, DESC_RATE11M}; +u8 ofdm_rates[] = {DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, + DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, + DESC_RATE48M, DESC_RATE54M}; +u8 ht_1s_rates[] = {DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, + DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, + DESC_RATEMCS6, DESC_RATEMCS7}; +u8 ht_2s_rates[] = {DESC_RATEMCS8, DESC_RATEMCS9, DESC_RATEMCS10, + DESC_RATEMCS11, DESC_RATEMCS12, DESC_RATEMCS13, + DESC_RATEMCS14, DESC_RATEMCS15}; +u8 vht_1s_rates[] = {DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, + DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, + DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, + DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, + DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9}; +u8 vht_2s_rates[] = {DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, + DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, + DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, + DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, + DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9}; +u8 cck_size = ARRAY_SIZE(cck_rates); +u8 ofdm_size = ARRAY_SIZE(ofdm_rates); +u8 ht_1s_size = ARRAY_SIZE(ht_1s_rates); +u8 ht_2s_size = ARRAY_SIZE(ht_2s_rates); +u8 vht_1s_size = ARRAY_SIZE(vht_1s_rates); +u8 vht_2s_size = ARRAY_SIZE(vht_2s_rates); +u8 *rate_section[RTW_RATE_SECTION_MAX] = {cck_rates, ofdm_rates, + ht_1s_rates, ht_2s_rates, + vht_1s_rates, vht_2s_rates}; +u8 rate_size[RTW_RATE_SECTION_MAX] = {ARRAY_SIZE(cck_rates), + ARRAY_SIZE(ofdm_rates), + ARRAY_SIZE(ht_1s_rates), + ARRAY_SIZE(ht_2s_rates), + ARRAY_SIZE(vht_1s_rates), + ARRAY_SIZE(vht_2s_rates)}; static const u8 rtw_channel_idx_5g[RTW_MAX_CHANNEL_NUM_5G] = { 36, 38, 40, 42, 44, 46, 48, /* Band 1 */ 52, 54, 56, 58, 60, 62, 64, /* Band 2 */ @@ -1087,6 +1095,7 @@ void phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev, u8 ch, u8 path) void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel) { + struct rtw_chip_info *chip = rtwdev->chip; struct rtw_hal *hal = &rtwdev->hal; u8 path; @@ -1095,6 +1104,7 @@ void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel) for (path = 0; path < hal->rf_path_num; path++) phy_set_tx_power_level_by_path(rtwdev, channel, path); + chip->ops->set_tx_power_index(rtwdev); mutex_unlock(&hal->tx_power_mutex); } @@ -1140,8 +1150,8 @@ u8 phy_get_tx_power_index(void *adapter, u8 rf_path, u8 rate, tx_power += offset; - if (tx_power > RTW_MAX_POWER_INDEX) - tx_power = RTW_MAX_POWER_INDEX; + if (tx_power > rtwdev->chip->max_power_index) + tx_power = rtwdev->chip->max_power_index; return tx_power; } @@ -1150,7 +1160,6 @@ void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs) { struct rtw_dev *rtwdev = adapter; struct rtw_hal *hal = &rtwdev->hal; - struct rtw_chip_info *chip = rtwdev->chip; u8 regd = rtwdev->regd.txpwr_regd; u8 *rates; u8 size; @@ -1158,26 +1167,18 @@ void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs) u8 pwr_idx; u8 bw; int i; - u8 *rate_sections[RTW_RATE_SECTION_MAX] = { - cck_rates, ofdm_rates, ht_1s_rates, ht_2s_rates, - vht_1s_rates, vht_2s_rates, - }; - u8 sizes[RTW_RATE_SECTION_MAX] = { - cck_size, ofdm_size, ht_1s_size, ht_2s_size, - vht_1s_size, vht_2s_size, - }; if (rs >= RTW_RATE_SECTION_MAX) return; - rates = rate_sections[rs]; - size = sizes[rs]; + rates = rate_section[rs]; + size = rate_size[rs]; bw = hal->current_band_width; for (i = 0; i < size; i++) { rate = rates[i]; pwr_idx = phy_get_tx_power_index(adapter, path, rate, bw, ch, regd); - chip->ops->set_tx_power_index(rtwdev, pwr_idx, path, rate); + hal->tx_pwr_tbl[path][rate] = pwr_idx; } } diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index f855d75..8dfbb4b 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -7,6 +7,15 @@ #include "debug.h" +extern u8 cck_rates[]; +extern u8 ofdm_rates[]; +extern u8 ht_1s_rates[]; +extern u8 ht_2s_rates[]; +extern u8 vht_1s_rates[]; +extern u8 vht_2s_rates[]; +extern u8 *rate_section[]; +extern u8 rate_size[]; + void rtw_phy_init(struct rtw_dev *rtwdev); void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev); u8 rtw_phy_rf_power_2_rssi(s8 *rf_power, u8 path_num); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 376ed88..95af97f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -888,27 +888,37 @@ static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); } -static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev, u8 power_index, - u8 path, u8 rate) +static void +rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) { + struct rtw_hal *hal = &rtwdev->hal; static const u32 offset_txagc[2] = {0x1d00, 0x1d80}; static u32 phy_pwr_idx; - u8 rate_idx; - u8 shift; + u8 rate, rate_idx, pwr_index, shift; + int j; + + for (j = 0; j < rate_size[rs]; j++) { + rate = rate_section[rs][j]; + pwr_index = hal->tx_pwr_tbl[path][rate]; + shift = rate & 0x3; + phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); + if (shift == 0x3) { + rate_idx = rate & 0xfc; + rtw_write32(rtwdev, offset_txagc[path] + rate_idx, + phy_pwr_idx); + phy_pwr_idx = 0; + } + } +} - if (path > RF_PATH_B || rate > 0x53) - return; +static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + int rs, path; - /* - * 8822B uses four bytes tx power index, driver needs to combine every - * one-byte value for the phydm - */ - shift = rate & 0x3; - phy_pwr_idx |= ((u32)power_index << (shift * 8)); - if (shift == 0x3) { - rate_idx = rate & 0xfc; - rtw_write32(rtwdev, offset_txagc[path] + rate_idx, phy_pwr_idx); - phy_pwr_idx = 0; + for (path = 0; path < hal->rf_path_num; path++) { + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) + rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs); } } @@ -1566,6 +1576,7 @@ struct rtw_chip_info rtw8822b_hw_spec = { .rxff_size = 24576, .txgi_factor = 1, .is_pwr_by_rate_dec = true, + .max_power_index = 0x3f, .csi_buf_pg_num = 0, .band = RTW_BAND_2G | RTW_BAND_5G, .page_size = 128, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 19e8e7b..9c3f0f1 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -751,10 +751,80 @@ static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); } -static void rtw8822c_set_tx_power_index(struct rtw_dev *rtwdev, u8 power_index, - u8 path, u8 rate) +static void +rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck, + u8 *tx_pwr_ref_ofdm) { - /* 8822C will use TSSI to track tx power */ + struct rtw_hal *hal = &rtwdev->hal; + u32 txref_cck[2] = {0x18a0, 0x41a0}; + u32 txref_ofdm[2] = {0x18e8, 0x41e8}; + u8 path; + + for (path = 0; path < hal->rf_path_num; path++) { + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0); + rtw_write32_mask(rtwdev, txref_cck[path], 0x7f0000, + tx_pwr_ref_cck[path]); + } + for (path = 0; path < hal->rf_path_num; path++) { + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0); + rtw_write32_mask(rtwdev, txref_ofdm[path], 0x1fc00, + tx_pwr_ref_ofdm[path]); + } +} + +static void rtw8822c_set_tx_power_diff(struct rtw_dev *rtwdev, u8 rate, + s8 *diff_idx) +{ + u32 offset_txagc = 0x3a00; + u8 rate_idx = rate & 0xfc; + u8 pwr_idx[4]; + u32 phy_pwr_idx; + int i; + + for (i = 0; i < 4; i++) + pwr_idx[i] = diff_idx[i] & 0x7f; + + phy_pwr_idx = pwr_idx[0] | + (pwr_idx[1] << 8) | + (pwr_idx[2] << 16) | + (pwr_idx[3] << 24); + + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0x0); + rtw_write32_mask(rtwdev, offset_txagc + rate_idx, MASKDWORD, + phy_pwr_idx); +} + +static void rtw8822c_set_tx_power_index(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + u8 rs, rate, j; + u8 pwr_ref_cck[2] = {hal->tx_pwr_tbl[RF_PATH_A][DESC_RATE11M], + hal->tx_pwr_tbl[RF_PATH_B][DESC_RATE11M]}; + u8 pwr_ref_ofdm[2] = {hal->tx_pwr_tbl[RF_PATH_A][DESC_RATEMCS7], + hal->tx_pwr_tbl[RF_PATH_B][DESC_RATEMCS7]}; + s8 diff_a, diff_b; + u8 pwr_a, pwr_b; + s8 diff_idx[4]; + + rtw8822c_set_write_tx_power_ref(rtwdev, pwr_ref_cck, pwr_ref_ofdm); + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) { + for (j = 0; j < rate_size[rs]; j++) { + rate = rate_section[rs][j]; + pwr_a = hal->tx_pwr_tbl[RF_PATH_A][rate]; + pwr_b = hal->tx_pwr_tbl[RF_PATH_B][rate]; + if (rs == 0) { + diff_a = (s8)pwr_a - (s8)pwr_ref_cck[0]; + diff_b = (s8)pwr_b - (s8)pwr_ref_cck[1]; + } else { + diff_a = (s8)pwr_a - (s8)pwr_ref_ofdm[0]; + diff_b = (s8)pwr_b - (s8)pwr_ref_ofdm[1]; + } + diff_idx[rate % 4] = min(diff_a, diff_b); + if (rate % 4 == 3) + rtw8822c_set_tx_power_diff(rtwdev, rate - 3, + diff_idx); + } + } } static void rtw8822c_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) @@ -1182,6 +1252,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .rxff_size = 24576, .txgi_factor = 2, .is_pwr_by_rate_dec = false, + .max_power_index = 0x7f, .csi_buf_pg_num = 50, .band = RTW_BAND_2G | RTW_BAND_5G, .page_size = 128, -- 2.7.4