linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] mt76x0: add tssi calibration support
@ 2018-10-29 21:31 Lorenzo Bianconi
  2018-10-29 21:31 ` [PATCH 1/3] mt76: move mt76x02_eeprom_copy in mt76x02-lib module Lorenzo Bianconi
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2018-10-29 21:31 UTC (permalink / raw)
  To: nbd; +Cc: sgruszka, linux-wireless

Introduce tssi calibration support in mt76x0 driver.
Configure tx power gain according to tssi calibrated value
if available

Lorenzo Bianconi (3):
  mt76: move mt76x02_eeprom_copy in mt76x02-lib module
  mt76x0: phy: introduce tssi calibration support
  mt76x0: phy: use tssi reported value to configure tx power if
    available

 .../wireless/mediatek/mt76/mt76x0/eeprom.c    |  20 +-
 .../net/wireless/mediatek/mt76/mt76x0/phy.c   | 357 +++++++++++++++++-
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |   3 +
 .../wireless/mediatek/mt76/mt76x02_eeprom.c   |  12 +
 .../wireless/mediatek/mt76/mt76x02_eeprom.h   |   5 +
 .../wireless/mediatek/mt76/mt76x2/eeprom.c    |  15 +-
 6 files changed, 391 insertions(+), 21 deletions(-)

-- 
2.19.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] mt76: move mt76x02_eeprom_copy in mt76x02-lib module
  2018-10-29 21:31 [PATCH 0/3] mt76x0: add tssi calibration support Lorenzo Bianconi
@ 2018-10-29 21:31 ` Lorenzo Bianconi
  2018-10-29 21:31 ` [PATCH 2/3] mt76x0: phy: introduce tssi calibration support Lorenzo Bianconi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2018-10-29 21:31 UTC (permalink / raw)
  To: nbd; +Cc: sgruszka, linux-wireless

Move mt76x02_eeprom_copy utility routine in mt76x02-lib module
in order to be reused by mt76x0 driver adding tssi calibration
support

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 .../net/wireless/mediatek/mt76/mt76x02_eeprom.c   | 12 ++++++++++++
 .../net/wireless/mediatek/mt76/mt76x02_eeprom.h   |  3 +++
 .../net/wireless/mediatek/mt76/mt76x2/eeprom.c    | 15 ++-------------
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
index 9390de2a323e..07f0496d828a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
@@ -53,6 +53,18 @@ mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data,
 	return 0;
 }
 
+int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
+			enum mt76x02_eeprom_field field,
+			void *dest, int len)
+{
+	if (field + len > dev->mt76.eeprom.size)
+		return -1;
+
+	memcpy(dest, dev->mt76.eeprom.data + field, len);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mt76x02_eeprom_copy);
+
 int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf,
 			   int len, enum mt76x02_eeprom_modes mode)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
index 1de041590050..5db01bda64b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
@@ -188,5 +188,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
 			s8 *lna_2g, s8 *lna_5g,
 			struct ieee80211_channel *chan);
 void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev);
+int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
+			enum mt76x02_eeprom_field field,
+			void *dest, int len);
 
 #endif /* __MT76x02_EEPROM_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
index f39b622d03f4..6f6998561d9d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
@@ -21,17 +21,6 @@
 
 #define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1
 
-static int
-mt76x2_eeprom_copy(struct mt76x02_dev *dev, enum mt76x02_eeprom_field field,
-		   void *dest, int len)
-{
-	if (field + len > dev->mt76.eeprom.size)
-		return -1;
-
-	memcpy(dest, dev->mt76.eeprom.data + field, len);
-	return 0;
-}
-
 static int
 mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev)
 {
@@ -378,7 +367,7 @@ mt76x2_get_power_info_2g(struct mt76x02_dev *dev,
 	else
 		delta_idx = 5;
 
-	mt76x2_eeprom_copy(dev, offset, data, sizeof(data));
+	mt76x02_eeprom_copy(dev, offset, data, sizeof(data));
 
 	t->chain[chain].tssi_slope = data[0];
 	t->chain[chain].tssi_offset = data[1];
@@ -429,7 +418,7 @@ mt76x2_get_power_info_5g(struct mt76x02_dev *dev,
 	else
 		delta_idx = 4;
 
-	mt76x2_eeprom_copy(dev, offset, data, sizeof(data));
+	mt76x02_eeprom_copy(dev, offset, data, sizeof(data));
 
 	t->chain[chain].tssi_slope = data[0];
 	t->chain[chain].tssi_offset = data[1];
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] mt76x0: phy: introduce tssi calibration support
  2018-10-29 21:31 [PATCH 0/3] mt76x0: add tssi calibration support Lorenzo Bianconi
  2018-10-29 21:31 ` [PATCH 1/3] mt76: move mt76x02_eeprom_copy in mt76x02-lib module Lorenzo Bianconi
@ 2018-10-29 21:31 ` Lorenzo Bianconi
  2018-11-02 13:09   ` Stanislaw Gruszka
  2018-10-29 21:31 ` [PATCH 3/3] mt76x0: phy: use tssi reported value to configure tx power if available Lorenzo Bianconi
  2018-11-05 17:00 ` [PATCH 0/3] mt76x0: add tssi calibration support Felix Fietkau
  3 siblings, 1 reply; 7+ messages in thread
From: Lorenzo Bianconi @ 2018-10-29 21:31 UTC (permalink / raw)
  To: nbd; +Cc: sgruszka, linux-wireless

Run mt76x0 tssi calibration process if enabled in eeprom data.
Perform calibration procedure every 4s

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 .../net/wireless/mediatek/mt76/mt76x0/phy.c   | 355 +++++++++++++++++-
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |   3 +
 .../wireless/mediatek/mt76/mt76x02_eeprom.h   |   2 +
 3 files changed, 357 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 830ea6047f10..f0d46e7bb76a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -503,6 +503,345 @@ mt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width)
 	mt76x02_mcu_function_select(dev, BW_SETTING, bw, false);
 }
 
+static void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev)
+{
+	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+	u32 val;
+
+	if (chan->band == NL80211_BAND_5GHZ)
+		mt76x0_rf_clear(dev, MT_RF(0, 67), 0xf);
+
+	/* bypass ADDA control */
+	mt76_wr(dev, MT_RF_SETTING_0, 0x60002237);
+	mt76_wr(dev, MT_RF_BYPASS_0, 0xffffffff);
+
+	/* bbp sw reset */
+	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
+	usleep_range(500, 1000);
+	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
+
+	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
+	mt76_wr(dev, MT_BBP(CORE, 34), val);
+
+	/* enable TX with DAC0 input */
+	mt76_wr(dev, MT_BBP(TXBE, 6), BIT(31));
+
+	mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200);
+	dev->cal.tssi_dc = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
+
+	/* stop bypass ADDA */
+	mt76_wr(dev, MT_RF_BYPASS_0, 0);
+	/* stop TX */
+	mt76_wr(dev, MT_BBP(TXBE, 6), 0);
+	/* bbp sw reset */
+	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
+	usleep_range(500, 1000);
+	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
+
+	if (chan->band == NL80211_BAND_5GHZ)
+		mt76x0_rf_rmw(dev, MT_RF(0, 67), 0xf, 0x4);
+}
+
+static int
+mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi,
+			      u8 *info)
+{
+	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+	u32 val;
+
+	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
+	mt76_wr(dev, MT_BBP(CORE, 34), val);
+
+	if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) {
+		mt76_clear(dev, MT_BBP(CORE, 34), BIT(4));
+		return -ETIMEDOUT;
+	}
+
+	*ltssi = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
+	if (chan->band == NL80211_BAND_5GHZ)
+		*ltssi += 128;
+
+	/* set packet info#1 mode */
+	mt76_wr(dev, MT_BBP(CORE, 34), 0x80041);
+	info[0] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
+
+	/* set packet info#2 mode */
+	mt76_wr(dev, MT_BBP(CORE, 34), 0x80042);
+	info[1] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
+
+	/* set packet info#3 mode */
+	mt76_wr(dev, MT_BBP(CORE, 34), 0x80043);
+	info[2] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
+
+	return 0;
+}
+
+static u8 mt76x0_phy_get_rf_pa_mode(struct mt76x02_dev *dev,
+				    int index, u8 tx_rate)
+{
+	u32 val, reg;
+
+	reg = (index == 1) ? MT_RF_PA_MODE_CFG1 : MT_RF_PA_MODE_CFG0;
+	val = mt76_rr(dev, reg);
+	return (val & (3 << (tx_rate * 2))) >> (tx_rate * 2);
+}
+
+static int
+mt76x0_phy_get_target_power(struct mt76x02_dev *dev, u8 tx_mode,
+			    u8 *info, s8 *target_power,
+			    s8 *target_pa_power)
+{
+	u8 tx_rate, cur_power;
+
+	cur_power = mt76_rr(dev, MT_TX_ALC_CFG_0) & MT_TX_ALC_CFG_0_CH_INIT_0;
+	switch (tx_mode) {
+	case 0:
+		/* cck rates */
+		tx_rate = (info[0] & 0x60) >> 5;
+		if (tx_rate > 3)
+			return -EINVAL;
+
+		*target_power = cur_power + dev->mt76.rate_power.cck[tx_rate];
+		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, tx_rate);
+		break;
+	case 1: {
+		u8 index;
+
+		/* ofdm rates */
+		tx_rate = (info[0] & 0xf0) >> 4;
+		switch (tx_rate) {
+		case 0xb:
+			index = 0;
+			break;
+		case 0xf:
+			index = 1;
+			break;
+		case 0xa:
+			index = 2;
+			break;
+		case 0xe:
+			index = 3;
+			break;
+		case 0x9:
+			index = 4;
+			break;
+		case 0xd:
+			index = 5;
+			break;
+		case 0x8:
+			index = 6;
+			break;
+		case 0xc:
+			index = 7;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		*target_power = cur_power + dev->mt76.rate_power.ofdm[index];
+		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, index + 4);
+		break;
+	}
+	case 4:
+		/* vht rates */
+		tx_rate = info[1] & 0xf;
+		if (tx_rate > 9)
+			return -EINVAL;
+
+		*target_power = cur_power + dev->mt76.rate_power.vht[tx_rate];
+		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
+		break;
+	default:
+		/* ht rates */
+		tx_rate = info[1] & 0x7f;
+		if (tx_rate > 9)
+			return -EINVAL;
+
+		*target_power = cur_power + dev->mt76.rate_power.ht[tx_rate];
+		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
+		break;
+	}
+
+	return 0;
+}
+
+static s16 mt76x0_phy_lin2db(u16 val)
+{
+	u32 mantissa = val << 4;
+	int ret, data;
+	s16 exp = -4;
+
+	while (mantissa < BIT(15)) {
+		mantissa <<= 1;
+		if (--exp < -20)
+			return -10000;
+	}
+	while (mantissa > 0xffff) {
+		mantissa >>= 1;
+		if (++exp > 20)
+			return -10000;
+	}
+
+	/* s(15,0) */
+	if (mantissa <= 47104)
+		data = mantissa + (mantissa >> 3) + (mantissa >> 4) - 38400;
+	else
+		data = mantissa - (mantissa >> 3) - (mantissa >> 6) - 23040;
+	data = max_t(int, 0, data);
+
+	ret = ((15 + exp) << 15) + data;
+	ret = (ret << 2) + (ret << 1) + (ret >> 6) + (ret >> 7);
+	return ret >> 10;
+}
+
+static int
+mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode,
+			   s8 target_power, s8 target_pa_power,
+			   s16 ltssi)
+{
+	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+	int tssi_target = target_power << 12, tssi_slope;
+	int tssi_offset, tssi_db, ret;
+	u32 data;
+	u16 val;
+
+	if (chan->band == NL80211_BAND_5GHZ) {
+		u8 bound[7];
+		int i, err;
+
+		err = mt76x02_eeprom_copy(dev, MT_EE_TSSI_BOUND1, bound,
+					  sizeof(bound));
+		if (err < 0)
+			return err;
+
+		for (i = 0; i < ARRAY_SIZE(bound); i++) {
+			if (chan->hw_value <= bound[i] || !bound[i])
+				break;
+		}
+		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_5G + i * 2);
+
+		tssi_offset = val >> 8;
+		if ((tssi_offset >= 64 && tssi_offset <= 127) ||
+		    (tssi_offset & BIT(7)))
+			tssi_offset -= BIT(8);
+	} else {
+		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_2G);
+
+		tssi_offset = val >> 8;
+		if (tssi_offset & BIT(7))
+			tssi_offset -= BIT(8);
+	}
+	tssi_slope = val & 0xff;
+
+	switch (target_pa_power) {
+	case 1:
+		if (chan->band == NL80211_BAND_2GHZ)
+			tssi_target += 29491; /* 3.6 * 8192 */
+		/* fall through */
+	case 0:
+		break;
+	default:
+		tssi_target += 4424; /* 0.54 * 8192 */
+		break;
+	}
+
+	if (!tx_mode) {
+		data = mt76_rr(dev, MT_BBP(CORE, 1));
+		if (is_mt7630(dev) && mt76_is_mmio(dev)) {
+			int offset;
+
+			/* 2.3 * 8192 or 1.5 * 8192 */
+			offset = (data & BIT(5)) ? 18841 : 12288;
+			tssi_target += offset;
+		} else if (data & BIT(5)) {
+			/* 0.8 * 8192 */
+			tssi_target += 6554;
+		}
+	}
+
+	data = mt76_rr(dev, MT_BBP(TXBE, 4));
+	switch (data & 0x3) {
+	case 1:
+		tssi_target -= 49152; /* -6db * 8192 */
+		break;
+	case 2:
+		tssi_target -= 98304; /* -12db * 8192 */
+		break;
+	case 3:
+		tssi_target += 49152; /* 6db * 8192 */
+		break;
+	default:
+		break;
+	}
+
+	tssi_db = mt76x0_phy_lin2db(ltssi - dev->cal.tssi_dc) * tssi_slope;
+	if (chan->band == NL80211_BAND_5GHZ) {
+		tssi_db += ((tssi_offset - 50) << 10); /* offset s4.3 */
+		tssi_target -= tssi_db;
+		if (ltssi > 254 && tssi_target > 0) {
+			/* upper saturate */
+			tssi_target = 0;
+		}
+	} else {
+		tssi_db += (tssi_offset << 9); /* offset s3.4 */
+		tssi_target -= tssi_db;
+		/* upper-lower saturate */
+		if ((ltssi > 126 && tssi_target > 0) ||
+		    ((ltssi - dev->cal.tssi_dc) < 1 && tssi_target < 0)) {
+			tssi_target = 0;
+		}
+	}
+
+	if ((dev->cal.tssi_target ^ tssi_target) < 0 &&
+	    dev->cal.tssi_target > -4096 && dev->cal.tssi_target < 4096 &&
+	    tssi_target > -4096 && tssi_target < 4096) {
+		if ((tssi_target < 0 &&
+		     tssi_target + dev->cal.tssi_target > 0) ||
+		    (tssi_target > 0 &&
+		     tssi_target + dev->cal.tssi_target <= 0))
+			tssi_target = 0;
+		else
+			dev->cal.tssi_target = tssi_target;
+	} else {
+		dev->cal.tssi_target = tssi_target;
+	}
+
+	/* make the compensate value to the nearest compensate code */
+	if (tssi_target > 0)
+		tssi_target += 2048;
+	else
+		tssi_target -= 2048;
+	tssi_target >>= 12;
+
+	ret = mt76_get_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP);
+	if (ret & BIT(5))
+		ret -= BIT(6);
+	ret += tssi_target;
+
+	ret = min_t(int, 31, ret);
+	return max_t(int, -32, ret);
+}
+
+static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
+{
+	s8 target_power, target_pa_power;
+	u8 tssi_info[3], tx_mode;
+	s16 ltssi;
+	s8 val;
+
+	if (mt76x0_phy_tssi_adc_calibrate(dev, &ltssi, tssi_info) < 0)
+		return;
+
+	tx_mode = tssi_info[0] & 0x7;
+	if (mt76x0_phy_get_target_power(dev, tx_mode, tssi_info,
+					&target_power, &target_pa_power) < 0)
+		return;
+
+	val = mt76x0_phy_get_delta_power(dev, tx_mode, target_power,
+					 target_pa_power, ltssi);
+	mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, val);
+}
+
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 {
 	struct mt76_rate_power *t = &dev->mt76.rate_power;
@@ -532,7 +871,15 @@ void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
 		mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value,
 				      false);
 		usleep_range(10, 20);
-		/* XXX: tssi */
+
+		if (mt76x0_tssi_enabled(dev)) {
+			mt76_wr(dev, MT_MAC_SYS_CTRL,
+				MT_MAC_SYS_CTRL_ENABLE_RX);
+			mt76x0_phy_tssi_dc_calibrate(dev);
+			mt76_wr(dev, MT_MAC_SYS_CTRL,
+				MT_MAC_SYS_CTRL_ENABLE_TX |
+				MT_MAC_SYS_CTRL_ENABLE_RX);
+		}
 	}
 
 	tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0);
@@ -761,11 +1108,13 @@ static void mt76x0_phy_calibration_work(struct work_struct *work)
 					       cal_work.work);
 
 	mt76x0_phy_update_channel_gain(dev);
-	if (!mt76x0_tssi_enabled(dev))
+	if (mt76x0_tssi_enabled(dev))
+		mt76x0_phy_tssi_calibrate(dev);
+	else
 		mt76x0_phy_temp_sensor(dev);
 
 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
-				     MT_CALIBRATE_INTERVAL);
+				     4 * MT_CALIBRATE_INTERVAL);
 }
 
 static void mt76x0_rf_patch_reg_array(struct mt76x02_dev *dev,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index d599b7dddac7..de1be1529f61 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -57,6 +57,9 @@ struct mt76x02_calibration {
 	bool tssi_comp_pending;
 	bool dpd_cal_done;
 	bool channel_cal_done;
+
+	int tssi_target;
+	s8 tssi_dc;
 };
 
 struct mt76x02_dev {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
index 5db01bda64b5..e3442bc4e0a4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
@@ -56,6 +56,7 @@ enum mt76x02_eeprom_field {
 #define MT_TX_POWER_GROUP_SIZE_5G		5
 #define MT_TX_POWER_GROUPS_5G			6
 	MT_EE_TX_POWER_0_START_5G =		0x062,
+	MT_EE_TSSI_SLOPE_2G =			0x06e,
 
 	MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA =	0x074,
 	MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE =	0x076,
@@ -86,6 +87,7 @@ enum mt76x02_eeprom_field {
 	MT_EE_TSSI_BOUND5 =			0x0dc,
 	MT_EE_TX_POWER_BYRATE_BASE =		0x0de,
 
+	MT_EE_TSSI_SLOPE_5G =			0x0f0,
 	MT_EE_RF_TEMP_COMP_SLOPE_5G =		0x0f2,
 	MT_EE_RF_TEMP_COMP_SLOPE_2G =		0x0f4,
 
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] mt76x0: phy: use tssi reported value to configure tx power if available
  2018-10-29 21:31 [PATCH 0/3] mt76x0: add tssi calibration support Lorenzo Bianconi
  2018-10-29 21:31 ` [PATCH 1/3] mt76: move mt76x02_eeprom_copy in mt76x02-lib module Lorenzo Bianconi
  2018-10-29 21:31 ` [PATCH 2/3] mt76x0: phy: introduce tssi calibration support Lorenzo Bianconi
@ 2018-10-29 21:31 ` Lorenzo Bianconi
  2018-11-05 17:00 ` [PATCH 0/3] mt76x0: add tssi calibration support Felix Fietkau
  3 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2018-10-29 21:31 UTC (permalink / raw)
  To: nbd; +Cc: sgruszka, linux-wireless

Use tssi calibrated value to configure tx power gain if tssi is enabled
in eeprom data

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 .../wireless/mediatek/mt76/mt76x0/eeprom.c    | 20 +++++++++++++++----
 .../net/wireless/mediatek/mt76/mt76x0/phy.c   |  2 +-
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 275d77c90624..497e762978cc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -135,9 +135,6 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
 	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
 	u8 val;
 
-	if (mt76x0_tssi_enabled(dev))
-		return 0;
-
 	if (chandef->width == NL80211_CHAN_WIDTH_80) {
 		val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER) >> 8;
 	} else if (chandef->width == NL80211_CHAN_WIDTH_40) {
@@ -160,8 +157,8 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
 	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
 	bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
 	struct mt76_rate_power *t = &dev->mt76.rate_power;
-	s8 delta = mt76x0_get_delta(dev);
 	u16 val, addr;
+	s8 delta;
 
 	memset(t, 0, sizeof(*t));
 
@@ -211,6 +208,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
 	t->vht[7] = s6_to_s8(val);
 	t->vht[8] = s6_to_s8(val >> 8);
 
+	delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev);
 	mt76x02_add_rate_power_offset(t, delta);
 }
 
@@ -233,6 +231,20 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
 	u16 data;
 	int i;
 
+	if (mt76x0_tssi_enabled(dev)) {
+		s8 target_power;
+
+		if (chan->band == NL80211_BAND_5GHZ)
+			data = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER);
+		else
+			data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
+		target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
+		info[0] = target_power + mt76x0_get_delta(dev);
+		info[1] = 0;
+
+		return;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
 		if (chan_map[i].chan <= chan->hw_value) {
 			offset = chan_map[i].offset;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index f0d46e7bb76a..a4d08655be61 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -847,8 +847,8 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 	struct mt76_rate_power *t = &dev->mt76.rate_power;
 	u8 info[2];
 
-	mt76x0_get_power_info(dev, info);
 	mt76x0_get_tx_power_per_rate(dev);
+	mt76x0_get_power_info(dev, info);
 
 	mt76x02_add_rate_power_offset(t, info[0]);
 	mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] mt76x0: phy: introduce tssi calibration support
  2018-10-29 21:31 ` [PATCH 2/3] mt76x0: phy: introduce tssi calibration support Lorenzo Bianconi
@ 2018-11-02 13:09   ` Stanislaw Gruszka
  2018-11-02 13:29     ` Lorenzo Bianconi
  0 siblings, 1 reply; 7+ messages in thread
From: Stanislaw Gruszka @ 2018-11-02 13:09 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: nbd, linux-wireless, Cheng-Hao.Luo, Ryder.Lee

(cc Mediatek.com engineers)

On Mon, Oct 29, 2018 at 10:31:24PM +0100, Lorenzo Bianconi wrote:
> Run mt76x0 tssi calibration process if enabled in eeprom data.
> Perform calibration procedure every 4s

I just checked the Mediatek vendor drivers for both MT7610E (at
github https://github.com/i80s/mtk-sources ) and GPL relesed MT7610U driver
are compiled without MT76x0_TSSI_CAL_COMPENSATION define.
So seems TSSI compensation is not used or tested in vendor driver.

Perhaps Cheng-Hao Luo and Ryder Lee at Mediatek could clarify if this
code is needed and is correct.

Thanks
Stanislaw


> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> ---
>  .../net/wireless/mediatek/mt76/mt76x0/phy.c   | 355 +++++++++++++++++-
>  drivers/net/wireless/mediatek/mt76/mt76x02.h  |   3 +
>  .../wireless/mediatek/mt76/mt76x02_eeprom.h   |   2 +
>  3 files changed, 357 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> index 830ea6047f10..f0d46e7bb76a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> @@ -503,6 +503,345 @@ mt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width)
>  	mt76x02_mcu_function_select(dev, BW_SETTING, bw, false);
>  }
>  
> +static void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev)
> +{
> +	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
> +	u32 val;
> +
> +	if (chan->band == NL80211_BAND_5GHZ)
> +		mt76x0_rf_clear(dev, MT_RF(0, 67), 0xf);
> +
> +	/* bypass ADDA control */
> +	mt76_wr(dev, MT_RF_SETTING_0, 0x60002237);
> +	mt76_wr(dev, MT_RF_BYPASS_0, 0xffffffff);
> +
> +	/* bbp sw reset */
> +	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
> +	usleep_range(500, 1000);
> +	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
> +
> +	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
> +	mt76_wr(dev, MT_BBP(CORE, 34), val);
> +
> +	/* enable TX with DAC0 input */
> +	mt76_wr(dev, MT_BBP(TXBE, 6), BIT(31));
> +
> +	mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200);
> +	dev->cal.tssi_dc = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
> +
> +	/* stop bypass ADDA */
> +	mt76_wr(dev, MT_RF_BYPASS_0, 0);
> +	/* stop TX */
> +	mt76_wr(dev, MT_BBP(TXBE, 6), 0);
> +	/* bbp sw reset */
> +	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
> +	usleep_range(500, 1000);
> +	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
> +
> +	if (chan->band == NL80211_BAND_5GHZ)
> +		mt76x0_rf_rmw(dev, MT_RF(0, 67), 0xf, 0x4);
> +}
> +
> +static int
> +mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi,
> +			      u8 *info)
> +{
> +	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
> +	u32 val;
> +
> +	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
> +	mt76_wr(dev, MT_BBP(CORE, 34), val);
> +
> +	if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) {
> +		mt76_clear(dev, MT_BBP(CORE, 34), BIT(4));
> +		return -ETIMEDOUT;
> +	}
> +
> +	*ltssi = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
> +	if (chan->band == NL80211_BAND_5GHZ)
> +		*ltssi += 128;
> +
> +	/* set packet info#1 mode */
> +	mt76_wr(dev, MT_BBP(CORE, 34), 0x80041);
> +	info[0] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
> +
> +	/* set packet info#2 mode */
> +	mt76_wr(dev, MT_BBP(CORE, 34), 0x80042);
> +	info[1] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
> +
> +	/* set packet info#3 mode */
> +	mt76_wr(dev, MT_BBP(CORE, 34), 0x80043);
> +	info[2] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
> +
> +	return 0;
> +}
> +
> +static u8 mt76x0_phy_get_rf_pa_mode(struct mt76x02_dev *dev,
> +				    int index, u8 tx_rate)
> +{
> +	u32 val, reg;
> +
> +	reg = (index == 1) ? MT_RF_PA_MODE_CFG1 : MT_RF_PA_MODE_CFG0;
> +	val = mt76_rr(dev, reg);
> +	return (val & (3 << (tx_rate * 2))) >> (tx_rate * 2);
> +}
> +
> +static int
> +mt76x0_phy_get_target_power(struct mt76x02_dev *dev, u8 tx_mode,
> +			    u8 *info, s8 *target_power,
> +			    s8 *target_pa_power)
> +{
> +	u8 tx_rate, cur_power;
> +
> +	cur_power = mt76_rr(dev, MT_TX_ALC_CFG_0) & MT_TX_ALC_CFG_0_CH_INIT_0;
> +	switch (tx_mode) {
> +	case 0:
> +		/* cck rates */
> +		tx_rate = (info[0] & 0x60) >> 5;
> +		if (tx_rate > 3)
> +			return -EINVAL;
> +
> +		*target_power = cur_power + dev->mt76.rate_power.cck[tx_rate];
> +		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, tx_rate);
> +		break;
> +	case 1: {
> +		u8 index;
> +
> +		/* ofdm rates */
> +		tx_rate = (info[0] & 0xf0) >> 4;
> +		switch (tx_rate) {
> +		case 0xb:
> +			index = 0;
> +			break;
> +		case 0xf:
> +			index = 1;
> +			break;
> +		case 0xa:
> +			index = 2;
> +			break;
> +		case 0xe:
> +			index = 3;
> +			break;
> +		case 0x9:
> +			index = 4;
> +			break;
> +		case 0xd:
> +			index = 5;
> +			break;
> +		case 0x8:
> +			index = 6;
> +			break;
> +		case 0xc:
> +			index = 7;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +
> +		*target_power = cur_power + dev->mt76.rate_power.ofdm[index];
> +		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, index + 4);
> +		break;
> +	}
> +	case 4:
> +		/* vht rates */
> +		tx_rate = info[1] & 0xf;
> +		if (tx_rate > 9)
> +			return -EINVAL;
> +
> +		*target_power = cur_power + dev->mt76.rate_power.vht[tx_rate];
> +		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
> +		break;
> +	default:
> +		/* ht rates */
> +		tx_rate = info[1] & 0x7f;
> +		if (tx_rate > 9)
> +			return -EINVAL;
> +
> +		*target_power = cur_power + dev->mt76.rate_power.ht[tx_rate];
> +		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static s16 mt76x0_phy_lin2db(u16 val)
> +{
> +	u32 mantissa = val << 4;
> +	int ret, data;
> +	s16 exp = -4;
> +
> +	while (mantissa < BIT(15)) {
> +		mantissa <<= 1;
> +		if (--exp < -20)
> +			return -10000;
> +	}
> +	while (mantissa > 0xffff) {
> +		mantissa >>= 1;
> +		if (++exp > 20)
> +			return -10000;
> +	}
> +
> +	/* s(15,0) */
> +	if (mantissa <= 47104)
> +		data = mantissa + (mantissa >> 3) + (mantissa >> 4) - 38400;
> +	else
> +		data = mantissa - (mantissa >> 3) - (mantissa >> 6) - 23040;
> +	data = max_t(int, 0, data);
> +
> +	ret = ((15 + exp) << 15) + data;
> +	ret = (ret << 2) + (ret << 1) + (ret >> 6) + (ret >> 7);
> +	return ret >> 10;
> +}
> +
> +static int
> +mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode,
> +			   s8 target_power, s8 target_pa_power,
> +			   s16 ltssi)
> +{
> +	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
> +	int tssi_target = target_power << 12, tssi_slope;
> +	int tssi_offset, tssi_db, ret;
> +	u32 data;
> +	u16 val;
> +
> +	if (chan->band == NL80211_BAND_5GHZ) {
> +		u8 bound[7];
> +		int i, err;
> +
> +		err = mt76x02_eeprom_copy(dev, MT_EE_TSSI_BOUND1, bound,
> +					  sizeof(bound));
> +		if (err < 0)
> +			return err;
> +
> +		for (i = 0; i < ARRAY_SIZE(bound); i++) {
> +			if (chan->hw_value <= bound[i] || !bound[i])
> +				break;
> +		}
> +		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_5G + i * 2);
> +
> +		tssi_offset = val >> 8;
> +		if ((tssi_offset >= 64 && tssi_offset <= 127) ||
> +		    (tssi_offset & BIT(7)))
> +			tssi_offset -= BIT(8);
> +	} else {
> +		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_2G);
> +
> +		tssi_offset = val >> 8;
> +		if (tssi_offset & BIT(7))
> +			tssi_offset -= BIT(8);
> +	}
> +	tssi_slope = val & 0xff;
> +
> +	switch (target_pa_power) {
> +	case 1:
> +		if (chan->band == NL80211_BAND_2GHZ)
> +			tssi_target += 29491; /* 3.6 * 8192 */
> +		/* fall through */
> +	case 0:
> +		break;
> +	default:
> +		tssi_target += 4424; /* 0.54 * 8192 */
> +		break;
> +	}
> +
> +	if (!tx_mode) {
> +		data = mt76_rr(dev, MT_BBP(CORE, 1));
> +		if (is_mt7630(dev) && mt76_is_mmio(dev)) {
> +			int offset;
> +
> +			/* 2.3 * 8192 or 1.5 * 8192 */
> +			offset = (data & BIT(5)) ? 18841 : 12288;
> +			tssi_target += offset;
> +		} else if (data & BIT(5)) {
> +			/* 0.8 * 8192 */
> +			tssi_target += 6554;
> +		}
> +	}
> +
> +	data = mt76_rr(dev, MT_BBP(TXBE, 4));
> +	switch (data & 0x3) {
> +	case 1:
> +		tssi_target -= 49152; /* -6db * 8192 */
> +		break;
> +	case 2:
> +		tssi_target -= 98304; /* -12db * 8192 */
> +		break;
> +	case 3:
> +		tssi_target += 49152; /* 6db * 8192 */
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	tssi_db = mt76x0_phy_lin2db(ltssi - dev->cal.tssi_dc) * tssi_slope;
> +	if (chan->band == NL80211_BAND_5GHZ) {
> +		tssi_db += ((tssi_offset - 50) << 10); /* offset s4.3 */
> +		tssi_target -= tssi_db;
> +		if (ltssi > 254 && tssi_target > 0) {
> +			/* upper saturate */
> +			tssi_target = 0;
> +		}
> +	} else {
> +		tssi_db += (tssi_offset << 9); /* offset s3.4 */
> +		tssi_target -= tssi_db;
> +		/* upper-lower saturate */
> +		if ((ltssi > 126 && tssi_target > 0) ||
> +		    ((ltssi - dev->cal.tssi_dc) < 1 && tssi_target < 0)) {
> +			tssi_target = 0;
> +		}
> +	}
> +
> +	if ((dev->cal.tssi_target ^ tssi_target) < 0 &&
> +	    dev->cal.tssi_target > -4096 && dev->cal.tssi_target < 4096 &&
> +	    tssi_target > -4096 && tssi_target < 4096) {
> +		if ((tssi_target < 0 &&
> +		     tssi_target + dev->cal.tssi_target > 0) ||
> +		    (tssi_target > 0 &&
> +		     tssi_target + dev->cal.tssi_target <= 0))
> +			tssi_target = 0;
> +		else
> +			dev->cal.tssi_target = tssi_target;
> +	} else {
> +		dev->cal.tssi_target = tssi_target;
> +	}
> +
> +	/* make the compensate value to the nearest compensate code */
> +	if (tssi_target > 0)
> +		tssi_target += 2048;
> +	else
> +		tssi_target -= 2048;
> +	tssi_target >>= 12;
> +
> +	ret = mt76_get_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP);
> +	if (ret & BIT(5))
> +		ret -= BIT(6);
> +	ret += tssi_target;
> +
> +	ret = min_t(int, 31, ret);
> +	return max_t(int, -32, ret);
> +}
> +
> +static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
> +{
> +	s8 target_power, target_pa_power;
> +	u8 tssi_info[3], tx_mode;
> +	s16 ltssi;
> +	s8 val;
> +
> +	if (mt76x0_phy_tssi_adc_calibrate(dev, &ltssi, tssi_info) < 0)
> +		return;
> +
> +	tx_mode = tssi_info[0] & 0x7;
> +	if (mt76x0_phy_get_target_power(dev, tx_mode, tssi_info,
> +					&target_power, &target_pa_power) < 0)
> +		return;
> +
> +	val = mt76x0_phy_get_delta_power(dev, tx_mode, target_power,
> +					 target_pa_power, ltssi);
> +	mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, val);
> +}
> +
>  void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
>  {
>  	struct mt76_rate_power *t = &dev->mt76.rate_power;
> @@ -532,7 +871,15 @@ void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
>  		mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value,
>  				      false);
>  		usleep_range(10, 20);
> -		/* XXX: tssi */
> +
> +		if (mt76x0_tssi_enabled(dev)) {
> +			mt76_wr(dev, MT_MAC_SYS_CTRL,
> +				MT_MAC_SYS_CTRL_ENABLE_RX);
> +			mt76x0_phy_tssi_dc_calibrate(dev);
> +			mt76_wr(dev, MT_MAC_SYS_CTRL,
> +				MT_MAC_SYS_CTRL_ENABLE_TX |
> +				MT_MAC_SYS_CTRL_ENABLE_RX);
> +		}
>  	}
>  
>  	tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0);
> @@ -761,11 +1108,13 @@ static void mt76x0_phy_calibration_work(struct work_struct *work)
>  					       cal_work.work);
>  
>  	mt76x0_phy_update_channel_gain(dev);
> -	if (!mt76x0_tssi_enabled(dev))
> +	if (mt76x0_tssi_enabled(dev))
> +		mt76x0_phy_tssi_calibrate(dev);
> +	else
>  		mt76x0_phy_temp_sensor(dev);
>  
>  	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
> -				     MT_CALIBRATE_INTERVAL);
> +				     4 * MT_CALIBRATE_INTERVAL);
>  }
>  
>  static void mt76x0_rf_patch_reg_array(struct mt76x02_dev *dev,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
> index d599b7dddac7..de1be1529f61 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
> @@ -57,6 +57,9 @@ struct mt76x02_calibration {
>  	bool tssi_comp_pending;
>  	bool dpd_cal_done;
>  	bool channel_cal_done;
> +
> +	int tssi_target;
> +	s8 tssi_dc;
>  };
>  
>  struct mt76x02_dev {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
> index 5db01bda64b5..e3442bc4e0a4 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
> @@ -56,6 +56,7 @@ enum mt76x02_eeprom_field {
>  #define MT_TX_POWER_GROUP_SIZE_5G		5
>  #define MT_TX_POWER_GROUPS_5G			6
>  	MT_EE_TX_POWER_0_START_5G =		0x062,
> +	MT_EE_TSSI_SLOPE_2G =			0x06e,
>  
>  	MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA =	0x074,
>  	MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE =	0x076,
> @@ -86,6 +87,7 @@ enum mt76x02_eeprom_field {
>  	MT_EE_TSSI_BOUND5 =			0x0dc,
>  	MT_EE_TX_POWER_BYRATE_BASE =		0x0de,
>  
> +	MT_EE_TSSI_SLOPE_5G =			0x0f0,
>  	MT_EE_RF_TEMP_COMP_SLOPE_5G =		0x0f2,
>  	MT_EE_RF_TEMP_COMP_SLOPE_2G =		0x0f4,
>  
> -- 
> 2.19.1
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] mt76x0: phy: introduce tssi calibration support
  2018-11-02 13:09   ` Stanislaw Gruszka
@ 2018-11-02 13:29     ` Lorenzo Bianconi
  0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2018-11-02 13:29 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: nbd, linux-wireless, Cheng-Hao.Luo, Ryder.Lee

> (cc Mediatek.com engineers)
> 
> On Mon, Oct 29, 2018 at 10:31:24PM +0100, Lorenzo Bianconi wrote:
> > Run mt76x0 tssi calibration process if enabled in eeprom data.
> > Perform calibration procedure every 4s
> 
> I just checked the Mediatek vendor drivers for both MT7610E (at
> github https://github.com/i80s/mtk-sources ) and GPL relesed MT7610U driver
> are compiled without MT76x0_TSSI_CAL_COMPENSATION define.
> So seems TSSI compensation is not used or tested in vendor driver.

During the tests I carried out, TSSI calibration is disabled on my mt7610e
device (it runs temperature calibration) but it is enabled on my mt7610u
dongle and it seems to work properly.
Anyway more light on this topic from mtk folks is definitely very useful.

Regards,
Lorenzo

> 
> Perhaps Cheng-Hao Luo and Ryder Lee at Mediatek could clarify if this
> code is needed and is correct.
> 
> Thanks
> Stanislaw
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] mt76x0: add tssi calibration support
  2018-10-29 21:31 [PATCH 0/3] mt76x0: add tssi calibration support Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2018-10-29 21:31 ` [PATCH 3/3] mt76x0: phy: use tssi reported value to configure tx power if available Lorenzo Bianconi
@ 2018-11-05 17:00 ` Felix Fietkau
  3 siblings, 0 replies; 7+ messages in thread
From: Felix Fietkau @ 2018-11-05 17:00 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: sgruszka, linux-wireless

On 2018-10-29 22:31, Lorenzo Bianconi wrote:
> Introduce tssi calibration support in mt76x0 driver.
> Configure tx power gain according to tssi calibrated value
> if available
Applied, thanks.

- Felix

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-11-05 17:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-29 21:31 [PATCH 0/3] mt76x0: add tssi calibration support Lorenzo Bianconi
2018-10-29 21:31 ` [PATCH 1/3] mt76: move mt76x02_eeprom_copy in mt76x02-lib module Lorenzo Bianconi
2018-10-29 21:31 ` [PATCH 2/3] mt76x0: phy: introduce tssi calibration support Lorenzo Bianconi
2018-11-02 13:09   ` Stanislaw Gruszka
2018-11-02 13:29     ` Lorenzo Bianconi
2018-10-29 21:31 ` [PATCH 3/3] mt76x0: phy: use tssi reported value to configure tx power if available Lorenzo Bianconi
2018-11-05 17:00 ` [PATCH 0/3] mt76x0: add tssi calibration support Felix Fietkau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).