diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:12:45 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:13:24 -0500 |
commit | 1032c736e81cdf490ae62f86da7efe67c3c3e61d (patch) | |
tree | a0c3919849f97dbbc5ea7c6a9ac1d7a639e44a73 /drivers/net/wireless/b43 | |
parent | 117ff42fd43e92d24c6aa6f3e4f0f1e1edada140 (diff) | |
parent | cb00ec382b57d35b955c085198cd54a0c1fcdc94 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/b43legacy/dma.c
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 355 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/b43/tables_nphy.c | 106 |
4 files changed, 348 insertions, 130 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f19605e8eb4..16e8f805815 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -191,6 +191,9 @@ #define B43_BFH_BUCKBOOST 0x0020 /* has buck/booster */ #define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna * with bluetooth */ +#define B43_BFH_NOCBUCK 0x0080 +#define B43_BFH_PALDO 0x0200 +#define B43_BFH_EXTLNA_5GHZ 0x1000 /* has an external LNA (5GHz mode) */ /* SPROM boardflags2_lo values */ #define B43_BFL2_RXBB_INT_REG_DIS 0x0001 /* external RX BB regulator present */ @@ -204,6 +207,14 @@ #define B43_BFL2_SKWRKFEM_BRD 0x0100 /* 4321mcm93 uses Skyworks FEM */ #define B43_BFL2_SPUR_WAR 0x0200 /* has a workaround for clock-harmonic spurs */ #define B43_BFL2_GPLL_WAR 0x0400 /* altenative G-band PLL settings implemented */ +#define B43_BFL2_SINGLEANT_CCK 0x1000 +#define B43_BFL2_2G_SPUR_WAR 0x2000 + +/* SPROM boardflags2_hi values */ +#define B43_BFH2_GPLL_WAR2 0x0001 +#define B43_BFH2_IPALVLSHIFT_3P3 0x0002 +#define B43_BFH2_INTERNDET_TXIQCAL 0x0004 +#define B43_BFH2_XTALBUFOUTEN 0x0008 /* GPIO register offset, in both ChipCommon and PCI core. */ #define B43_GPIO_CONTROL 0x6c diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 0d25fe4069b..bf5a4385535 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -167,7 +167,7 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, b43_phy_mask(dev, val_addr, ~(rf_ctrl->val_mask)); } else { - if (core == 0 || ((1 << core) & i) != 0) { + if (core == 0 || ((1 << i) & core)) { b43_phy_set(dev, en_addr, field); b43_phy_maskset(dev, val_addr, ~(rf_ctrl->val_mask), @@ -200,7 +200,7 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, addr = B43_PHY_N((i == 0) ? rf_ctrl->addr0 : rf_ctrl->addr1); - if ((core & (1 << i)) != 0) + if ((1 << i) & core) b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask), (value << rf_ctrl->shift)); @@ -956,7 +956,7 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1); } for (i = 0; i < 100; i++) { - if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) { + if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) { i = 0; break; } @@ -1511,7 +1511,8 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev) /* Prepare values */ ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; - ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA; + ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ : + sprom->boardflags_lo & B43_BFL_EXTLNA; e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna); if (ghz5 && dev->phy.rev >= 5) rssi_gain = 0x90; @@ -1562,7 +1563,6 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev) b43_phy_write(dev, 0x2A7, e->init_gain); b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2, e->rfseq_init); - b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain); /* TODO: check defines. Do not match variables names */ b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain); @@ -1929,6 +1929,117 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) } /************************************************** + * Tx/Rx common + **************************************************/ + +/* + * Transmits a known value for LO calibration + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone + */ +static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, + bool iqmode, bool dac_test) +{ + u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); + if (samp == 0) + return -1; + b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test); + return 0; +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ +static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + bool override = false; + u16 chain = 0x33; + + if (nphy->txrx_chain == 0) { + chain = 0x11; + override = true; + } else if (nphy->txrx_chain == 1) { + chain = 0x22; + override = true; + } + + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, + ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), + chain); + + if (override) + b43_phy_set(dev, B43_NPHY_RFSEQMODE, + B43_NPHY_RFSEQMODE_CAOVER); + else + b43_phy_mask(dev, B43_NPHY_RFSEQMODE, + ~B43_NPHY_RFSEQMODE_CAOVER); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ +static void b43_nphy_stop_playback(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u16 tmp; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); + if (tmp & 0x1) + b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); + else if (tmp & 0x2) + b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); + + b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); + + if (nphy->bb_mult_save & 0x80000000) { + tmp = nphy->bb_mult_save & 0xFFFF; + b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); + nphy->bb_mult_save = 0; + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ +static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, + struct nphy_txgains target, + struct nphy_iqcal_params *params) +{ + int i, j, indx; + u16 gain; + + if (dev->phy.rev >= 3) { + params->txgm = target.txgm[core]; + params->pga = target.pga[core]; + params->pad = target.pad[core]; + params->ipa = target.ipa[core]; + params->cal_gain = (params->txgm << 12) | (params->pga << 8) | + (params->pad << 4) | (params->ipa); + for (j = 0; j < 5; j++) + params->ncorr[j] = 0x79; + } else { + gain = (target.pad[core]) | (target.pga[core] << 4) | + (target.txgm[core] << 8); + + indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? + 1 : 0; + for (i = 0; i < 9; i++) + if (tbl_iqcal_gainparams[indx][i][0] == gain) + break; + i = min(i, 8); + + params->txgm = tbl_iqcal_gainparams[indx][i][1]; + params->pga = tbl_iqcal_gainparams[indx][i][2]; + params->pad = tbl_iqcal_gainparams[indx][i][3]; + params->cal_gain = (params->txgm << 7) | (params->pga << 4) | + (params->pad << 2); + for (j = 0; j < 4; j++) + params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; + } +} + +/************************************************** * Tx and Rx **************************************************/ @@ -2107,7 +2218,7 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) } } if (dev->phy.rev < 7 && - (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10)) + (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100)) txpi[0] = txpi[1] = 91; /* @@ -2186,6 +2297,129 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + + u8 core; + u16 r; /* routing */ + + if (phy->rev >= 7) { + for (core = 0; core < 2; core++) { + r = core ? 0x190 : 0x170; + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_radio_write(dev, r + 0x5, 0x5); + b43_radio_write(dev, r + 0x9, 0xE); + if (phy->rev != 5) + b43_radio_write(dev, r + 0xA, 0); + if (phy->rev != 7) + b43_radio_write(dev, r + 0xB, 1); + else + b43_radio_write(dev, r + 0xB, 0x31); + } else { + b43_radio_write(dev, r + 0x5, 0x9); + b43_radio_write(dev, r + 0x9, 0xC); + b43_radio_write(dev, r + 0xB, 0x0); + if (phy->rev != 5) + b43_radio_write(dev, r + 0xA, 1); + else + b43_radio_write(dev, r + 0xA, 0x31); + } + b43_radio_write(dev, r + 0x6, 0); + b43_radio_write(dev, r + 0x7, 0); + b43_radio_write(dev, r + 0x8, 3); + b43_radio_write(dev, r + 0xC, 0); + } + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128); + else + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80); + b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0); + b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29); + + for (core = 0; core < 2; core++) { + r = core ? B2056_TX1 : B2056_TX0; + + b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0); + b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0); + b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3); + b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0); + b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8); + b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0); + b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER, + 0x5); + if (phy->rev != 5) + b43_radio_write(dev, r | B2056_TX_TSSIA, + 0x00); + if (phy->rev >= 5) + b43_radio_write(dev, r | B2056_TX_TSSIG, + 0x31); + else + b43_radio_write(dev, r | B2056_TX_TSSIG, + 0x11); + b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX, + 0xE); + } else { + b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER, + 0x9); + b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31); + b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0); + b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX, + 0xC); + } + } + } +} + +/* + * Stop radio and transmit known signal. Then check received signal strength to + * get TSSI (Transmit Signal Strength Indicator). + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi + */ +static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = dev->phy.n; + + u32 tmp; + s32 rssi[4] = { }; + + /* TODO: check if we can transmit */ + + if (b43_nphy_ipa(dev)) + b43_nphy_ipa_internal_tssi_setup(dev); + + if (phy->rev >= 7) + ; /* TODO: Override Rev7 with 0x2000, 0, 3, 0, 0 as arguments */ + else if (phy->rev >= 3) + b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false); + + b43_nphy_stop_playback(dev); + b43_nphy_tx_tone(dev, 0xFA0, 0, false, false); + udelay(20); + tmp = b43_nphy_poll_rssi(dev, 4, rssi, 1); + b43_nphy_stop_playback(dev); + b43_nphy_rssi_select(dev, 0, 0); + + if (phy->rev >= 7) + ; /* TODO: Override Rev7 with 0x2000, 0, 3, 1, 0 as arguments */ + else if (phy->rev >= 3) + b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true); + + if (phy->rev >= 3) { + nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; + nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; + } else { + nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF; + nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF; + } + nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF; + nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; +} + static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; @@ -2290,34 +2524,6 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) } } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ -static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) -{ - struct b43_phy_n *nphy = dev->phy.n; - - bool override = false; - u16 chain = 0x33; - - if (nphy->txrx_chain == 0) { - chain = 0x11; - override = true; - } else if (nphy->txrx_chain == 1) { - chain = 0x22; - override = true; - } - - b43_phy_maskset(dev, B43_NPHY_RFSEQCA, - ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), - chain); - - if (override) - b43_phy_set(dev, B43_NPHY_RFSEQMODE, - B43_NPHY_RFSEQMODE_CAOVER); - else - b43_phy_mask(dev, B43_NPHY_RFSEQMODE, - ~B43_NPHY_RFSEQMODE_CAOVER); -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, u16 samps, u8 time, bool wait) @@ -2569,33 +2775,6 @@ static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ -static void b43_nphy_stop_playback(struct b43_wldev *dev) -{ - struct b43_phy_n *nphy = dev->phy.n; - u16 tmp; - - if (nphy->hang_avoid) - b43_nphy_stay_in_carrier_search(dev, 1); - - tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); - if (tmp & 0x1) - b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); - else if (tmp & 0x2) - b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); - - b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); - - if (nphy->bb_mult_save & 0x80000000) { - tmp = nphy->bb_mult_save & 0xFFFF; - b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); - nphy->bb_mult_save = 0; - } - - if (nphy->hang_avoid) - b43_nphy_stay_in_carrier_search(dev, 0); -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ static void b43_nphy_spur_workaround(struct b43_wldev *dev) { @@ -2655,20 +2834,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } -/* - * Transmits a known value for LO calibration - * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone - */ -static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, - bool iqmode, bool dac_test) -{ - u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); - if (samp == 0) - return -1; - b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test); - return 0; -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) { @@ -2872,44 +3037,6 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) } } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ -static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, - struct nphy_txgains target, - struct nphy_iqcal_params *params) -{ - int i, j, indx; - u16 gain; - - if (dev->phy.rev >= 3) { - params->txgm = target.txgm[core]; - params->pga = target.pga[core]; - params->pad = target.pad[core]; - params->ipa = target.ipa[core]; - params->cal_gain = (params->txgm << 12) | (params->pga << 8) | - (params->pad << 4) | (params->ipa); - for (j = 0; j < 5; j++) - params->ncorr[j] = 0x79; - } else { - gain = (target.pad[core]) | (target.pga[core] << 4) | - (target.txgm[core] << 8); - - indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? - 1 : 0; - for (i = 0; i < 9; i++) - if (tbl_iqcal_gainparams[indx][i][0] == gain) - break; - i = min(i, 8); - - params->txgm = tbl_iqcal_gainparams[indx][i][1]; - params->pga = tbl_iqcal_gainparams[indx][i][2]; - params->pad = tbl_iqcal_gainparams[indx][i][3]; - params->cal_gain = (params->txgm << 7) | (params->pga << 4) | - (params->pad << 2); - for (j = 0; j < 4; j++) - params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; - } -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) { @@ -3982,7 +4109,7 @@ int b43_phy_initn(struct b43_wldev *dev) tx_pwr_state = nphy->txpwrctrl; b43_nphy_tx_power_ctrl(dev, false); b43_nphy_tx_power_fix(dev); - /* TODO N PHY TX Power Control Idle TSSI */ + b43_nphy_tx_power_ctl_idle_tssi(dev); /* TODO N PHY TX Power Control Setup */ b43_nphy_tx_gain_table_upload(dev); diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 56ef97b5b81..5de8f74cc02 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -765,6 +765,11 @@ struct b43_phy_n_txpwrindex { u16 locomp; }; +struct b43_phy_n_pwr_ctl_info { + u8 idle_tssi_2g; + u8 idle_tssi_5g; +}; + struct b43_phy_n { u8 antsel_type; u8 cal_orig_pwr_idx[2]; @@ -798,6 +803,7 @@ struct b43_phy_n { u16 txiqlocal_bestc[11]; bool txiqlocal_coeffsvalid; struct b43_phy_n_txpwrindex txpwrindex[2]; + struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2]; struct b43_chanspec txiqlocal_chanspec; u8 txrx_chain; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 3252560e9fa..f7def13524d 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2752,7 +2752,18 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = { { 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */ }; -struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = { +struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { + { 10, 14, 19, 27 }, + { -5, 6, 10, 15 }, + { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + 0x427E, + { 0x413F, 0x413F, 0x413F, 0x413F }, + 0x007E, 0x0066, 0x1074, + 0x18, 0x18, 0x18, + 0x01D0, 0x5, +}; +struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = { { /* 2GHz */ { /* PHY rev 3 */ { 7, 11, 16, 23 }, @@ -2776,15 +2787,26 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = { 0x18, 0x18, 0x18, 0x01A1, 0x5, }, - { /* PHY rev 5+ */ + { /* PHY rev 5 */ { 9, 13, 18, 26 }, { -3, 7, 11, 16 }, { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, 0x427E, /* invalid for external LNA! */ { 0x413F, 0x413F, 0x413F, 0x413F }, /* invalid for external LNA! */ - 0x1076, 0x0066, 0x106A, - 0xC, 0xC, 0xC, + 0x1076, 0x0066, 0x0000, /* low is invalid (the last one) */ + 0x18, 0x18, 0x18, + 0x01D0, 0x9, + }, + { /* PHY rev 6+ */ + { 8, 13, 18, 25 }, + { -5, 6, 10, 14 }, + { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + 0x527E, /* invalid for external LNA! */ + { 0x513F, 0x513F, 0x513F, 0x513F }, /* invalid for external LNA! */ + 0x1076, 0x0066, 0x0000, /* low is invalid (the last one) */ + 0x18, 0x18, 0x18, 0x01D0, 0x5, }, }, @@ -2811,7 +2833,7 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = { 0x24, 0x24, 0x24, 0x0107, 25, }, - { /* PHY rev 5+ */ + { /* PHY rev 5 */ { 6, 10, 16, 21 }, { -7, 0, 4, 8 }, { 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD }, @@ -2822,6 +2844,17 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = { 0x24, 0x24, 0x24, 0x00A9, 25, }, + { /* PHY rev 6+ */ + { 6, 10, 16, 21 }, + { -7, 0, 4, 8 }, + { 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, + 0x729E, + { 0x714F, 0x714F, 0x714F, 0x714F }, + 0x029E, 0x2084, 0x2086, + 0x24, 0x24, 0x24, /* low is invalid for radio rev 11! */ + 0x00F0, 25, + }, }, }; @@ -3098,26 +3131,67 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( { struct nphy_gain_ctl_workaround_entry *e; u8 phy_idx; + u8 tr_iso = ghz5 ? dev->dev->bus_sprom->fem.ghz5.tr_iso : + dev->dev->bus_sprom->fem.ghz2.tr_iso; + + if (!ghz5 && dev->phy.rev >= 6 && dev->phy.radio_rev == 11) + return &nphy_gain_ctl_wa_phy6_radio11_ghz2; B43_WARN_ON(dev->phy.rev < 3); - if (dev->phy.rev >= 5) + if (dev->phy.rev >= 6) + phy_idx = 3; + else if (dev->phy.rev == 5) phy_idx = 2; else if (dev->phy.rev == 4) phy_idx = 1; else phy_idx = 0; - e = &nphy_gain_ctl_workaround[ghz5][phy_idx]; - /* Only one entry differs for external LNA, so instead making whole - * table 2 times bigger, hack is here - */ - if (!ghz5 && dev->phy.rev >= 5 && ext_lna) { - e->rfseq_init[0] &= 0x0FFF; - e->rfseq_init[1] &= 0x0FFF; - e->rfseq_init[2] &= 0x0FFF; - e->rfseq_init[3] &= 0x0FFF; - e->init_gain &= 0x0FFF; + /* Some workarounds to the workarounds... */ + if (ghz5 && dev->phy.rev >= 6) { + if (dev->phy.radio_rev == 11 && + !b43_channel_type_is_40mhz(dev->phy.channel_type)) + e->cliplo_gain = 0x2d; + } else if (!ghz5 && dev->phy.rev >= 5) { + if (ext_lna) { + e->rfseq_init[0] &= ~0x4000; + e->rfseq_init[1] &= ~0x4000; + e->rfseq_init[2] &= ~0x4000; + e->rfseq_init[3] &= ~0x4000; + e->init_gain &= ~0x4000; + } + switch (tr_iso) { + case 0: + e->cliplo_gain = 0x0062; + case 1: + e->cliplo_gain = 0x0064; + case 2: + e->cliplo_gain = 0x006a; + case 3: + e->cliplo_gain = 0x106a; + case 4: + e->cliplo_gain = 0x106c; + case 5: + e->cliplo_gain = 0x1074; + case 6: + e->cliplo_gain = 0x107c; + case 7: + e->cliplo_gain = 0x207c; + default: + e->cliplo_gain = 0x106a; + } + } else if (ghz5 && dev->phy.rev == 4 && ext_lna) { + e->rfseq_init[0] &= ~0x4000; + e->rfseq_init[1] &= ~0x4000; + e->rfseq_init[2] &= ~0x4000; + e->rfseq_init[3] &= ~0x4000; + e->init_gain &= ~0x4000; + e->rfseq_init[0] |= 0x1000; + e->rfseq_init[1] |= 0x1000; + e->rfseq_init[2] |= 0x1000; + e->rfseq_init[3] |= 0x1000; + e->init_gain |= 0x1000; } return e; |