static void ar9285WriteIni(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *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 */ freqIndex = 2; if (IS_CHAN_HT40(chan)) modesIndex = 3; else if (IS_CHAN_108G(chan)) modesIndex = 5; else modesIndex = 4; /* 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); regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites); if (AR_SREV_KITE_12_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, modesIndex, regWrites); } regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if (AR_SREV_MERLIN_10_OR_LATER(ah)) { uint32_t val; val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_PCU_MISC_MODE2_HWWAR1); OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val); OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); } }
static HAL_BOOL ar2316GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, int16_t *minPow) { struct ath_hal_5212 *ahp = AH5212(ah); RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; RAW_DATA_PER_CHANNEL_2316 *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 = ar2316GetMaxPower(ah, &data[0]); *minPow = ar2316GetMinPower(ah, &data[0]); return(AH_TRUE); } else { *maxPow = ar2316GetMaxPower(ah, &data[numChannels - 1]); *minPow = ar2316GetMinPower(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 = ar2316GetMaxPower(ah, &data[i]) - ar2316GetMaxPower(ah, &data[last]); *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + ar2316GetMaxPower(ah, &data[last])*totalD)/totalD); totalMin = ar2316GetMinPower(ah, &data[i]) - ar2316GetMinPower(ah, &data[last]); *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2316GetMinPower(ah, &data[last])*totalD)/totalD); return(AH_TRUE); } else { if (chan->channel == data[i].channelValue) { *maxPow = ar2316GetMaxPower(ah, &data[i]); *minPow = ar2316GetMinPower(ah, &data[i]); return(AH_TRUE); } else return(AH_FALSE); } }
static HAL_BOOL ar2316SetPowerTable(struct ath_hal *ah, int16_t *minPower, int16_t *maxPower, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain) { struct ath_hal_5212 *ahp = AH5212(ah); const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; const RAW_DATA_STRUCT_2316 *pRawDataset = AH_NULL; uint16_t pdGainOverlap_t2; int16_t minCalPower2316_t2; uint16_t *pdadcValues = ahp->ah_pcdacTable; uint16_t gainBoundaries[4]; uint32_t reg32, regoffset; int i, numPdGainsUsed; #ifndef AH_USE_INIPDGAIN uint32_t tpcrg1; #endif HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", __func__, chan->channel,chan->channelFlags); if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; else if (IS_CHAN_B(chan)) pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; else { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: illegal mode\n", __func__); return AH_FALSE; } pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP); numPdGainsUsed = ar2316getGainBoundariesAndPdadcsForPowers(ah, chan->channel, pRawDataset, pdGainOverlap_t2, &minCalPower2316_t2,gainBoundaries, rfXpdGain, pdadcValues); HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); #ifdef AH_USE_INIPDGAIN /* * Use pd_gains curve from eeprom; Atheros always uses * the default curve from the ini file but some vendors * (e.g. Zcomax) want to override this curve and not * honoring their settings results in tx power 5dBm low. */ OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, (pRawDataset->pDataPerChannel[0].numPdGains - 1)); #else tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); switch (numPdGainsUsed) { case 3: tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); /* fall thru... */ case 2: tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); /* fall thru... */ case 1: tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); break; } #ifdef AH_DEBUG if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " "pd_gains (default 0x%x, calculated 0x%x)\n", __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); #endif OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); #endif /* * 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 (minCalPower2316_t2 != 0) ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2316_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; }
static HAL_BOOL ar2316SetPowerTable(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_2316 *pRawDataset = AH_NULL; u_int16_t pdGainOverlap_t2; int16_t minCalPower2316_t2; u_int16_t *pdadcValues = ahp->ah_pcdacTable; u_int16_t gainBoundaries[4]; u_int32_t i, reg32, regoffset; HDPRINTF(ah, HAL_DBG_RF_PARAM, "%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 { HDPRINTF(ah, HAL_DBG_RF_PARAM, "%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); ar2316getGainBoundariesAndPdadcsForPowers(ah, chan->channel, pRawDataset, pdGainOverlap_t2,&minCalPower2316_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 (minCalPower2316_t2 != 0) ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower2316_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; }
static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t *maxPow, int16_t *minPow) { #if 0 struct ath_hal_5212 *ahp = AH5212(ah); int numChannels=0,i,last; int totalD, totalF,totalMin; EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; *maxPow = 0; if (IS_CHAN_A(chan)) { powerArray = ahp->ah_modePowerArray5112; data = powerArray[headerInfo11A].pDataPerChannel; numChannels = powerArray[headerInfo11A].numChannels; } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { /* XXX - is this correct? Should we also use the same power for turbo G? */ powerArray = ahp->ah_modePowerArray5112; data = powerArray[headerInfo11G].pDataPerChannel; numChannels = powerArray[headerInfo11G].numChannels; } else if (IS_CHAN_B(chan)) { powerArray = ahp->ah_modePowerArray5112; data = powerArray[headerInfo11B].pDataPerChannel; numChannels = powerArray[headerInfo11B].numChannels; } else { return (AH_TRUE); } /* Make sure the channel is in the range of the TP values * (freq piers) */ if ((numChannels < 1) || (chan->channel < data[0].channelValue) || (chan->channel > data[numChannels-1].channelValue)) return(AH_FALSE); /* 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 = data[i].maxPower_t4 - data[last].maxPower_t4; *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); return (AH_TRUE); } else { if (chan->channel == data[i].channelValue) { *maxPow = data[i].maxPower_t4; *minPow = ar2133GetMinPower(ah, &data[i]); return(AH_TRUE); } else return(AH_FALSE); } #else *maxPow = *minPow = 0; return AH_FALSE; #endif }