Commit 5227c2ee authored by Tzu-En Huang's avatar Tzu-En Huang Committed by Kalle Valo
Browse files

rtw88: 8822c: add SW DPK support



Power amplifiers are not linear components, and require DPK to
reduce its nonlinearity. DPK is called Digital Pre-distortion
Calibration, can be used to compensate the output of power.

DPK tracking is in charge of tracking the thermal changes. And
it then shifts the power curve accordingly, which makes the
power output remains linear even if the PA works in different
temperature.

To perform DPK, the parameter table should also be updated.
And the table will be applied when device is powered on.
Then DPK will reference the values to calibrate.

Signed-off-by: default avatarTzu-En Huang <tehuang@realtek.com>
Signed-off-by: default avatarYan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 1ac3294b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -721,7 +721,7 @@ static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
	rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
}

static u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
{
	u32 val;

+1 −0
Original line number Diff line number Diff line
@@ -346,6 +346,7 @@ void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
}

void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb);
u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr);
void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
				 u32 mask, u32 val);
void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set);
+38 −0
Original line number Diff line number Diff line
@@ -641,6 +641,8 @@ struct rtw_chip_ops {
	void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
	void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
	void (*do_iqk)(struct rtw_dev *rtwdev);
	void (*dpk_track)(struct rtw_dev *rtwdev);
	void (*do_dpk)(struct rtw_dev *rtwdev);

	/* for coex */
	void (*coex_set_init)(struct rtw_dev *rtwdev);
@@ -864,6 +866,9 @@ struct rtw_chip_info {
	const struct rtw_rfe_def *rfe_defs;
	u32 rfe_defs_size;

	bool en_dis_dpd;
	u16 dpd_ratemask;

	/* coex paras */
	u32 coex_para_ver;
	u8 bt_desired_ver;
@@ -1075,6 +1080,37 @@ struct rtw_coex {
	struct delayed_work defreeze_work;
};

#define DPK_RF_REG_NUM 7
#define DPK_RF_PATH_NUM 2
#define DPK_BB_REG_NUM 18
#define DPK_CHANNEL_WIDTH_80 1

DECLARE_EWMA(thermal, 10, 4);

struct rtw_dpk_info {
	bool is_dpk_pwr_on;
	bool is_reload;

	DECLARE_BITMAP(dpk_path_ok, DPK_RF_PATH_NUM);

	u8 thermal_dpk[DPK_RF_PATH_NUM];
	struct ewma_thermal avg_thermal[DPK_RF_PATH_NUM];

	u32 gnt_control;
	u32 gnt_value;

	u8 result[RTW_RF_PATH_MAX];
	u8 dpk_txagc[RTW_RF_PATH_MAX];
	u32 coef[RTW_RF_PATH_MAX][20];
	u16 dpk_gs[RTW_RF_PATH_MAX];
	u8 thermal_dpk_delta[RTW_RF_PATH_MAX];
	u8 pre_pwsf[RTW_RF_PATH_MAX];

	u8 dpk_band;
	u8 dpk_ch;
	u8 dpk_bw;
};

#define DACK_MSBK_BACKUP_NUM	0xf
#define DACK_DCK_BACKUP_NUM	0x2

@@ -1108,6 +1144,8 @@ struct rtw_dm_info {
	u32 dack_adck[RTW_RF_PATH_MAX];
	u16 dack_msbk[RTW_RF_PATH_MAX][2][DACK_MSBK_BACKUP_NUM];
	u8 dack_dck[RTW_RF_PATH_MAX][2][DACK_DCK_BACKUP_NUM];

	struct rtw_dpk_info dpk_info;
};

struct rtw_efuse {
+52 −0
Original line number Diff line number Diff line
@@ -439,12 +439,21 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev)
	rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev);
}

static void rtw_phy_dpk_track(struct rtw_dev *rtwdev)
{
	struct rtw_chip_info *chip = rtwdev->chip;

	if (chip->ops->dpk_track)
		chip->ops->dpk_track(rtwdev);
}

void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev)
{
	/* for further calculation */
	rtw_phy_statistics(rtwdev);
	rtw_phy_dig(rtwdev);
	rtw_phy_ra_info_update(rtwdev);
	rtw_phy_dpk_track(rtwdev);
}

#define FRAC_BITS 3
@@ -1316,11 +1325,20 @@ void rtw_phy_cfg_rf(struct rtw_dev *rtwdev, const struct rtw_table *tbl,
static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
{
	struct rtw_chip_info *chip = rtwdev->chip;
	struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;

	if (!chip->rfk_init_tbl)
		return;

	rtw_write32_mask(rtwdev, 0x1e24, BIT(17), 0x1);
	rtw_write32_mask(rtwdev, 0x1cd0, BIT(28), 0x1);
	rtw_write32_mask(rtwdev, 0x1cd0, BIT(29), 0x1);
	rtw_write32_mask(rtwdev, 0x1cd0, BIT(30), 0x1);
	rtw_write32_mask(rtwdev, 0x1cd0, BIT(31), 0x0);

	rtw_load_table(rtwdev, chip->rfk_init_tbl);

	dpk_info->is_dpk_pwr_on = 1;
}

void rtw_phy_load_tables(struct rtw_dev *rtwdev)
@@ -1430,6 +1448,37 @@ static u8 rtw_get_channel_group(u8 channel)
	}
}

static s8 rtw_phy_get_dis_dpd_by_rate_diff(struct rtw_dev *rtwdev, u16 rate)
{
	struct rtw_chip_info *chip = rtwdev->chip;
	s8 dpd_diff = 0;

	if (!chip->en_dis_dpd)
		return 0;

#define RTW_DPD_RATE_CHECK(_rate)					\
	case DESC_RATE ## _rate:					\
	if (DIS_DPD_RATE ## _rate & chip->dpd_ratemask)			\
		dpd_diff = -6 * chip->txgi_factor;			\
	break

	switch (rate) {
	RTW_DPD_RATE_CHECK(6M);
	RTW_DPD_RATE_CHECK(9M);
	RTW_DPD_RATE_CHECK(MCS0);
	RTW_DPD_RATE_CHECK(MCS1);
	RTW_DPD_RATE_CHECK(MCS8);
	RTW_DPD_RATE_CHECK(MCS9);
	RTW_DPD_RATE_CHECK(VHT1SS_MCS0);
	RTW_DPD_RATE_CHECK(VHT1SS_MCS1);
	RTW_DPD_RATE_CHECK(VHT2SS_MCS0);
	RTW_DPD_RATE_CHECK(VHT2SS_MCS1);
	}
#undef RTW_DPD_RATE_CHECK

	return dpd_diff;
}

static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev,
					struct rtw_2g_txpwr_idx *pwr_idx_2g,
					enum rtw_bandwidth bandwidth,
@@ -1638,6 +1687,9 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate,
	tx_power = pwr_param.pwr_base;
	offset = min_t(s8, pwr_param.pwr_offset, pwr_param.pwr_limit);

	if (rtwdev->chip->en_dis_dpd)
		offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate);

	tx_power += offset;

	if (tx_power > rtwdev->chip->max_power_index)
+15 −0
Original line number Diff line number Diff line
@@ -341,6 +341,20 @@

#define REG_RFE_CTRL_E		0x0974

#define REG_DIS_DPD		0x0a70
#define DIS_DPD_MASK		GENMASK(9, 0)
#define DIS_DPD_RATE6M		BIT(0)
#define DIS_DPD_RATE9M		BIT(1)
#define DIS_DPD_RATEMCS0	BIT(2)
#define DIS_DPD_RATEMCS1	BIT(3)
#define DIS_DPD_RATEMCS8	BIT(4)
#define DIS_DPD_RATEMCS9	BIT(5)
#define DIS_DPD_RATEVHT1SS_MCS0	BIT(6)
#define DIS_DPD_RATEVHT1SS_MCS1	BIT(7)
#define DIS_DPD_RATEVHT2SS_MCS0	BIT(8)
#define DIS_DPD_RATEVHT2SS_MCS1	BIT(9)
#define DIS_DPD_RATEALL		GENMASK(9, 0)

#define REG_RFE_CTRL8		0x0cb4
#define BIT_MASK_RFE_SEL89	GENMASK(7, 0)
#define REG_RFE_INV8		0x0cbd
@@ -471,6 +485,7 @@
#define RF_LUTWA	0x33
#define RF_LUTWD1	0x3e
#define RF_LUTWD0	0x3f
#define RF_T_METER	0x42
#define RF_XTALX2	0xb8
#define RF_MALSEL	0xbe
#define RF_RCKD		0xde
Loading