diff options
author | Ryder Lee <ryder.lee@mediatek.com> | 2020-04-25 03:32:29 +0800 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2020-05-12 19:52:35 +0200 |
commit | f1d962369d5687b08d3270dad421e9346caee0ca (patch) | |
tree | 6305f3e22c8dcb8ae527c167a8ae743a3b2700bd /drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | |
parent | 5205071a519c5dd7b479343e17a109fb3cb19629 (diff) |
mt76: mt7915: implement HE per-rate tx power support
Use firmware support for applying per-rate limit and power offsets.
This can support all HE RU types.
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Chih-Min Chen <chih-min.chen@mediatek.com>
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
Acked-by: Yiwei Chung <yiwei.chung@mediatek.com>
Acked-by: YF Luo <yf.luo@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 2099dd40530f..7deba7ebd68a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -123,3 +123,121 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, return mt7915_eeprom_read(dev, index); } + +static const u8 sku_cck_delta_map[] = { + SKU_CCK_GROUP0, + SKU_CCK_GROUP0, + SKU_CCK_GROUP1, + SKU_CCK_GROUP1, +}; + +static const u8 sku_ofdm_delta_map[] = { + SKU_OFDM_GROUP0, + SKU_OFDM_GROUP0, + SKU_OFDM_GROUP1, + SKU_OFDM_GROUP1, + SKU_OFDM_GROUP2, + SKU_OFDM_GROUP2, + SKU_OFDM_GROUP3, + SKU_OFDM_GROUP4, +}; + +static const u8 sku_mcs_delta_map[] = { + SKU_MCS_GROUP0, + SKU_MCS_GROUP1, + SKU_MCS_GROUP1, + SKU_MCS_GROUP2, + SKU_MCS_GROUP2, + SKU_MCS_GROUP3, + SKU_MCS_GROUP4, + SKU_MCS_GROUP5, + SKU_MCS_GROUP6, + SKU_MCS_GROUP7, + SKU_MCS_GROUP8, + SKU_MCS_GROUP9, +}; + +#define SKU_GROUP(_mode, _len, _ofs_2g, _ofs_5g, _map) \ + [_mode] = { \ + .len = _len, \ + .offset = { \ + _ofs_2g, \ + _ofs_5g, \ + }, \ + .delta_map = _map \ +} + +const struct sku_group mt7915_sku_groups[] = { + SKU_GROUP(SKU_CCK, 4, 0x252, 0, sku_cck_delta_map), + SKU_GROUP(SKU_OFDM, 8, 0x254, 0x29d, sku_ofdm_delta_map), + + SKU_GROUP(SKU_HT_BW20, 8, 0x259, 0x2a2, sku_mcs_delta_map), + SKU_GROUP(SKU_HT_BW40, 9, 0x262, 0x2ab, sku_mcs_delta_map), + SKU_GROUP(SKU_VHT_BW20, 12, 0x259, 0x2a2, sku_mcs_delta_map), + SKU_GROUP(SKU_VHT_BW40, 12, 0x262, 0x2ab, sku_mcs_delta_map), + SKU_GROUP(SKU_VHT_BW80, 12, 0, 0x2b4, sku_mcs_delta_map), + SKU_GROUP(SKU_VHT_BW160, 12, 0, 0, sku_mcs_delta_map), + + SKU_GROUP(SKU_HE_RU26, 12, 0x27f, 0x2dd, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU52, 12, 0x289, 0x2e7, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU106, 12, 0x293, 0x2f1, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU242, 12, 0x26b, 0x2bf, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU484, 12, 0x275, 0x2c9, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU996, 12, 0, 0x2d3, sku_mcs_delta_map), + SKU_GROUP(SKU_HE_RU2x996, 12, 0, 0, sku_mcs_delta_map), +}; + +static s8 +mt7915_get_sku_delta(struct mt7915_dev *dev, u32 addr) +{ + u32 val = mt7915_eeprom_read(dev, addr); + s8 delta = FIELD_GET(SKU_DELTA_VAL, val); + + if (!(val & SKU_DELTA_EN)) + return 0; + + return val & SKU_DELTA_ADD ? delta : -delta; +} + +static void +mt7915_eeprom_init_sku_band(struct mt7915_dev *dev, + struct ieee80211_supported_band *sband) +{ + int i, band = sband->band; + s8 *rate_power = dev->rate_power[band], max_delta = 0; + u8 idx = 0; + + for (i = 0; i < ARRAY_SIZE(mt7915_sku_groups); i++) { + const struct sku_group *sku = &mt7915_sku_groups[i]; + u32 offset = sku->offset[band]; + int j; + + if (!offset) { + idx += sku->len; + continue; + } + + rate_power[idx++] = mt7915_get_sku_delta(dev, offset); + if (rate_power[idx - 1] > max_delta) + max_delta = rate_power[idx - 1]; + + if (i == SKU_HT_BW20 || i == SKU_VHT_BW20) + offset += 1; + + for (j = 1; j < sku->len; j++) { + u32 addr = offset + sku->delta_map[j]; + + rate_power[idx++] = mt7915_get_sku_delta(dev, addr); + if (rate_power[idx - 1] > max_delta) + max_delta = rate_power[idx - 1]; + } + } + + rate_power[idx] = max_delta; +} + +void mt7915_eeprom_init_sku(struct mt7915_dev *dev) +{ + mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_2g.sband); + mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_5g.sband); +} |