📄 ar2413.c
字号:
u_int16_t VpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; /* filled out Vpd table for all pdGains (chanR) */ u_int16_t VpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; /* filled out Vpd table for all pdGains (interpolated) */ /* * If desired to support -ve power levels in future, just * change pwr_I_0 to signed 5-bits. */ int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; /* to accomodate -ve power levels later on. */ int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; /* to accomodate -ve power levels later on */ u_int16_t numVpd = 0; u_int16_t Vpd_step; int16_t tmpVal ; u_int32_t sizeCurrVpdTable, maxIndex, tgtIndex; HALDEBUG(ah, "==>%s:\n", __func__); /* Get upper lower index */ GetLowerUpperIndex(channel, pRawDataset->pChannels, pRawDataset->numChannels, &(idxL), &(idxR)); for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; /* work backwards 'cause highest pdGain for lowest power */ numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; if (numVpd > 0) { pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; } Pmin_t2[numPdGainsUsed] = (int16_t) (Pmin_t2[numPdGainsUsed] / 2); Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); ar2413FillVpdTable( numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L ); ar2413FillVpdTable( numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R ); for (kk = 0; kk < (u_int16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { VpdTable_I[numPdGainsUsed][kk] = interpolate_signed( channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); } /* fill VpdTable_I for this pdGain */ numPdGainsUsed++; } /* if this pdGain is used */ } *pMinCalPower = Pmin_t2[0]; kk = 0; /* index for the final table */ for (ii = 0; ii < numPdGainsUsed; ii++) { if (ii == (numPdGainsUsed - 1)) pPdGainBoundaries[ii] = Pmax_t2[ii] + PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; else pPdGainBoundaries[ii] = (u_int16_t) ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); /* Find starting index for this pdGain */ if (ii == 0) ss = 0; /* for the first pdGain, start from index 0 */ else ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - pdGainOverlap_t2; Vpd_step = (u_int16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); Vpd_step = (u_int16_t)((Vpd_step < 1) ? 1 : Vpd_step); /* *-ve ss indicates need to extrapolate data below for this pdGain */ while (ss < 0) { tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); pPDADCValues[kk++] = (u_int16_t)((tmpVal < 0) ? 0 : tmpVal); ss++; } sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; while (ss < (int16_t)maxIndex) pPDADCValues[kk++] = VpdTable_I[ii][ss++]; Vpd_step = (u_int16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - VpdTable_I[ii][sizeCurrVpdTable-2]); Vpd_step = (u_int16_t)((Vpd_step < 1) ? 1 : Vpd_step); /* * for last gain, pdGainBoundary == Pmax_t2, so will * have to extrapolate */ if (tgtIndex > maxIndex) { /* need to extrapolate above */ while(ss < (int16_t)tgtIndex) { tmpVal = (u_int16_t) (VpdTable_I[ii][sizeCurrVpdTable-1] + (ss-maxIndex)*Vpd_step); pPDADCValues[kk++] = (tmpVal > 127) ? 127 : tmpVal; ss++; } } /* extrapolated above */ } /* for all pdGainUsed */ while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; ii++; } while (kk < 128) { pPDADCValues[kk] = pPDADCValues[kk-1]; kk++; } HALDEBUG(ah, "<==%s\n", __func__);}static HAL_BOOLar2413SetPowerTable(struct ath_hal *ah, int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, u_int16_t *rfXpdGain){ struct ath_hal_5212 *ahp = AH5212(ah); RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; u_int16_t pdGainOverlap_t2; int16_t minCalPower2413_t2; u_int16_t *pdadcValues = ahp->ah_pcdacTable; u_int16_t gainBoundaries[4]; u_int32_t i, reg32, regoffset; HALDEBUG(ah, "%s:chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) pRawDataset = &ahp->ah_rawDataset2413[headerInfo11G]; else if (IS_CHAN_B(chan)) pRawDataset = &ahp->ah_rawDataset2413[headerInfo11B]; else { HALDEBUG(ah, "%s:illegal mode\n", __func__); return AH_FALSE; } pdGainOverlap_t2 = (u_int16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP); ar2413getGainBoundariesAndPdadcsForPowers(ah, chan->channel, pRawDataset, pdGainOverlap_t2,&minCalPower2413_t2,gainBoundaries, rfXpdGain, pdadcValues); OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); /* * Note the pdadc table may not start at 0 dBm power, could be * negative or greater than 0. Need to offset the power * values by the amount of minPower for griffin */ if (minCalPower2413_t2 != 0) ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2413_t2); else ahp->ah_txPowerIndexOffset = 0; /* Finally, write the power values into the baseband power table */ regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ for (i = 0; i < 32; i++) { reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | ((pdadcValues[4*i + 1] & 0xFF) << 8) | ((pdadcValues[4*i + 2] & 0xFF) << 16) | ((pdadcValues[4*i + 3] & 0xFF) << 24) ; OS_REG_WRITE(ah, regoffset, reg32); regoffset += 4; } OS_REG_WRITE(ah, AR_PHY_TPCRG5, SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); return AH_TRUE;}/* * Free memory for analog bank scratch buffers */static voidar2413RfDetach(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 int16_tar2413GetMinPower(struct ath_hal *ah, RAW_DATA_PER_CHANNEL_2413 *data){ u_int32_t ii,jj; u_int16_t Pmin=0,numVpd; for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; /* work backwards 'cause highest pdGain for lowest power */ numVpd = data->pDataPerPDGain[jj].numVpd; if (numVpd > 0) { Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; return(Pmin); } } return(Pmin);}static int16_tar2413GetMaxPower(struct ath_hal *ah, RAW_DATA_PER_CHANNEL_2413 *data){ u_int32_t ii; u_int16_t Pmax=0,numVpd; for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; if (numVpd > 0) { Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; return(Pmax); } } return(Pmax);}staticHAL_BOOL ar2413GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, int16_t *minPow){ struct ath_hal_5212 *ahp = AH5212(ah); RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; RAW_DATA_PER_CHANNEL_2413 *data=AH_NULL; u_int16_t numChannels; int totalD,totalF, totalMin,last, i; *maxPow = 0; if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) pRawDataset = &ahp->ah_rawDataset2413[headerInfo11G]; else if (IS_CHAN_B(chan)) pRawDataset = &ahp->ah_rawDataset2413[headerInfo11B]; else return(AH_FALSE); numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; /* Make sure the channel is in the range of the TP values * (freq piers) */ if (numChannels < 1) return(AH_FALSE); if ((chan->channel < data[0].channelValue) || (chan->channel > data[numChannels-1].channelValue)) { if (chan->channel < data[0].channelValue) { *maxPow = ar2413GetMaxPower(ah, &data[0]); *minPow = ar2413GetMinPower(ah, &data[0]); return(AH_TRUE); } else { *maxPow = ar2413GetMaxPower(ah, &data[numChannels - 1]); *minPow = ar2413GetMinPower(ah, &data[numChannels - 1]); return(AH_TRUE); } } /* Linearly interpolate the power value now */ for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue); last = i++); totalD = data[i].channelValue - data[last].channelValue; if (totalD > 0) { totalF = ar2413GetMaxPower(ah, &data[i]) - ar2413GetMaxPower(ah, &data[last]); *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + ar2413GetMaxPower(ah, &data[last])*totalD)/totalD); totalMin = ar2413GetMinPower(ah, &data[i]) - ar2413GetMinPower(ah, &data[last]); *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2413GetMinPower(ah, &data[last])*totalD)/totalD); return(AH_TRUE); } else { if (chan->channel == data[i].channelValue) { *maxPow = ar2413GetMaxPower(ah, &data[i]); *minPow = ar2413GetMinPower(ah, &data[i]); return(AH_TRUE); } else return(AH_FALSE); }}static HAL_BOOLar2413GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans){ HAL_BOOL retVal = AH_TRUE; int i; int16_t maxPow, minPow; for (i=0; i<nchans; i++) { if (ar2413GetChannelMaxMinPower(ah, &chans[i], &maxPow, &minPow)) { chans[i].maxTxPower = maxPow; chans[i].minTxPower = minPow; } else { HALDEBUG(ah, "Failed setting power table for nchans=%d\n", i); retVal = AH_FALSE; } }#ifdef AH_DEBUG for (i=0; i<nchans; i++) { ath_hal_printf(ah,"Chan %d: MaxPow = %d MinPow = %d\n", chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower); }#endif return (retVal);} /* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */HAL_BOOLar2413RfAttach(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_2413)); 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_2413 * 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 = ar2413RfDetach; ahp->ah_rfHal.writeRegs = ar2413WriteRegs; ahp->ah_rfHal.getRfBank = ar2413GetRfBank; ahp->ah_rfHal.setChannel = ar2413SetChannel; ahp->ah_rfHal.setRfRegs = ar2413SetRfRegs; ahp->ah_rfHal.setPowerTable = ar2413SetPowerTable; ahp->ah_rfHal.getChipPowerLim = ar2413GetChipPowerLimits; return AH_TRUE;}#endif /* AH_SUPPORT_2413 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -