Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61d36824 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: mt7615: add the capability to configure tx power



Introduce mt7615_mcu_set_tx_power routine in order to cap tx power
according to the value configured by the user

Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent c19b0ca5
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -110,6 +110,40 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
	}
}

int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan,
				  u8 chain_idx)
{
	int index;

	if (chain_idx > 3)
		return -EINVAL;

	if (chan->band == NL80211_BAND_2GHZ) {
		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
	} else {
		int group = mt7615_get_channel_group(chan->hw_value);

		switch (chain_idx) {
		case 1:
			index = MT_EE_TX1_5G_G0_TARGET_POWER;
			break;
		case 2:
			index = MT_EE_TX2_5G_G0_TARGET_POWER;
			break;
		case 3:
			index = MT_EE_TX3_5G_G0_TARGET_POWER;
			break;
		case 0:
		default:
			index = MT_EE_TX0_5G_G0_TARGET_POWER;
			break;
		}
		index += 5 * group;
	}

	return index;
}

int mt7615_eeprom_init(struct mt7615_dev *dev)
{
	int ret;
+35 −0
Original line number Diff line number Diff line
@@ -12,6 +12,11 @@ enum mt7615_eeprom_field {
	MT_EE_MAC_ADDR =			0x004,
	MT_EE_NIC_CONF_0 =			0x034,
	MT_EE_WIFI_CONF =			0x03e,
	MT_EE_TX0_2G_TARGET_POWER =		0x058,
	MT_EE_TX0_5G_G0_TARGET_POWER =		0x070,
	MT_EE_TX1_5G_G0_TARGET_POWER =		0x098,
	MT_EE_TX2_5G_G0_TARGET_POWER =		0x142,
	MT_EE_TX3_5G_G0_TARGET_POWER =		0x16a,

	__MT_EE_MAX =				0x3bf
};
@@ -24,4 +29,34 @@ enum mt7615_eeprom_band {
	MT_EE_DBDC,
};

enum mt7615_channel_group {
	MT_CH_5G_JAPAN,
	MT_CH_5G_UNII_1,
	MT_CH_5G_UNII_2A,
	MT_CH_5G_UNII_2B,
	MT_CH_5G_UNII_2E_1,
	MT_CH_5G_UNII_2E_2,
	MT_CH_5G_UNII_2E_3,
	MT_CH_5G_UNII_3,
	__MT_CH_MAX
};

static inline enum mt7615_channel_group
mt7615_get_channel_group(int channel)
{
	if (channel >= 184 && channel <= 196)
		return MT_CH_5G_JAPAN;
	if (channel <= 48)
		return MT_CH_5G_UNII_1;
	if (channel <= 64)
		return MT_CH_5G_UNII_2A;
	if (channel <= 114)
		return MT_CH_5G_UNII_2E_1;
	if (channel <= 144)
		return MT_CH_5G_UNII_2E_2;
	if (channel <= 161)
		return MT_CH_5G_UNII_2E_3;
	return MT_CH_5G_UNII_3;
}

#endif
+3 −0
Original line number Diff line number Diff line
@@ -201,6 +201,9 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
		mutex_unlock(&dev->mt76.mutex);
	}

	if (changed & IEEE80211_CONF_CHANGE_POWER)
		ret = mt7615_mcu_set_tx_power(dev);

	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
		mutex_lock(&dev->mt76.mutex);

+64 −0
Original line number Diff line number Diff line
@@ -1151,6 +1151,70 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
				   &req, sizeof(req), true);
}

int mt7615_mcu_set_tx_power(struct mt7615_dev *dev)
{
	int i, ret, n_chains = hweight8(dev->mt76.antenna_mask);
	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
	u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data;
	struct ieee80211_hw *hw = mt76_hw(dev);
	int freq = chandef->center_freq1, len;
	struct {
		u8 center_chan;
		u8 dbdc_idx;
		u8 band;
		u8 rsv;
	} __packed req_hdr = {
		.center_chan = ieee80211_frequency_to_channel(freq),
		.band = chandef->chan->band,
	};
	s8 tx_power;

	len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0;
	req = kzalloc(len, GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	memcpy(req, &req_hdr, sizeof(req_hdr));
	data = req + sizeof(req_hdr);
	memcpy(data, eep + MT_EE_NIC_CONF_0,
	       __MT_EE_MAX - MT_EE_NIC_CONF_0);

	tx_power = hw->conf.power_level * 2;
	switch (n_chains) {
	case 4:
		tx_power -= 12;
		break;
	case 3:
		tx_power -= 8;
		break;
	case 2:
		tx_power -= 6;
		break;
	default:
		break;
	}
	tx_power = max_t(s8, tx_power, 0);
	dev->mt76.txpower_cur = tx_power;

	for (i = 0; i < n_chains; i++) {
		int index = -MT_EE_NIC_CONF_0;

		ret = mt7615_eeprom_get_power_index(chandef->chan, i);
		if (ret < 0)
			goto out;

		index += ret;
		data[index] = min_t(u8, data[index], tx_power);
	}

	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL,
				  req, len, true);
out:
	kfree(req);

	return ret;
}

int mt7615_mcu_set_channel(struct mt7615_dev *dev)
{
	struct cfg80211_chan_def *chdef = &dev->mt76.chandef;
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ enum {
enum {
	MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
	MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
	MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
	MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
	MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
	MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
Loading