18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 48c2ecf20Sopenharmony_ci * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "mt76x2.h" 88c2ecf20Sopenharmony_ci#include "eeprom.h" 98c2ecf20Sopenharmony_ci#include "mcu.h" 108c2ecf20Sopenharmony_ci#include "../mt76x02_phy.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic void 138c2ecf20Sopenharmony_cimt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci s8 gain; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci gain = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, 188c2ecf20Sopenharmony_ci mt76_rr(dev, MT_BBP(AGC, reg))); 198c2ecf20Sopenharmony_ci gain -= offset / 2; 208c2ecf20Sopenharmony_ci mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_LNA_HIGH_GAIN, gain); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic void 248c2ecf20Sopenharmony_cimt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci s8 gain; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci gain = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, reg))); 298c2ecf20Sopenharmony_ci gain += offset; 308c2ecf20Sopenharmony_ci mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid mt76x2_apply_gain_adj(struct mt76x02_dev *dev) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci s8 *gain_adj = dev->cal.rx.high_gain; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci mt76x2_adjust_high_lna_gain(dev, 4, gain_adj[0]); 388c2ecf20Sopenharmony_ci mt76x2_adjust_high_lna_gain(dev, 5, gain_adj[1]); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci mt76x2_adjust_agc_gain(dev, 8, gain_adj[0]); 418c2ecf20Sopenharmony_ci mt76x2_adjust_agc_gain(dev, 9, gain_adj[1]); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_civoid mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev, 468c2ecf20Sopenharmony_ci enum nl80211_band band) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci u32 pa_mode[2]; 498c2ecf20Sopenharmony_ci u32 pa_mode_adj; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (band == NL80211_BAND_2GHZ) { 528c2ecf20Sopenharmony_ci pa_mode[0] = 0x010055ff; 538c2ecf20Sopenharmony_ci pa_mode[1] = 0x00550055; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00); 568c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) { 598c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00); 608c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00); 618c2ecf20Sopenharmony_ci } else { 628c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0xf4000200); 638c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0xfa000200); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci } else { 668c2ecf20Sopenharmony_ci pa_mode[0] = 0x0000ffff; 678c2ecf20Sopenharmony_ci pa_mode[1] = 0x00ff00ff; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) { 708c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400); 718c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476); 728c2ecf20Sopenharmony_ci } else { 738c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_2, 0x1b0f0400); 748c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) 788c2ecf20Sopenharmony_ci pa_mode_adj = 0x04000000; 798c2ecf20Sopenharmony_ci else 808c2ecf20Sopenharmony_ci pa_mode_adj = 0; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ0, pa_mode_adj); 838c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_ADJ1, pa_mode_adj); 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BB_PA_MODE_CFG0, pa_mode[0]); 878c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BB_PA_MODE_CFG1, pa_mode[1]); 888c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]); 898c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) { 928c2ecf20Sopenharmony_ci u32 val; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (band == NL80211_BAND_2GHZ) 958c2ecf20Sopenharmony_ci val = 0x3c3c023c; 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci val = 0x363c023c; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val); 1008c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val); 1018c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00001818); 1028c2ecf20Sopenharmony_ci } else { 1038c2ecf20Sopenharmony_ci if (band == NL80211_BAND_2GHZ) { 1048c2ecf20Sopenharmony_ci u32 val = 0x0f3c3c3c; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val); 1078c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val); 1088c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00000606); 1098c2ecf20Sopenharmony_ci } else { 1108c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x383c023c); 1118c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX1_RF_GAIN_CORR, 0x24282e28); 1128c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_4, 0); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic int 1198c2ecf20Sopenharmony_cimt76x2_get_min_rate_power(struct mt76_rate_power *r) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci int i; 1228c2ecf20Sopenharmony_ci s8 ret = 0; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(r->all); i++) { 1258c2ecf20Sopenharmony_ci if (!r->all[i]) 1268c2ecf20Sopenharmony_ci continue; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (ret) 1298c2ecf20Sopenharmony_ci ret = min(ret, r->all[i]); 1308c2ecf20Sopenharmony_ci else 1318c2ecf20Sopenharmony_ci ret = r->all[i]; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci return ret; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_civoid mt76x2_phy_set_txpower(struct mt76x02_dev *dev) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci enum nl80211_chan_width width = dev->mphy.chandef.width; 1408c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 1418c2ecf20Sopenharmony_ci struct mt76x2_tx_power_info txp; 1428c2ecf20Sopenharmony_ci int txp_0, txp_1, delta = 0; 1438c2ecf20Sopenharmony_ci struct mt76_rate_power t = {}; 1448c2ecf20Sopenharmony_ci int base_power, gain; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci mt76x2_get_power_info(dev, &txp, chan); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (width == NL80211_CHAN_WIDTH_40) 1498c2ecf20Sopenharmony_ci delta = txp.delta_bw40; 1508c2ecf20Sopenharmony_ci else if (width == NL80211_CHAN_WIDTH_80) 1518c2ecf20Sopenharmony_ci delta = txp.delta_bw80; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci mt76x2_get_rate_power(dev, &t, chan); 1548c2ecf20Sopenharmony_ci mt76x02_add_rate_power_offset(&t, txp.target_power + delta); 1558c2ecf20Sopenharmony_ci mt76x02_limit_rate_power(&t, dev->txpower_conf); 1568c2ecf20Sopenharmony_ci dev->mphy.txpower_cur = mt76x02_get_max_rate_power(&t); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci base_power = mt76x2_get_min_rate_power(&t); 1598c2ecf20Sopenharmony_ci delta = base_power - txp.target_power; 1608c2ecf20Sopenharmony_ci txp_0 = txp.chain[0].target_power + txp.chain[0].delta + delta; 1618c2ecf20Sopenharmony_ci txp_1 = txp.chain[1].target_power + txp.chain[1].delta + delta; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci gain = min(txp_0, txp_1); 1648c2ecf20Sopenharmony_ci if (gain < 0) { 1658c2ecf20Sopenharmony_ci base_power -= gain; 1668c2ecf20Sopenharmony_ci txp_0 -= gain; 1678c2ecf20Sopenharmony_ci txp_1 -= gain; 1688c2ecf20Sopenharmony_ci } else if (gain > 0x2f) { 1698c2ecf20Sopenharmony_ci base_power -= gain - 0x2f; 1708c2ecf20Sopenharmony_ci txp_0 = 0x2f; 1718c2ecf20Sopenharmony_ci txp_1 = 0x2f; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci mt76x02_add_rate_power_offset(&t, -base_power); 1758c2ecf20Sopenharmony_ci dev->target_power = txp.target_power; 1768c2ecf20Sopenharmony_ci dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power; 1778c2ecf20Sopenharmony_ci dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power; 1788c2ecf20Sopenharmony_ci dev->mt76.rate_power = t; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci mt76x02_phy_set_txpower(dev, txp_0, txp_1); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_civoid mt76x2_configure_tx_delay(struct mt76x02_dev *dev, 1858c2ecf20Sopenharmony_ci enum nl80211_band band, u8 bw) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci u32 cfg0, cfg1; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) { 1908c2ecf20Sopenharmony_ci cfg0 = bw ? 0x000b0c01 : 0x00101101; 1918c2ecf20Sopenharmony_ci cfg1 = 0x00011414; 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci cfg0 = bw ? 0x000b0b01 : 0x00101001; 1948c2ecf20Sopenharmony_ci cfg1 = 0x00021414; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_SW_CFG0, cfg0); 1978c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_SW_CFG1, cfg1); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_OFDM_SIFS, 15); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_civoid mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 2068c2ecf20Sopenharmony_ci struct mt76x2_tx_power_info txp; 2078c2ecf20Sopenharmony_ci struct mt76x2_tssi_comp t = {}; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (!dev->cal.tssi_cal_done) 2108c2ecf20Sopenharmony_ci return; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (!dev->cal.tssi_comp_pending) { 2138c2ecf20Sopenharmony_ci /* TSSI trigger */ 2148c2ecf20Sopenharmony_ci t.cal_mode = BIT(0); 2158c2ecf20Sopenharmony_ci mt76x2_mcu_tssi_comp(dev, &t); 2168c2ecf20Sopenharmony_ci dev->cal.tssi_comp_pending = true; 2178c2ecf20Sopenharmony_ci } else { 2188c2ecf20Sopenharmony_ci if (mt76_rr(dev, MT_BBP(CORE, 34)) & BIT(4)) 2198c2ecf20Sopenharmony_ci return; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci dev->cal.tssi_comp_pending = false; 2228c2ecf20Sopenharmony_ci mt76x2_get_power_info(dev, &txp, chan); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, chan->band)) 2258c2ecf20Sopenharmony_ci t.pa_mode = 1; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci t.cal_mode = BIT(1); 2288c2ecf20Sopenharmony_ci t.slope0 = txp.chain[0].tssi_slope; 2298c2ecf20Sopenharmony_ci t.offset0 = txp.chain[0].tssi_offset; 2308c2ecf20Sopenharmony_ci t.slope1 = txp.chain[1].tssi_slope; 2318c2ecf20Sopenharmony_ci t.offset1 = txp.chain[1].tssi_offset; 2328c2ecf20Sopenharmony_ci mt76x2_mcu_tssi_comp(dev, &t); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked) 2358c2ecf20Sopenharmony_ci return; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 2388c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value); 2398c2ecf20Sopenharmony_ci dev->cal.dpd_cal_done = true; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic void 2458c2ecf20Sopenharmony_cimt76x2_phy_set_gain_val(struct mt76x02_dev *dev) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci u32 val; 2488c2ecf20Sopenharmony_ci u8 gain_val[2]; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; 2518c2ecf20Sopenharmony_ci gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci val = 0x1836 << 16; 2548c2ecf20Sopenharmony_ci if (!mt76x2_has_ext_lna(dev) && 2558c2ecf20Sopenharmony_ci dev->mphy.chandef.width >= NL80211_CHAN_WIDTH_40) 2568c2ecf20Sopenharmony_ci val = 0x1e42 << 16; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (mt76x2_has_ext_lna(dev) && 2598c2ecf20Sopenharmony_ci dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ && 2608c2ecf20Sopenharmony_ci dev->mphy.chandef.width < NL80211_CHAN_WIDTH_40) 2618c2ecf20Sopenharmony_ci val = 0x0f36 << 16; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci val |= 0xf8; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 8), 2668c2ecf20Sopenharmony_ci val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[0])); 2678c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 9), 2688c2ecf20Sopenharmony_ci val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) 2718c2ecf20Sopenharmony_ci mt76x02_phy_dfs_adjust_agc(dev); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_civoid mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci u8 *gain = dev->cal.agc_gain_init; 2778c2ecf20Sopenharmony_ci u8 low_gain_delta, gain_delta; 2788c2ecf20Sopenharmony_ci u32 agc_35, agc_37; 2798c2ecf20Sopenharmony_ci bool gain_change; 2808c2ecf20Sopenharmony_ci int low_gain; 2818c2ecf20Sopenharmony_ci u32 val; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); 2848c2ecf20Sopenharmony_ci if (!dev->cal.avg_rssi_all) 2858c2ecf20Sopenharmony_ci dev->cal.avg_rssi_all = -75; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + 2888c2ecf20Sopenharmony_ci (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci gain_change = dev->cal.low_gain < 0 || 2918c2ecf20Sopenharmony_ci (dev->cal.low_gain & 2) ^ (low_gain & 2); 2928c2ecf20Sopenharmony_ci dev->cal.low_gain = low_gain; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (!gain_change) { 2958c2ecf20Sopenharmony_ci if (mt76x02_phy_adjust_vga_gain(dev)) 2968c2ecf20Sopenharmony_ci mt76x2_phy_set_gain_val(dev); 2978c2ecf20Sopenharmony_ci return; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) { 3018c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211); 3028c2ecf20Sopenharmony_ci val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf; 3038c2ecf20Sopenharmony_ci if (low_gain == 2) 3048c2ecf20Sopenharmony_ci val |= 0x3; 3058c2ecf20Sopenharmony_ci else 3068c2ecf20Sopenharmony_ci val |= 0x5; 3078c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 26), val); 3088c2ecf20Sopenharmony_ci } else { 3098c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (mt76x2_has_ext_lna(dev)) 3138c2ecf20Sopenharmony_ci low_gain_delta = 10; 3148c2ecf20Sopenharmony_ci else 3158c2ecf20Sopenharmony_ci low_gain_delta = 14; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci agc_37 = 0x2121262c; 3188c2ecf20Sopenharmony_ci if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ) 3198c2ecf20Sopenharmony_ci agc_35 = 0x11111516; 3208c2ecf20Sopenharmony_ci else if (low_gain == 2) 3218c2ecf20Sopenharmony_ci agc_35 = agc_37 = 0x08080808; 3228c2ecf20Sopenharmony_ci else if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) 3238c2ecf20Sopenharmony_ci agc_35 = 0x10101014; 3248c2ecf20Sopenharmony_ci else 3258c2ecf20Sopenharmony_ci agc_35 = 0x11111116; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (low_gain == 2) { 3288c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); 3298c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); 3308c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808); 3318c2ecf20Sopenharmony_ci gain_delta = low_gain_delta; 3328c2ecf20Sopenharmony_ci dev->cal.agc_gain_adjust = 0; 3338c2ecf20Sopenharmony_ci } else { 3348c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); 3358c2ecf20Sopenharmony_ci gain_delta = 0; 3368c2ecf20Sopenharmony_ci dev->cal.agc_gain_adjust = low_gain_delta; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 35), agc_35); 3408c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(AGC, 37), agc_37); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; 3438c2ecf20Sopenharmony_ci dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; 3448c2ecf20Sopenharmony_ci mt76x2_phy_set_gain_val(dev); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* clear false CCA counters */ 3478c2ecf20Sopenharmony_ci mt76_rr(dev, MT_RX_STAT_1); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain); 350