Import some initial Kite fixed diversity code from Atheros.

For now, the diversity settings are controlled by 'txantenna',
-not- rxantenna. This is because the earlier chipsets had
controllable TX diversity; the RX antenna setting twiddles
the default antenna register. I'll try sort that stuff out at
some point.

Call the antenna switch function from the board setup function
so scans, channel changes, mode changes, etc don't set the
diversity back to a default state too far from what's intended.

Things to todo:

* Squirrel away the last antenna diversity/combining parameters
  and restore them during board setup if HAL_ANT_VARIABLE is
  defined. That way scans, etc don't reset the diversity settings.

* Add some more public facing statistics, rather than what's
  simply logged under HAL_DEBUG_DIVERSITY.

For now, the fixed antenna settings behave better than variable
settings for me. I have some further fiddling to do..

Obtained from:	Atheros
This commit is contained in:
adrian 2011-05-09 15:19:49 +00:00
parent 3592656c6f
commit 08e0a0c638
4 changed files with 148 additions and 44 deletions

View File

@ -21,10 +21,10 @@
#include "ar5416/ar5416.h"
enum ar9285_ant_div_comb_lna_conf {
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
ATH_ANT_DIV_COMB_LNA2,
ATH_ANT_DIV_COMB_LNA1,
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2 = 0,
ATH_ANT_DIV_COMB_LNA2 = 1,
ATH_ANT_DIV_COMB_LNA1 = 2,
ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2 = 3,
};
struct ar9285_ant_comb {

View File

@ -407,15 +407,6 @@ ar9285FillCapabilityInfo(struct ath_hal *ah)
return AH_TRUE;
}
/*
* Antenna selection is not (currently) done this way.
*/
HAL_BOOL
ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
{
return AH_TRUE;
}
static const char*
ar9285Probe(uint16_t vendorid, uint16_t devid)
{

View File

@ -374,11 +374,19 @@ ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs,
if (! ar9285_check_div_comb(ah))
return;
if (AH5212(ah)->ah_diversity == AH_FALSE)
return;
rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
ATH_ANT_RX_MASK;
main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
ATH_ANT_RX_MASK;
#if 0
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main: %d, alt: %d, rx_ant_conf: %x, main_ant_conf: %x\n",
__func__, main_rssi, alt_rssi, rx_ant_conf, main_ant_conf);
#endif
/* Record packet only when alt_rssi is positive */
if (alt_rssi > 0) {
antcomb->total_pkt_count++;
@ -587,6 +595,24 @@ ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs,
ar9285_antdiv_comb_conf_set(ah, &div_ant_conf);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n",
__func__, antcomb->total_pkt_count);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n",
__func__, antcomb->main_total_rssi);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n",
__func__, antcomb->alt_total_rssi);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n",
__func__, main_rssi_avg);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n",
__func__, alt_rssi_avg);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n",
__func__, antcomb->main_recv_cnt);
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n",
__func__, antcomb->alt_recv_cnt);
if (curr_alt_set != div_ant_conf.alt_lna_conf)
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n",
__func__, curr_alt_set, div_ant_conf.alt_lna_conf);
@ -604,3 +630,117 @@ ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs,
antcomb->main_recv_cnt = 0;
antcomb->alt_recv_cnt = 0;
}
/*
* Set the antenna switch to control RX antenna diversity.
*
* If a fixed configuration is used, the LNA and div bias
* settings are fixed and the antenna diversity scanning routine
* is disabled.
*
* If a variable configuration is used, a default is programmed
* in and sampling commences per RXed packet.
*
* Since this is called from ar9285SetBoardValues() to setup
* diversity, it means that after a reset or scan, any current
* software diversity combining settings will be lost and won't
* re-appear until after the first successful sample run.
* Please keep this in mind if you're seeing weird performance
* that happens to relate to scan/diversity timing.
*/
HAL_BOOL
ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
{
int regVal;
const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom;
const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader;
uint8_t ant_div_control1, ant_div_control2;
if (pModal->version < 3) {
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: not supported\n",
__func__);
return AH_FALSE; /* Can't do diversity */
}
/* Store settings */
AH5212(ah)->ah_antControl = settings;
AH5212(ah)->ah_diversity = (settings == HAL_ANT_VARIABLE);
/* XXX don't fiddle if the PHY is in sleep mode or ! chan */
/* Begin setting the relevant registers */
ant_div_control1 = pModal->antdiv_ctl1;
ant_div_control2 = pModal->antdiv_ctl2;
regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
/* enable antenna diversity only if diversityControl == HAL_ANT_VARIABLE */
if (settings == HAL_ANT_VARIABLE)
regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL);
if (settings == HAL_ANT_VARIABLE) {
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_VARIABLE\n",
__func__);
regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB);
regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
} else {
if (settings == HAL_ANT_FIXED_A) {
/* Diversity disabled, RX = LNA1 */
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_A\n",
__func__);
regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_ALT_GAINTB);
regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
}
else if (settings == HAL_ANT_FIXED_B) {
/* Diversity disabled, RX = LNA2 */
HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_B\n",
__func__);
regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_ALT_GAINTB);
regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
}
}
OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
if (settings == HAL_ANT_VARIABLE)
regVal |= SM((ant_div_control1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
/*
* If Diversity combining is available and the diversity setting
* is to allow variable diversity, enable it by default.
*
* This will be eventually overridden by the software antenna
* diversity logic.
*
* Note that yes, this following section overrides the above
* settings for the LNA configuration and fast-bias.
*/
if (ar9285_check_div_comb(ah) && AH5212(ah)->ah_diversity == AH_TRUE) {
// If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning
HALDEBUG(ah, HAL_DEBUG_DIVERSITY,
"%s: Enable initial settings for combined diversity\n",
__func__);
regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | AR_PHY_9285_ANT_DIV_ALT_LNACONF));
regVal |= (ATH_ANT_DIV_COMB_LNA1 << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S);
regVal |= (ATH_ANT_DIV_COMB_LNA2 << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S);
regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));
regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S);
OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
}
return AH_TRUE;
}

View File

@ -237,8 +237,6 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
const MODAL_EEP4K_HEADER *pModal;
uint8_t txRxAttenLocal;
uint8_t ob[5], db1[5], db2[5];
uint8_t ant_div_control1, ant_div_control2;
uint32_t regVal;
pModal = &eep->modalHeader;
txRxAttenLocal = 23;
@ -248,36 +246,10 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
/* Single chain for 4K EEPROM*/
ar9285SetBoardGain(ah, pModal, eep, txRxAttenLocal);
/* Initialize Ant Diversity settings from EEPROM */
if (pModal->version >= 3) {
ant_div_control1 = pModal->antdiv_ctl1;
ant_div_control2 = pModal->antdiv_ctl2;
regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
regVal |= SM(ant_div_control1,
AR_PHY_9285_ANT_DIV_CTL);
regVal |= SM(ant_div_control2,
AR_PHY_9285_ANT_DIV_ALT_LNACONF);
regVal |= SM((ant_div_control2 >> 2),
AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
regVal |= SM((ant_div_control1 >> 1),
AR_PHY_9285_ANT_DIV_ALT_GAINTB);
regVal |= SM((ant_div_control1 >> 2),
AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
regVal |= SM((ant_div_control1 >> 3),
AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
}
/* Initialize Ant Diversity settings if supported */
(void) ar9285SetAntennaSwitch(ah, AH5212(ah)->ah_antControl);
/* Configure TX power calibration */
if (pModal->version >= 2) {
ob[0] = pModal->ob_0;
ob[1] = pModal->ob_1;
@ -379,6 +351,7 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
if (AR_SREV_9271(ah) || AR_SREV_KITE(ah)) {
uint8_t bb_desired_scale = (pModal->bb_scale_smrt_antenna & EEP_4K_BB_DESIRED_SCALE_MASK);
if ((eep->baseEepHeader.txGainType == 0) && (bb_desired_scale != 0)) {
ath_hal_printf(ah, "[ath]: adjusting cck tx gain factor\n");
uint32_t pwrctrl, mask, clr;
mask = (1<<0) | (1<<5) | (1<<10) | (1<<15) | (1<<20) | (1<<25);