void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) { enum nl80211_chan_width width = dev->mt76.chandef.width; struct ieee80211_channel *chan = dev->mt76.chandef.chan; struct mt76x2_tx_power_info txp; int txp_0, txp_1, delta = 0; struct mt76_rate_power t = {}; int base_power, gain; mt76x2_get_power_info(dev, &txp, chan); if (width == NL80211_CHAN_WIDTH_40) delta = txp.delta_bw40; else if (width == NL80211_CHAN_WIDTH_80) delta = txp.delta_bw80; mt76x2_get_rate_power(dev, &t, chan); mt76x02_add_rate_power_offset(&t, txp.chain[0].target_power); mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t); base_power = mt76x2_get_min_rate_power(&t); delta += base_power - txp.chain[0].target_power; txp_0 = txp.chain[0].target_power + txp.chain[0].delta + delta; txp_1 = txp.chain[1].target_power + txp.chain[1].delta + delta; gain = min(txp_0, txp_1); if (gain < 0) { base_power -= gain; txp_0 -= gain; txp_1 -= gain; } else if (gain > 0x2f) { base_power -= gain - 0x2f; txp_0 = 0x2f; txp_1 = 0x2f; } mt76x02_add_rate_power_offset(&t, -base_power); dev->target_power = txp.chain[0].target_power; dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power; dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power; dev->mt76.rate_power = t; mt76x02_phy_set_txpower(dev, txp_0, txp_1); }
void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; struct mt76x2_tx_power_info txp; struct mt76x2_tssi_comp t = {}; if (!dev->cal.tssi_cal_done) return; if (!dev->cal.tssi_comp_pending) { /* TSSI trigger */ t.cal_mode = BIT(0); mt76x2_mcu_tssi_comp(dev, &t); dev->cal.tssi_comp_pending = true; } else { if (mt76_rr(dev, MT_BBP(CORE, 34)) & BIT(4)) return; dev->cal.tssi_comp_pending = false; mt76x2_get_power_info(dev, &txp, chan); if (mt76x02_ext_pa_enabled(dev, chan->band)) t.pa_mode = 1; t.cal_mode = BIT(1); t.slope0 = txp.chain[0].tssi_slope; t.offset0 = txp.chain[0].tssi_offset; t.slope1 = txp.chain[1].tssi_slope; t.offset1 = txp.chain[1].tssi_offset; mt76x2_mcu_tssi_comp(dev, &t); if (t.pa_mode || dev->cal.dpd_cal_done) return; usleep_range(10000, 20000); mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value); dev->cal.dpd_cal_done = true; } }
void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_supported_band *sband) { struct ieee80211_channel *chan; struct mt76x2_tx_power_info txp; struct mt76_rate_power t = {}; int i; for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; mt76x2_get_power_info(dev, &txp, chan); mt76x2_get_rate_power(dev, &t, chan); chan->max_power = mt76x02_get_max_rate_power(&t) + txp.target_power; chan->max_power = DIV_ROUND_UP(chan->max_power, 2); /* convert to combined output power on 2x2 devices */ chan->max_power += 3; chan->orig_mpwr = chan->max_power; } }