0001
0002
0003
0004
0005
0006
0007 #include "mt76x2.h"
0008 #include "eeprom.h"
0009 #include "mcu.h"
0010 #include "../mt76x02_phy.h"
0011
0012 static void
0013 mt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset)
0014 {
0015 s8 gain;
0016
0017 gain = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN,
0018 mt76_rr(dev, MT_BBP(AGC, reg)));
0019 gain -= offset / 2;
0020 mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_LNA_HIGH_GAIN, gain);
0021 }
0022
0023 static void
0024 mt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset)
0025 {
0026 s8 gain;
0027
0028 gain = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, reg)));
0029 gain += offset;
0030 mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain);
0031 }
0032
0033 void mt76x2_apply_gain_adj(struct mt76x02_dev *dev)
0034 {
0035 s8 *gain_adj = dev->cal.rx.high_gain;
0036
0037 mt76x2_adjust_high_lna_gain(dev, 4, gain_adj[0]);
0038 mt76x2_adjust_high_lna_gain(dev, 5, gain_adj[1]);
0039
0040 mt76x2_adjust_agc_gain(dev, 8, gain_adj[0]);
0041 mt76x2_adjust_agc_gain(dev, 9, gain_adj[1]);
0042 }
0043 EXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj);
0044
0045 void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev,
0046 enum nl80211_band band)
0047 {
0048 u32 pa_mode[2];
0049 u32 pa_mode_adj;
0050
0051 if (band == NL80211_BAND_2GHZ) {
0052 pa_mode[0] = 0x010055ff;
0053 pa_mode[1] = 0x00550055;
0054
0055 mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00);
0056 mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06);
0057
0058 if (mt76x02_ext_pa_enabled(dev, band)) {
0059 mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00);
0060 mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00);
0061 } else {
0062 mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0xf4000200);
0063 mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0xfa000200);
0064 }
0065 } else {
0066 pa_mode[0] = 0x0000ffff;
0067 pa_mode[1] = 0x00ff00ff;
0068
0069 if (mt76x02_ext_pa_enabled(dev, band)) {
0070 mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400);
0071 mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476);
0072 } else {
0073 mt76_wr(dev, MT_TX_ALC_CFG_2, 0x1b0f0400);
0074 mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476);
0075 }
0076
0077 if (mt76x02_ext_pa_enabled(dev, band))
0078 pa_mode_adj = 0x04000000;
0079 else
0080 pa_mode_adj = 0;
0081
0082 mt76_wr(dev, MT_RF_PA_MODE_ADJ0, pa_mode_adj);
0083 mt76_wr(dev, MT_RF_PA_MODE_ADJ1, pa_mode_adj);
0084 }
0085
0086 mt76_wr(dev, MT_BB_PA_MODE_CFG0, pa_mode[0]);
0087 mt76_wr(dev, MT_BB_PA_MODE_CFG1, pa_mode[1]);
0088 mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]);
0089 mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]);
0090
0091 if (mt76x02_ext_pa_enabled(dev, band)) {
0092 u32 val;
0093
0094 if (band == NL80211_BAND_2GHZ)
0095 val = 0x3c3c023c;
0096 else
0097 val = 0x363c023c;
0098
0099 mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val);
0100 mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val);
0101 mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00001818);
0102 } else {
0103 if (band == NL80211_BAND_2GHZ) {
0104 u32 val = 0x0f3c3c3c;
0105
0106 mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val);
0107 mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val);
0108 mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00000606);
0109 } else {
0110 mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x383c023c);
0111 mt76_wr(dev, MT_TX1_RF_GAIN_CORR, 0x24282e28);
0112 mt76_wr(dev, MT_TX_ALC_CFG_4, 0);
0113 }
0114 }
0115 }
0116 EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs);
0117
0118 static int
0119 mt76x2_get_min_rate_power(struct mt76_rate_power *r)
0120 {
0121 int i;
0122 s8 ret = 0;
0123
0124 for (i = 0; i < sizeof(r->all); i++) {
0125 if (!r->all[i])
0126 continue;
0127
0128 if (ret)
0129 ret = min(ret, r->all[i]);
0130 else
0131 ret = r->all[i];
0132 }
0133
0134 return ret;
0135 }
0136
0137 void mt76x2_phy_set_txpower(struct mt76x02_dev *dev)
0138 {
0139 enum nl80211_chan_width width = dev->mphy.chandef.width;
0140 struct ieee80211_channel *chan = dev->mphy.chandef.chan;
0141 struct mt76x2_tx_power_info txp;
0142 int txp_0, txp_1, delta = 0;
0143 struct mt76_rate_power t = {};
0144 int base_power, gain;
0145
0146 mt76x2_get_power_info(dev, &txp, chan);
0147
0148 if (width == NL80211_CHAN_WIDTH_40)
0149 delta = txp.delta_bw40;
0150 else if (width == NL80211_CHAN_WIDTH_80)
0151 delta = txp.delta_bw80;
0152
0153 mt76x2_get_rate_power(dev, &t, chan);
0154 mt76x02_add_rate_power_offset(&t, txp.target_power + delta);
0155 mt76x02_limit_rate_power(&t, dev->txpower_conf);
0156 dev->mphy.txpower_cur = mt76x02_get_max_rate_power(&t);
0157
0158 base_power = mt76x2_get_min_rate_power(&t);
0159 delta = base_power - txp.target_power;
0160 txp_0 = txp.chain[0].target_power + txp.chain[0].delta + delta;
0161 txp_1 = txp.chain[1].target_power + txp.chain[1].delta + delta;
0162
0163 gain = min(txp_0, txp_1);
0164 if (gain < 0) {
0165 base_power -= gain;
0166 txp_0 -= gain;
0167 txp_1 -= gain;
0168 } else if (gain > 0x2f) {
0169 base_power -= gain - 0x2f;
0170 txp_0 = 0x2f;
0171 txp_1 = 0x2f;
0172 }
0173
0174 mt76x02_add_rate_power_offset(&t, -base_power);
0175 dev->target_power = txp.target_power;
0176 dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power;
0177 dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power;
0178 dev->mt76.rate_power = t;
0179
0180 mt76x02_phy_set_txpower(dev, txp_0, txp_1);
0181 }
0182 EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower);
0183
0184 void mt76x2_configure_tx_delay(struct mt76x02_dev *dev,
0185 enum nl80211_band band, u8 bw)
0186 {
0187 u32 cfg0, cfg1;
0188
0189 if (mt76x02_ext_pa_enabled(dev, band)) {
0190 cfg0 = bw ? 0x000b0c01 : 0x00101101;
0191 cfg1 = 0x00011414;
0192 } else {
0193 cfg0 = bw ? 0x000b0b01 : 0x00101001;
0194 cfg1 = 0x00021414;
0195 }
0196 mt76_wr(dev, MT_TX_SW_CFG0, cfg0);
0197 mt76_wr(dev, MT_TX_SW_CFG1, cfg1);
0198
0199 mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_OFDM_SIFS, 15);
0200 }
0201 EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay);
0202
0203 void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev)
0204 {
0205 struct ieee80211_channel *chan = dev->mphy.chandef.chan;
0206 struct mt76x2_tx_power_info txp;
0207 struct mt76x2_tssi_comp t = {};
0208
0209 if (!dev->cal.tssi_cal_done)
0210 return;
0211
0212 if (!dev->cal.tssi_comp_pending) {
0213
0214 t.cal_mode = BIT(0);
0215 mt76x2_mcu_tssi_comp(dev, &t);
0216 dev->cal.tssi_comp_pending = true;
0217 } else {
0218 if (mt76_rr(dev, MT_BBP(CORE, 34)) & BIT(4))
0219 return;
0220
0221 dev->cal.tssi_comp_pending = false;
0222 mt76x2_get_power_info(dev, &txp, chan);
0223
0224 if (mt76x02_ext_pa_enabled(dev, chan->band))
0225 t.pa_mode = 1;
0226
0227 t.cal_mode = BIT(1);
0228 t.slope0 = txp.chain[0].tssi_slope;
0229 t.offset0 = txp.chain[0].tssi_offset;
0230 t.slope1 = txp.chain[1].tssi_slope;
0231 t.offset1 = txp.chain[1].tssi_offset;
0232 mt76x2_mcu_tssi_comp(dev, &t);
0233
0234 if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked)
0235 return;
0236
0237 usleep_range(10000, 20000);
0238 mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value);
0239 dev->cal.dpd_cal_done = true;
0240 }
0241 }
0242 EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate);
0243
0244 static void
0245 mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)
0246 {
0247 u32 val;
0248 u8 gain_val[2];
0249
0250 gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust;
0251 gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust;
0252
0253 val = 0x1836 << 16;
0254 if (!mt76x2_has_ext_lna(dev) &&
0255 dev->mphy.chandef.width >= NL80211_CHAN_WIDTH_40)
0256 val = 0x1e42 << 16;
0257
0258 if (mt76x2_has_ext_lna(dev) &&
0259 dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ &&
0260 dev->mphy.chandef.width < NL80211_CHAN_WIDTH_40)
0261 val = 0x0f36 << 16;
0262
0263 val |= 0xf8;
0264
0265 mt76_wr(dev, MT_BBP(AGC, 8),
0266 val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[0]));
0267 mt76_wr(dev, MT_BBP(AGC, 9),
0268 val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1]));
0269
0270 if (dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR)
0271 mt76x02_phy_dfs_adjust_agc(dev);
0272 }
0273
0274 void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
0275 {
0276 u8 *gain = dev->cal.agc_gain_init;
0277 u8 low_gain_delta, gain_delta;
0278 u32 agc_35, agc_37;
0279 bool gain_change;
0280 int low_gain;
0281 u32 val;
0282
0283 dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false);
0284 if (!dev->cal.avg_rssi_all)
0285 dev->cal.avg_rssi_all = -75;
0286
0287 low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
0288 (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
0289
0290 gain_change = dev->cal.low_gain < 0 ||
0291 (dev->cal.low_gain & 2) ^ (low_gain & 2);
0292 dev->cal.low_gain = low_gain;
0293
0294 if (!gain_change) {
0295 if (mt76x02_phy_adjust_vga_gain(dev))
0296 mt76x2_phy_set_gain_val(dev);
0297 return;
0298 }
0299
0300 if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) {
0301 mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211);
0302 val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf;
0303 if (low_gain == 2)
0304 val |= 0x3;
0305 else
0306 val |= 0x5;
0307 mt76_wr(dev, MT_BBP(AGC, 26), val);
0308 } else {
0309 mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423);
0310 }
0311
0312 if (mt76x2_has_ext_lna(dev))
0313 low_gain_delta = 10;
0314 else
0315 low_gain_delta = 14;
0316
0317 agc_37 = 0x2121262c;
0318 if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ)
0319 agc_35 = 0x11111516;
0320 else if (low_gain == 2)
0321 agc_35 = agc_37 = 0x08080808;
0322 else if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80)
0323 agc_35 = 0x10101014;
0324 else
0325 agc_35 = 0x11111116;
0326
0327 if (low_gain == 2) {
0328 mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990);
0329 mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808);
0330 mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808);
0331 gain_delta = low_gain_delta;
0332 dev->cal.agc_gain_adjust = 0;
0333 } else {
0334 mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991);
0335 gain_delta = 0;
0336 dev->cal.agc_gain_adjust = low_gain_delta;
0337 }
0338
0339 mt76_wr(dev, MT_BBP(AGC, 35), agc_35);
0340 mt76_wr(dev, MT_BBP(AGC, 37), agc_37);
0341
0342 dev->cal.agc_gain_cur[0] = gain[0] - gain_delta;
0343 dev->cal.agc_gain_cur[1] = gain[1] - gain_delta;
0344 mt76x2_phy_set_gain_val(dev);
0345
0346
0347 mt76_rr(dev, MT_RX_STAT_1);
0348 }
0349 EXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain);