Commit 608d2a08 authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo

rtw88: 8723d: Add power tracking

When chip's temperature is changed, RF characters are changed. To keep the
characters to be consistent, 8723d uses thermal meter to assist in
calibrating LCK, IQK, crystal and TX power.

A base thermal value is programmed in efuse, all calibration data in
MP process is based on this thermal value. So we calucate the delta of
thermal value between the base value, and use this delta to reference XTAL
and TX power offset tables to know how much we need to adjust.

For IQK and LCK, driver checks if delta of thermal value is over 8, then
they are triggered.

For crystal adjustment, when delta of thermal value is changed, we check
XTAL tables to get offset of XTAL value. If thermal value is larger than
base value, positive table (_p as suffix) is used. Otherwise, we use
negative table (_n as suffix). Then, we add offset to XTAL default value
programmed in efuse, and write sum value to register.

To compensate TX power, there are two hierarchical tables. First level use
delta of thermal value to access eight tables to yield delta of TX power
index. Then, plus base TX power index to get index of BB swing table
(second level tables) where register value is induced.

BB swing table can't deal with all cases, if index of BB swing table is
over the size of the table. In this case, TX AGC is used to compensate the
remnant part. Assume 'upper' is the upper bound of BB swing table, and
'target' is the desired index. Then, we can illustrate them as

  compensation method    BB swing        TX AGC
  -------------------    --------    --------------
  target > upper         upper       target - upper
  target < 0             0           target
  otherwise              target      0

For debug purpose, add a column 'rem' to tx_pwr_tbl entry, and it looks
like

  path rate       pwr       base      (byr  lmt ) rem
    A  CCK_1M     32(0x20)   34   -2 (   0   -2)    0
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarYan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200512102621.5148-4-yhchuang@realtek.com
parent 1d229e88
...@@ -531,8 +531,8 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) ...@@ -531,8 +531,8 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
u8 ch = hal->current_channel; u8 ch = hal->current_channel;
u8 regd = rtwdev->regd.txpwr_regd; u8 regd = rtwdev->regd.txpwr_regd;
seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n", seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n",
"path", "rate", "pwr", "", "base", "", "byr", "lmt"); "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem");
mutex_lock(&hal->tx_power_mutex); mutex_lock(&hal->tx_power_mutex);
for (path = RF_PATH_A; path <= RF_PATH_B; path++) { for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
...@@ -554,13 +554,14 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) ...@@ -554,13 +554,14 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
seq_printf(m, "%4c ", path + 'A'); seq_printf(m, "%4c ", path + 'A');
rtw_print_rate(m, rate); rtw_print_rate(m, rate);
seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n", seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n",
hal->tx_pwr_tbl[path][rate], hal->tx_pwr_tbl[path][rate],
hal->tx_pwr_tbl[path][rate], hal->tx_pwr_tbl[path][rate],
pwr_param.pwr_base, pwr_param.pwr_base,
min_t(s8, pwr_param.pwr_offset, min_t(s8, pwr_param.pwr_offset,
pwr_param.pwr_limit), pwr_param.pwr_limit),
pwr_param.pwr_offset, pwr_param.pwr_limit); pwr_param.pwr_offset, pwr_param.pwr_limit,
pwr_param.pwr_remnant);
} }
} }
......
...@@ -1056,6 +1056,8 @@ struct rtw_pwr_track_tbl { ...@@ -1056,6 +1056,8 @@ struct rtw_pwr_track_tbl {
const u8 *pwrtrk_2g_cckb_p; const u8 *pwrtrk_2g_cckb_p;
const u8 *pwrtrk_2g_ccka_n; const u8 *pwrtrk_2g_ccka_n;
const u8 *pwrtrk_2g_ccka_p; const u8 *pwrtrk_2g_ccka_p;
const s8 *pwrtrk_xtal_n;
const s8 *pwrtrk_xtal_p;
}; };
enum rtw_wlan_cpu { enum rtw_wlan_cpu {
...@@ -1447,6 +1449,8 @@ struct rtw_dm_info { ...@@ -1447,6 +1449,8 @@ struct rtw_dm_info {
bool pwr_trk_triggered; bool pwr_trk_triggered;
bool pwr_trk_init_trigger; bool pwr_trk_init_trigger;
struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX]; struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
s8 txagc_remnant_cck;
s8 txagc_remnant_ofdm;
/* backup dack results for each path and I/Q */ /* backup dack results for each path and I/Q */
u32 dack_adck[RTW_RF_PATH_MAX]; u32 dack_adck[RTW_RF_PATH_MAX];
......
...@@ -1785,11 +1785,13 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, ...@@ -1785,11 +1785,13 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw,
u8 ch, u8 regd, struct rtw_power_params *pwr_param) u8 ch, u8 regd, struct rtw_power_params *pwr_param)
{ {
struct rtw_hal *hal = &rtwdev->hal; struct rtw_hal *hal = &rtwdev->hal;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_txpwr_idx *pwr_idx; struct rtw_txpwr_idx *pwr_idx;
u8 group, band; u8 group, band;
u8 *base = &pwr_param->pwr_base; u8 *base = &pwr_param->pwr_base;
s8 *offset = &pwr_param->pwr_offset; s8 *offset = &pwr_param->pwr_offset;
s8 *limit = &pwr_param->pwr_limit; s8 *limit = &pwr_param->pwr_limit;
s8 *remnant = &pwr_param->pwr_remnant;
pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; pwr_idx = &rtwdev->efuse.txpwr_idx_table[path];
group = rtw_get_channel_group(ch); group = rtw_get_channel_group(ch);
...@@ -1811,6 +1813,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, ...@@ -1811,6 +1813,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw,
*limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path, *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path,
rate, ch, regd); rate, ch, regd);
*remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
dm_info->txagc_remnant_ofdm);
} }
u8 u8
...@@ -1830,7 +1834,7 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate, ...@@ -1830,7 +1834,7 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate,
if (rtwdev->chip->en_dis_dpd) if (rtwdev->chip->en_dis_dpd)
offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate);
tx_power += offset; tx_power += offset + pwr_param.pwr_remnant;
if (tx_power > rtwdev->chip->max_power_index) if (tx_power > rtwdev->chip->max_power_index)
tx_power = rtwdev->chip->max_power_index; tx_power = rtwdev->chip->max_power_index;
......
...@@ -141,6 +141,7 @@ struct rtw_power_params { ...@@ -141,6 +141,7 @@ struct rtw_power_params {
u8 pwr_base; u8 pwr_base;
s8 pwr_offset; s8 pwr_offset;
s8 pwr_limit; s8 pwr_limit;
s8 pwr_remnant;
}; };
void void
......
...@@ -112,6 +112,13 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) ...@@ -112,6 +112,13 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
return (t >> 8); /* Q.16 --> Q.8 */ return (t >> 8); /* Q.16 --> Q.8 */
} }
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
#define RTW_DEF_OFDM_SWING_INDEX 28
#define RTW_DEF_CCK_SWING_INDEX 28
#define MAX_TOLERANCE 5 #define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142 #define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42 #define IQK_TX_Y_ERR 0x42
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment