📄 ar5111.c.svn-base
字号:
if (srcRight != srcLeft) { /* * Note the ratio always need to be scaled, * since it will be a fraction. */ lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); if (lRatio < 0) { /* Return as Left target if value would be negative */ rv = targetLeft; } else if (lRatio > EEP_SCALE) { /* Return as Right target if Ratio is greater than 100% (SCALE) */ rv = targetRight; } else { rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * targetLeft) / EEP_SCALE; } } else { rv = targetLeft; } return rv;}/* * Read the transmit power levels from the structures taken from EEPROM * Interpolate read transmit power values for this channel * Organize the transmit power values into a table for writing into the hardware */static HAL_BOOLar5111SetPowerTable(struct ath_hal *ah, int16_t *pMinPower, int16_t *pMaxPower, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain){ struct ath_hal_5212 *ahp = AH5212(ah); const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; FULL_PCDAC_STRUCT pcdacStruct; int i, j; uint16_t *pPcdacValues; int16_t *pScaledUpDbm; int16_t minScaledPwr; int16_t maxScaledPwr; int16_t pwr; uint16_t pcdacMin = 0; uint16_t pcdacMax = PCDAC_STOP; uint16_t pcdacTableIndex; uint16_t scaledPcdac; PCDACS_EEPROM *pSrcStruct; PCDACS_EEPROM eepromPcdacs; /* setup the pcdac struct to point to the correct info, based on mode */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: eepromPcdacs.numChannels = ee->ee_numChannels11a; eepromPcdacs.pChannelList = ee->ee_channels11a; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; break; case CHANNEL_B: eepromPcdacs.numChannels = ee->ee_numChannels2_4; eepromPcdacs.pChannelList = ee->ee_channels11b; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; break; case CHANNEL_G: case CHANNEL_108G: eepromPcdacs.numChannels = ee->ee_numChannels2_4; eepromPcdacs.pChannelList = ee->ee_channels11g; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } pSrcStruct = &eepromPcdacs; OS_MEMZERO(&pcdacStruct, sizeof(pcdacStruct)); pPcdacValues = pcdacStruct.PcdacValues; pScaledUpDbm = pcdacStruct.PwrValues; /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) pPcdacValues[j] = i; pcdacStruct.numPcdacValues = j; pcdacStruct.pcdacMin = PCDAC_START; pcdacStruct.pcdacMax = PCDAC_STOP; /* Fill out the power values for this channel */ for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) pScaledUpDbm[j] = ar5212GetScaledPower(chan->channel, pPcdacValues[j], pSrcStruct); /* Now scale the pcdac values to fit in the 64 entry power table */ minScaledPwr = pScaledUpDbm[0]; maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; /* find minimum and make monotonic */ for (j = 0; j < pcdacStruct.numPcdacValues; j++) { if (minScaledPwr >= pScaledUpDbm[j]) { minScaledPwr = pScaledUpDbm[j]; pcdacMin = j; } /* * Make the full_hsh monotonically increasing otherwise * interpolation algorithm will get fooled gotta start * working from the top, hence i = 63 - j. */ i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); if (i == 0) break; if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { /* * It could be a glitch, so make the power for * this pcdac the same as the power from the * next highest pcdac. */ pScaledUpDbm[i - 1] = pScaledUpDbm[i]; } } for (j = 0; j < pcdacStruct.numPcdacValues; j++) if (maxScaledPwr < pScaledUpDbm[j]) { maxScaledPwr = pScaledUpDbm[j]; pcdacMax = j; } /* Find the first power level with a pcdac */ pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); /* Write all the first pcdac entries based off the pcdacMin */ pcdacTableIndex = 0; for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) { HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); ahp->ah_pcdacTable[pcdacTableIndex++] = pcdacMin; } i = 0; while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && pcdacTableIndex < PWR_TABLE_SIZE) { pwr += PWR_STEP; /* stop if dbM > max_power_possible */ while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) i++; /* scale by 2 and add 1 to enable round up or down as needed */ scaledPcdac = (uint16_t)(interpolate(pwr, pScaledUpDbm[i], pScaledUpDbm[i + 1], (uint16_t)(pPcdacValues[i] * 2), (uint16_t)(pPcdacValues[i + 1] * 2)) + 1); HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); ahp->ah_pcdacTable[pcdacTableIndex] = scaledPcdac / 2; if (ahp->ah_pcdacTable[pcdacTableIndex] > pcdacMax) ahp->ah_pcdacTable[pcdacTableIndex] = pcdacMax; pcdacTableIndex++; } /* Write all the last pcdac entries based off the last valid pcdac */ while (pcdacTableIndex < PWR_TABLE_SIZE) { ahp->ah_pcdacTable[pcdacTableIndex] = ahp->ah_pcdacTable[pcdacTableIndex - 1]; pcdacTableIndex++; } /* No power table adjustment for 5111 */ ahp->ah_txPowerIndexOffset = 0; return AH_TRUE;}/* * Get or interpolate the pcdac value from the calibrated data. */static uint16_tar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct){ uint16_t powerValue; uint16_t lFreq, rFreq; /* left and right frequency values */ uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ uint16_t lPwr, uPwr; /* lower and upper temp pwr values */ uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ if (ar5212FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) { /* value was copied from srcStruct */ return powerValue; } ar5212GetLowerUpperValues(channel, pSrcStruct->pChannelList, pSrcStruct->numChannels, &lFreq, &rFreq); ar5212GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct, &llPcdac, &ulPcdac); ar5212GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct, &lrPcdac, &urPcdac); /* get the power index for the pcdac value */ ar5212FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); ar5212FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); lScaledPwr = interpolate(pcdacValue, llPcdac, ulPcdac, lPwr, uPwr); ar5212FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); ar5212FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); rScaledPwr = interpolate(pcdacValue, lrPcdac, urPcdac, lPwr, uPwr); return interpolate(channel, lFreq, rFreq, lScaledPwr, rScaledPwr);}/* * Find the value from the calibrated source data struct */static HAL_BOOLar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue){ const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; int i; for (i = 0; i < pSrcStruct->numChannels; i++ ) { if (pChannelData->channelValue == channel) { const uint16_t* pPcdac = pChannelData->PcdacValues; int j; for (j = 0; j < pChannelData->numPcdacValues; j++ ) { if (*pPcdac == pcdacValue) { *powerValue = pChannelData->PwrValues[j]; return AH_TRUE; } pPcdac++; } } pChannelData++; } return AH_FALSE;}/* * Get the upper and lower pcdac given the channel and the pcdac * used in the search */static voidar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, const PCDACS_EEPROM *pSrcStruct, uint16_t *pLowerPcdac, uint16_t *pUpperPcdac){ const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; int i; /* Find the channel information */ for (i = 0; i < pSrcStruct->numChannels; i++) { if (pChannelData->channelValue == channel) break; pChannelData++; } ar5212GetLowerUpperValues(pcdac, pChannelData->PcdacValues, pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac);}static HAL_BOOLar5111GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, int16_t *minPow){ /* XXX - Get 5111 power limits! */ /* NB: caller will cope */ return AH_FALSE;}/* * Adjust NF based on statistical values for 5GHz frequencies. */static int16_tar5111GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c){ static const struct { uint16_t freqLow; int16_t adjust; } adjust5111[] = { { 5790, 6 }, /* NB: ordered high -> low */ { 5730, 4 }, { 5690, 3 }, { 5660, 2 }, { 5610, 1 }, { 5530, 0 }, { 5450, 0 }, { 5379, 1 }, { 5209, 3 }, { 3000, 5 }, { 0, 0 }, }; int i; for (i = 0; c->channel <= adjust5111[i].freqLow; i++) ; return adjust5111[i].adjust;}/* * Free memory for analog bank scratch buffers */static voidar5111RfDetach(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); HALASSERT(ahp->ah_rfHal != AH_NULL); ath_hal_free(ahp->ah_rfHal); ahp->ah_rfHal = AH_NULL;}/* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */static HAL_BOOLar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status){ struct ath_hal_5212 *ahp = AH5212(ah); struct ar5111State *priv; HALASSERT(ah->ah_magic == AR5212_MAGIC); HALASSERT(ahp->ah_rfHal == AH_NULL); priv = ath_hal_malloc(sizeof(struct ar5111State)); if (priv == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot allocate private state\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } priv->base.rfDetach = ar5111RfDetach; priv->base.writeRegs = ar5111WriteRegs; priv->base.getRfBank = ar5111GetRfBank; priv->base.setChannel = ar5111SetChannel; priv->base.setRfRegs = ar5111SetRfRegs; priv->base.setPowerTable = ar5111SetPowerTable; priv->base.getChannelMaxMinPower = ar5111GetChannelMaxMinPower; priv->base.getNfAdjust = ar5111GetNfAdjust; ahp->ah_pcdacTable = priv->pcdacTable; ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); ahp->ah_rfHal = &priv->base; return AH_TRUE;}static HAL_BOOLar5111Probe(struct ath_hal *ah){ return IS_RAD5111(ah);}AH_RF(RF5111, ar5111Probe, ar5111RfAttach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -