Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
0004  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
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         /* TSSI trigger */
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     /* clear false CCA counters */
0347     mt76_rr(dev, MT_RX_STAT_1);
0348 }
0349 EXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain);