@@ -613,8 +613,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,
@@ -809,6 +808,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;
@@ -996,6 +996,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 {
@@ -812,33 +812,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 */
@@ -1081,6 +1089,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;
@@ -1089,6 +1098,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);
}
@@ -1134,8 +1144,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;
}
@@ -1144,7 +1154,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;
@@ -1152,26 +1161,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;
}
}
@@ -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);
@@ -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);
}
}
@@ -1565,6 +1575,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,
@@ -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,