1 // SPDX-License-Identifier: ISC
3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
10 #include "../mt76x02_phy.h"
13 mt76x2_adjust_high_lna_gain(struct mt76x02_dev
*dev
, int reg
, s8 offset
)
17 gain
= FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN
,
18 mt76_rr(dev
, MT_BBP(AGC
, reg
)));
20 mt76_rmw_field(dev
, MT_BBP(AGC
, reg
), MT_BBP_AGC_LNA_HIGH_GAIN
, gain
);
24 mt76x2_adjust_agc_gain(struct mt76x02_dev
*dev
, int reg
, s8 offset
)
28 gain
= FIELD_GET(MT_BBP_AGC_GAIN
, mt76_rr(dev
, MT_BBP(AGC
, reg
)));
30 mt76_rmw_field(dev
, MT_BBP(AGC
, reg
), MT_BBP_AGC_GAIN
, gain
);
33 void mt76x2_apply_gain_adj(struct mt76x02_dev
*dev
)
35 s8
*gain_adj
= dev
->cal
.rx
.high_gain
;
37 mt76x2_adjust_high_lna_gain(dev
, 4, gain_adj
[0]);
38 mt76x2_adjust_high_lna_gain(dev
, 5, gain_adj
[1]);
40 mt76x2_adjust_agc_gain(dev
, 8, gain_adj
[0]);
41 mt76x2_adjust_agc_gain(dev
, 9, gain_adj
[1]);
43 EXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj
);
45 void mt76x2_phy_set_txpower_regs(struct mt76x02_dev
*dev
,
46 enum nl80211_band band
)
51 if (band
== NL80211_BAND_2GHZ
) {
52 pa_mode
[0] = 0x010055ff;
53 pa_mode
[1] = 0x00550055;
55 mt76_wr(dev
, MT_TX_ALC_CFG_2
, 0x35160a00);
56 mt76_wr(dev
, MT_TX_ALC_CFG_3
, 0x35160a06);
58 if (mt76x02_ext_pa_enabled(dev
, band
)) {
59 mt76_wr(dev
, MT_RF_PA_MODE_ADJ0
, 0x0000ec00);
60 mt76_wr(dev
, MT_RF_PA_MODE_ADJ1
, 0x0000ec00);
62 mt76_wr(dev
, MT_RF_PA_MODE_ADJ0
, 0xf4000200);
63 mt76_wr(dev
, MT_RF_PA_MODE_ADJ1
, 0xfa000200);
66 pa_mode
[0] = 0x0000ffff;
67 pa_mode
[1] = 0x00ff00ff;
69 if (mt76x02_ext_pa_enabled(dev
, band
)) {
70 mt76_wr(dev
, MT_TX_ALC_CFG_2
, 0x2f0f0400);
71 mt76_wr(dev
, MT_TX_ALC_CFG_3
, 0x2f0f0476);
73 mt76_wr(dev
, MT_TX_ALC_CFG_2
, 0x1b0f0400);
74 mt76_wr(dev
, MT_TX_ALC_CFG_3
, 0x1b0f0476);
77 if (mt76x02_ext_pa_enabled(dev
, band
))
78 pa_mode_adj
= 0x04000000;
82 mt76_wr(dev
, MT_RF_PA_MODE_ADJ0
, pa_mode_adj
);
83 mt76_wr(dev
, MT_RF_PA_MODE_ADJ1
, pa_mode_adj
);
86 mt76_wr(dev
, MT_BB_PA_MODE_CFG0
, pa_mode
[0]);
87 mt76_wr(dev
, MT_BB_PA_MODE_CFG1
, pa_mode
[1]);
88 mt76_wr(dev
, MT_RF_PA_MODE_CFG0
, pa_mode
[0]);
89 mt76_wr(dev
, MT_RF_PA_MODE_CFG1
, pa_mode
[1]);
91 if (mt76x02_ext_pa_enabled(dev
, band
)) {
94 if (band
== NL80211_BAND_2GHZ
)
99 mt76_wr(dev
, MT_TX0_RF_GAIN_CORR
, val
);
100 mt76_wr(dev
, MT_TX1_RF_GAIN_CORR
, val
);
101 mt76_wr(dev
, MT_TX_ALC_CFG_4
, 0x00001818);
103 if (band
== NL80211_BAND_2GHZ
) {
104 u32 val
= 0x0f3c3c3c;
106 mt76_wr(dev
, MT_TX0_RF_GAIN_CORR
, val
);
107 mt76_wr(dev
, MT_TX1_RF_GAIN_CORR
, val
);
108 mt76_wr(dev
, MT_TX_ALC_CFG_4
, 0x00000606);
110 mt76_wr(dev
, MT_TX0_RF_GAIN_CORR
, 0x383c023c);
111 mt76_wr(dev
, MT_TX1_RF_GAIN_CORR
, 0x24282e28);
112 mt76_wr(dev
, MT_TX_ALC_CFG_4
, 0);
116 EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs
);
119 mt76x2_get_min_rate_power(struct mt76_rate_power
*r
)
124 for (i
= 0; i
< sizeof(r
->all
); i
++) {
129 ret
= min(ret
, r
->all
[i
]);
137 void mt76x2_phy_set_txpower(struct mt76x02_dev
*dev
)
139 enum nl80211_chan_width width
= dev
->mt76
.chandef
.width
;
140 struct ieee80211_channel
*chan
= dev
->mt76
.chandef
.chan
;
141 struct mt76x2_tx_power_info txp
;
142 int txp_0
, txp_1
, delta
= 0;
143 struct mt76_rate_power t
= {};
144 int base_power
, gain
;
146 mt76x2_get_power_info(dev
, &txp
, chan
);
148 if (width
== NL80211_CHAN_WIDTH_40
)
149 delta
= txp
.delta_bw40
;
150 else if (width
== NL80211_CHAN_WIDTH_80
)
151 delta
= txp
.delta_bw80
;
153 mt76x2_get_rate_power(dev
, &t
, chan
);
154 mt76x02_add_rate_power_offset(&t
, txp
.target_power
+ delta
);
155 mt76x02_limit_rate_power(&t
, dev
->mt76
.txpower_conf
);
156 dev
->mt76
.txpower_cur
= mt76x02_get_max_rate_power(&t
);
158 base_power
= mt76x2_get_min_rate_power(&t
);
159 delta
= base_power
- txp
.target_power
;
160 txp_0
= txp
.chain
[0].target_power
+ txp
.chain
[0].delta
+ delta
;
161 txp_1
= txp
.chain
[1].target_power
+ txp
.chain
[1].delta
+ delta
;
163 gain
= min(txp_0
, txp_1
);
168 } else if (gain
> 0x2f) {
169 base_power
-= gain
- 0x2f;
174 mt76x02_add_rate_power_offset(&t
, -base_power
);
175 dev
->target_power
= txp
.target_power
;
176 dev
->target_power_delta
[0] = txp_0
- txp
.chain
[0].target_power
;
177 dev
->target_power_delta
[1] = txp_1
- txp
.chain
[0].target_power
;
178 dev
->mt76
.rate_power
= t
;
180 mt76x02_phy_set_txpower(dev
, txp_0
, txp_1
);
182 EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower
);
184 void mt76x2_configure_tx_delay(struct mt76x02_dev
*dev
,
185 enum nl80211_band band
, u8 bw
)
189 if (mt76x02_ext_pa_enabled(dev
, band
)) {
190 cfg0
= bw
? 0x000b0c01 : 0x00101101;
193 cfg0
= bw
? 0x000b0b01 : 0x00101001;
196 mt76_wr(dev
, MT_TX_SW_CFG0
, cfg0
);
197 mt76_wr(dev
, MT_TX_SW_CFG1
, cfg1
);
199 mt76_rmw_field(dev
, MT_XIFS_TIME_CFG
, MT_XIFS_TIME_CFG_OFDM_SIFS
, 15);
201 EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay
);
203 void mt76x2_phy_tssi_compensate(struct mt76x02_dev
*dev
)
205 struct ieee80211_channel
*chan
= dev
->mt76
.chandef
.chan
;
206 struct mt76x2_tx_power_info txp
;
207 struct mt76x2_tssi_comp t
= {};
209 if (!dev
->cal
.tssi_cal_done
)
212 if (!dev
->cal
.tssi_comp_pending
) {
215 mt76x2_mcu_tssi_comp(dev
, &t
);
216 dev
->cal
.tssi_comp_pending
= true;
218 if (mt76_rr(dev
, MT_BBP(CORE
, 34)) & BIT(4))
221 dev
->cal
.tssi_comp_pending
= false;
222 mt76x2_get_power_info(dev
, &txp
, chan
);
224 if (mt76x02_ext_pa_enabled(dev
, chan
->band
))
228 t
.slope0
= txp
.chain
[0].tssi_slope
;
229 t
.offset0
= txp
.chain
[0].tssi_offset
;
230 t
.slope1
= txp
.chain
[1].tssi_slope
;
231 t
.offset1
= txp
.chain
[1].tssi_offset
;
232 mt76x2_mcu_tssi_comp(dev
, &t
);
234 if (t
.pa_mode
|| dev
->cal
.dpd_cal_done
|| dev
->ed_tx_blocked
)
237 usleep_range(10000, 20000);
238 mt76x02_mcu_calibrate(dev
, MCU_CAL_DPD
, chan
->hw_value
);
239 dev
->cal
.dpd_cal_done
= true;
242 EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate
);
245 mt76x2_phy_set_gain_val(struct mt76x02_dev
*dev
)
250 gain_val
[0] = dev
->cal
.agc_gain_cur
[0] - dev
->cal
.agc_gain_adjust
;
251 gain_val
[1] = dev
->cal
.agc_gain_cur
[1] - dev
->cal
.agc_gain_adjust
;
254 if (!mt76x2_has_ext_lna(dev
) &&
255 dev
->mt76
.chandef
.width
>= NL80211_CHAN_WIDTH_40
)
258 if (mt76x2_has_ext_lna(dev
) &&
259 dev
->mt76
.chandef
.chan
->band
== NL80211_BAND_2GHZ
&&
260 dev
->mt76
.chandef
.width
< NL80211_CHAN_WIDTH_40
)
265 mt76_wr(dev
, MT_BBP(AGC
, 8),
266 val
| FIELD_PREP(MT_BBP_AGC_GAIN
, gain_val
[0]));
267 mt76_wr(dev
, MT_BBP(AGC
, 9),
268 val
| FIELD_PREP(MT_BBP_AGC_GAIN
, gain_val
[1]));
270 if (dev
->mt76
.chandef
.chan
->flags
& IEEE80211_CHAN_RADAR
)
271 mt76x02_phy_dfs_adjust_agc(dev
);
274 void mt76x2_phy_update_channel_gain(struct mt76x02_dev
*dev
)
276 u8
*gain
= dev
->cal
.agc_gain_init
;
277 u8 low_gain_delta
, gain_delta
;
283 dev
->cal
.avg_rssi_all
= mt76_get_min_avg_rssi(&dev
->mt76
);
284 if (!dev
->cal
.avg_rssi_all
)
285 dev
->cal
.avg_rssi_all
= -75;
287 low_gain
= (dev
->cal
.avg_rssi_all
> mt76x02_get_rssi_gain_thresh(dev
)) +
288 (dev
->cal
.avg_rssi_all
> mt76x02_get_low_rssi_gain_thresh(dev
));
290 gain_change
= dev
->cal
.low_gain
< 0 ||
291 (dev
->cal
.low_gain
& 2) ^ (low_gain
& 2);
292 dev
->cal
.low_gain
= low_gain
;
295 if (mt76x02_phy_adjust_vga_gain(dev
))
296 mt76x2_phy_set_gain_val(dev
);
300 if (dev
->mt76
.chandef
.width
== NL80211_CHAN_WIDTH_80
) {
301 mt76_wr(dev
, MT_BBP(RXO
, 14), 0x00560211);
302 val
= mt76_rr(dev
, MT_BBP(AGC
, 26)) & ~0xf;
307 mt76_wr(dev
, MT_BBP(AGC
, 26), val
);
309 mt76_wr(dev
, MT_BBP(RXO
, 14), 0x00560423);
312 if (mt76x2_has_ext_lna(dev
))
318 if (dev
->mt76
.chandef
.chan
->band
== NL80211_BAND_2GHZ
)
320 else if (low_gain
== 2)
321 agc_35
= agc_37
= 0x08080808;
322 else if (dev
->mt76
.chandef
.width
== NL80211_CHAN_WIDTH_80
)
328 mt76_wr(dev
, MT_BBP(RXO
, 18), 0xf000a990);
329 mt76_wr(dev
, MT_BBP(AGC
, 35), 0x08080808);
330 mt76_wr(dev
, MT_BBP(AGC
, 37), 0x08080808);
331 gain_delta
= low_gain_delta
;
332 dev
->cal
.agc_gain_adjust
= 0;
334 mt76_wr(dev
, MT_BBP(RXO
, 18), 0xf000a991);
336 dev
->cal
.agc_gain_adjust
= low_gain_delta
;
339 mt76_wr(dev
, MT_BBP(AGC
, 35), agc_35
);
340 mt76_wr(dev
, MT_BBP(AGC
, 37), agc_37
);
342 dev
->cal
.agc_gain_cur
[0] = gain
[0] - gain_delta
;
343 dev
->cal
.agc_gain_cur
[1] = gain
[1] - gain_delta
;
344 mt76x2_phy_set_gain_val(dev
);
346 /* clear false CCA counters */
347 mt76_rr(dev
, MT_RX_STAT_1
);
349 EXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain
);