📄 ar5111.c
字号:
} /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; return AH_TRUE;}/* * Returns interpolated or the scaled up interpolated value */static u_int16_tinterpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, u_int16_t targetLeft, u_int16_t targetRight){ u_int16_t rv; int16_t lRatio; /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ if ((targetLeft * targetRight) == 0) return 0; 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, u_int16_t *rfXpdGain){ struct ath_hal_5212 *ahp = AH5212(ah); FULL_PCDAC_STRUCT pcdacStruct; int i, j; u_int16_t *pPcdacValues; int16_t *pScaledUpDbm; int16_t minScaledPwr; int16_t maxScaledPwr; int16_t pwr; u_int16_t pcdacMin = 0; u_int16_t pcdacMax = PCDAC_STOP; u_int16_t pcdacTableIndex; u_int16_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: case CHANNEL_X: eepromPcdacs.numChannels = ahp->ah_numChannels11a; eepromPcdacs.pChannelList = ahp->ah_channels11a; eepromPcdacs.pDataPerChannel = ahp->ah_dataPerChannel11a; break; case CHANNEL_B: eepromPcdacs.numChannels = ahp->ah_numChannels2_4; eepromPcdacs.pChannelList = ahp->ah_channels11b; eepromPcdacs.pDataPerChannel = ahp->ah_dataPerChannel11b; break; case CHANNEL_G: case CHANNEL_108G: eepromPcdacs.numChannels = ahp->ah_numChannels2_4; eepromPcdacs.pChannelList = ahp->ah_channels11g; eepromPcdacs.pDataPerChannel = ahp->ah_dataPerChannel11g; break; default: HALDEBUG(ah, "%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 = (u_int16_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 = (u_int16_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 = (u_int16_t)(interpolate(pwr, pScaledUpDbm[i], pScaledUpDbm[i + 1], (u_int16_t)(pPcdacValues[i] * 2), (u_int16_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 u_int16_tar5212GetScaledPower(u_int16_t channel, u_int16_t pcdacValue, PCDACS_EEPROM *pSrcStruct){ u_int16_t powerValue; u_int16_t lFreq, rFreq; /* left and right frequency values */ u_int16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ u_int16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ u_int16_t lPwr, uPwr; /* lower and upper temp pwr values */ u_int16_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(u_int16_t channel, u_int16_t pcdacValue, PCDACS_EEPROM *pSrcStruct, u_int16_t *powerValue){ DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; int i; for (i = 0; i < pSrcStruct->numChannels; i++ ) { if (pChannelData->channelValue == channel) { u_int16_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(u_int16_t pcdac, u_int16_t channel, PCDACS_EEPROM *pSrcStruct, u_int16_t *pLowerPcdac, u_int16_t *pUpperPcdac){ 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);}/* * Free memory for analog bank scratch buffers */static voidar5111Detach(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); if (ahp->ah_pcdacTable != AH_NULL) { ath_hal_free(ahp->ah_pcdacTable); ahp->ah_pcdacTable = AH_NULL; } if (ahp->ah_analogBanks != AH_NULL) { ath_hal_free(ahp->ah_analogBanks); ahp->ah_analogBanks = AH_NULL; }}static HAL_BOOLar5111GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans){ /* XXX - Get 5111 power limits! */ return AH_TRUE;}/* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */HAL_BOOLar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status){ struct ath_hal_5212 *ahp = AH5212(ah); HALASSERT(ahp->ah_analogBanks == AH_NULL); ahp->ah_analogBanks = ath_hal_malloc(sizeof(AR5212_RF_BANKS_5111)); if (ahp->ah_analogBanks == AH_NULL) { HALDEBUG(ah, "%s: cannot allocate RF banks\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } HALASSERT(ahp->ah_pcdacTable == AH_NULL); ahp->ah_pcdacTableSize = PWR_TABLE_SIZE * sizeof(u_int16_t); ahp->ah_pcdacTable = ath_hal_malloc(ahp->ah_pcdacTableSize); if (ahp->ah_pcdacTable == AH_NULL) { HALDEBUG(ah, "%s: cannot allocate PCDAC table\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } ahp->ah_rfHal.rfDetach = ar5111Detach; ahp->ah_rfHal.writeRegs = ar5111WriteRegs; ahp->ah_rfHal.getRfBank = ar5111GetRfBank; ahp->ah_rfHal.setChannel = ar5111SetChannel; ahp->ah_rfHal.setRfRegs = ar5111SetRfRegs; ahp->ah_rfHal.setPowerTable = ar5111SetPowerTable; ahp->ah_rfHal.getChipPowerLim = ar5111GetChipPowerLimits; return AH_TRUE;}#endif /* AH_SUPPORT_5111 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -