static void ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) { u_int modesIndex, freqIndex; int regWrites = 0; /* Setup the indices for the next set of register array writes */ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { freqIndex = 2; if (IEEE80211_IS_CHAN_HT40(chan)) modesIndex = 3; else if (IEEE80211_IS_CHAN_108G(chan)) modesIndex = 5; else modesIndex = 4; } else { freqIndex = 1; if (IEEE80211_IS_CHAN_HT40(chan) || IEEE80211_IS_CHAN_TURBO(chan)) modesIndex = 2; else modesIndex = 1; } /* Set correct Baseband to analog shift setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); /* XXX Merlin ini fixups */ /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); if (AR_SREV_MERLIN_20_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, modesIndex, regWrites); regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, modesIndex, regWrites); } /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* 5GHz channels w/ Fast Clock use different modal values */ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, modesIndex, regWrites); } }
void ar9280olcGetTxGainIndex(struct ath_hal *ah, const struct ieee80211_channel *chan, struct calDataPerFreqOpLoop *rawDatasetOpLoop, uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx) { uint8_t pcdac, i = 0; uint16_t idxL = 0, idxR = 0, numPiers; HAL_BOOL match; CHAN_CENTERS centers; ar5416GetChannelCenters(ah, chan, ¢ers); for (numPiers = 0; numPiers < availPiers; numPiers++) if (calChans[numPiers] == AR5416_BCHAN_UNUSED) break; match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), calChans, numPiers, &idxL, &idxR); if (match) { pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; } else { pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; } while (pcdac > AH9280(ah)->originalGain[i] && i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) i++; *pcdacIdx = i; }
void ar9280olcInit(struct ath_hal *ah) { uint32_t i; /* Only do OLC if it's enabled for this chipset */ if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) return; HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Setting up TX gain tables.\n", __func__); for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) AH9280(ah)->originalGain[i] = MS(OS_REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_GAIN); AH9280(ah)->PDADCdelta = 0; }
/* * Run temperature compensation calibration. * * The TX gain table is adjusted depending upon the difference * between the initial PDADC value and the currently read * average TX power sample value. This value is only valid if * frames have been transmitted, so currPDADC will be 0 if * no frames have yet been transmitted. */ void ar9280olcTemperatureCompensation(struct ath_hal *ah) { uint32_t rddata, i; int delta, currPDADC, regval; uint8_t hpwr_5g = 0; if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) return; rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: called: initPDADC=%d, currPDADC=%d\n", __func__, AH5416(ah)->initPDADC, currPDADC); if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) return; (void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g)); if (hpwr_5g) delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8; else delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10; HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n", __func__, delta, AH9280(ah)->PDADCdelta); if (delta != AH9280(ah)->PDADCdelta) { AH9280(ah)->PDADCdelta = delta; for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { regval = AH9280(ah)->originalGain[i] - delta; if (regval < 0) regval = 0; OS_REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, AR_PHY_TX_GAIN, regval); } } }
static void ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) { u_int modesIndex, freqIndex; int regWrites = 0; int i; const HAL_INI_ARRAY *ia; /* Setup the indices for the next set of register array writes */ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { freqIndex = 2; if (IEEE80211_IS_CHAN_HT40(chan)) modesIndex = 3; else if (IEEE80211_IS_CHAN_108G(chan)) modesIndex = 5; else modesIndex = 4; } else { freqIndex = 1; if (IEEE80211_IS_CHAN_HT40(chan) || IEEE80211_IS_CHAN_TURBO(chan)) modesIndex = 2; else modesIndex = 1; } /* Set correct Baseband to analog shift setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); /* * This is unwound because at the moment, there's a requirement * for Merlin (and later, perhaps) to have a specific bit fixed * in the AR_AN_TOP2 register before writing it. */ ia = &AH5212(ah)->ah_ini_modes; #if 0 regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); #endif HALASSERT(modesIndex < ia->cols); for (i = 0; i < ia->rows; i++) { uint32_t reg = HAL_INI_VAL(ia, i, 0); uint32_t val = HAL_INI_VAL(ia, i, modesIndex); if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup) val &= ~AR_AN_TOP2_PWDCLKIND; OS_REG_WRITE(ah, reg, val); /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ if (reg >= 0x7800 && reg < 0x7900) OS_DELAY(100); DMA_YIELD(regWrites); } if (AR_SREV_MERLIN_20_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, modesIndex, regWrites); regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, modesIndex, regWrites); } /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* 5GHz channels w/ Fast Clock use different modal values */ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, modesIndex, regWrites); } }