]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mt76: mt7615: add the capability to configure tx power
authorLorenzo Bianconi <lorenzo@kernel.org>
Sun, 26 May 2019 14:05:11 +0000 (16:05 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 27 Jun 2019 10:58:13 +0000 (12:58 +0200)
Introduce mt7615_mcu_set_tx_power routine in order to cap tx power
according to the value configured by the user

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h

index 714590878d658c0171bad80736e58e693a65e559..023c8bbc767dd67c94c7fda8516ca9232be0090d 100644 (file)
@@ -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;
index b422e395d6ee7ef737fa68224528c91b18c59da2..3c9086b67f515db04f5608c139fe147f4dfbebaf 100644 (file)
@@ -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
index b0bb7cc123854fbaeb1ad4ff4efef6dc4ff10cad..72bdb871ca138a361d38e1e2c4e222d74ff9596e 100644 (file)
@@ -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);
 
index 43f70195244c8352575bde9278832f197340959a..0e12e9f05f95c24f207a6081594969a8707bd5f4 100644 (file)
@@ -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;
index e96efb13fa4d01b6ac45f52ef3ae516fee6abe97..cca11737693c008c53aac664f634a7c66dc74c20 100644 (file)
@@ -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,
index 09c48dfbef3c4832685cc72dbc218752b0fa1d18..7c08d3b93a2a89ddf21ba5e958fd71c8d82faa69 100644 (file)
@@ -105,6 +105,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
 int mt7615_register_device(struct mt7615_dev *dev);
 void mt7615_unregister_device(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);
 void mt7615_dma_cleanup(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);
 int mt7615_mcu_init_mac(struct mt7615_dev *dev);
 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_set_tx_power(struct mt7615_dev *dev);
 void mt7615_mcu_exit(struct mt7615_dev *dev);
 
 int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,