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

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
...@@ -110,6 +110,40 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) ...@@ -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 mt7615_eeprom_init(struct mt7615_dev *dev)
{ {
int ret; int ret;
......
...@@ -12,6 +12,11 @@ enum mt7615_eeprom_field { ...@@ -12,6 +12,11 @@ enum mt7615_eeprom_field {
MT_EE_MAC_ADDR = 0x004, MT_EE_MAC_ADDR = 0x004,
MT_EE_NIC_CONF_0 = 0x034, MT_EE_NIC_CONF_0 = 0x034,
MT_EE_WIFI_CONF = 0x03e, 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 __MT_EE_MAX = 0x3bf
}; };
...@@ -24,4 +29,34 @@ enum mt7615_eeprom_band { ...@@ -24,4 +29,34 @@ enum mt7615_eeprom_band {
MT_EE_DBDC, 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 #endif
...@@ -201,6 +201,9 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) ...@@ -201,6 +201,9 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
} }
if (changed & IEEE80211_CONF_CHANGE_POWER)
ret = mt7615_mcu_set_tx_power(dev);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
mutex_lock(&dev->mt76.mutex); mutex_lock(&dev->mt76.mutex);
......
...@@ -1151,6 +1151,70 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, ...@@ -1151,6 +1151,70 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
&req, sizeof(req), true); &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) int mt7615_mcu_set_channel(struct mt7615_dev *dev)
{ {
struct cfg80211_chan_def *chdef = &dev->mt76.chandef; struct cfg80211_chan_def *chdef = &dev->mt76.chandef;
......
...@@ -70,6 +70,7 @@ enum { ...@@ -70,6 +70,7 @@ enum {
enum { enum {
MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
......
...@@ -105,6 +105,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); ...@@ -105,6 +105,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
int mt7615_register_device(struct mt7615_dev *dev); int mt7615_register_device(struct mt7615_dev *dev);
void mt7615_unregister_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev);
int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev);
int mt7615_eeprom_get_power_index(struct ieee80211_channel *chan,
u8 chain_idx);
int mt7615_dma_init(struct mt7615_dev *dev); int mt7615_dma_init(struct mt7615_dev *dev);
void mt7615_dma_cleanup(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev);
int mt7615_mcu_init(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev);
...@@ -167,6 +169,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); ...@@ -167,6 +169,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev);
int mt7615_mcu_init_mac(struct mt7615_dev *dev); int mt7615_mcu_init_mac(struct mt7615_dev *dev);
int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val);
int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter);
int mt7615_mcu_set_tx_power(struct mt7615_dev *dev);
void mt7615_mcu_exit(struct mt7615_dev *dev); void mt7615_mcu_exit(struct mt7615_dev *dev);
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
......
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