Example #1
0
/*
 * Take the MHz channel value and set the Channel value
 *
 * ASSUMES: Writes enabled to analog bus
 */
static HAL_BOOL
ar2317SetChannel(struct ath_hal *ah,  const struct ieee80211_channel *chan)
{
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	uint32_t channelSel  = 0;
	uint32_t bModeSynth  = 0;
	uint32_t aModeRefSel = 0;
	uint32_t reg32       = 0;

	OS_MARK(ah, AH_MARK_SETCHANNEL, freq);

	if (freq < 4800) {
		uint32_t txctl;
		channelSel = freq - 2272 ;
		channelSel = ath_hal_reverseBits(channelSel, 8);

		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
		if (freq == 2484) {
			/* Enable channel spreading for channel 14 */
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
				txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
		} else {
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
				txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
		}
	} else if ((freq % 20) == 0 && freq >= 5120) {
		channelSel = ath_hal_reverseBits(
			((freq - 4800) / 20 << 2), 8);
		aModeRefSel = ath_hal_reverseBits(3, 2);
	} else if ((freq % 10) == 0) {
		channelSel = ath_hal_reverseBits(
			((freq - 4800) / 10 << 1), 8);
		aModeRefSel = ath_hal_reverseBits(2, 2);
	} else if ((freq % 5) == 0) {
		channelSel = ath_hal_reverseBits(
			(freq - 4800) / 5, 8);
		aModeRefSel = ath_hal_reverseBits(1, 2);
	} else {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
		    __func__, freq);
		return AH_FALSE;
	}

	reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
			(1 << 12) | 0x1;
	OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);

	reg32 >>= 8;
	OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);

	AH_PRIVATE(ah)->ah_curchan = chan;
	return AH_TRUE;
}
Example #2
0
static HAL_BOOL
ar2413SetPowerTable(struct ath_hal *ah,
	int16_t *minPower, int16_t *maxPower,
	const struct ieee80211_channel *chan, 
	uint16_t *rfXpdGain)
{
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	struct ath_hal_5212 *ahp = AH5212(ah);
	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
	const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL;
	uint16_t pdGainOverlap_t2;
	int16_t minCalPower2413_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__, freq, chan->ic_flags);

	if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan))
		pRawDataset = &ee->ee_rawDataset2413[headerInfo11G];
	else if (IEEE80211_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 = ar2413getGainBoundariesAndPdadcsForPowers(ah,
		freq, pRawDataset, pdGainOverlap_t2,
		&minCalPower2413_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 (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;
}
Example #3
0
/*
 * 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_BOOL
ar5111SetPowerTable(struct ath_hal *ah,
	int16_t *pMinPower, int16_t *pMaxPower,
	const struct ieee80211_channel *chan,
	uint16_t *rfXpdGain)
{
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	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->ic_flags & IEEE80211_CHAN_ALLTURBOFULL) {
	case IEEE80211_CHAN_A:
	case IEEE80211_CHAN_ST:
		eepromPcdacs.numChannels     = ee->ee_numChannels11a;
		eepromPcdacs.pChannelList    = ee->ee_channels11a;
		eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a;
		break;
	case IEEE80211_CHAN_B:
		eepromPcdacs.numChannels     = ee->ee_numChannels2_4;
		eepromPcdacs.pChannelList    = ee->ee_channels11b;
		eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b;
		break;
	case IEEE80211_CHAN_G:
	case IEEE80211_CHAN_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->ic_flags);
		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(freq,
			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;
}
Example #4
0
/*
 * Take the MHz channel value and set the Channel value
 *
 * ASSUMES: Writes enabled to analog bus
 */
static HAL_BOOL
ar5111SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
#define CI_2GHZ_INDEX_CORRECTION 19
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	uint32_t refClk, reg32, data2111;
	int16_t chan5111, chanIEEE;

	/*
	 * Structure to hold 11b tuning information for 5111/2111
	 * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
	 */
	typedef struct {
		uint32_t	refClkSel;	/* reference clock, 1 for 16 MHz */
		uint32_t	channelSelect;	/* P[7:4]S[3:0] bits */
		uint16_t	channel5111;	/* 11a channel for 5111 */
	} CHAN_INFO_2GHZ;

	static const CHAN_INFO_2GHZ chan2GHzData[] = {
		{ 1, 0x46, 96  },	/* 2312 -19 */
		{ 1, 0x46, 97  },	/* 2317 -18 */
		{ 1, 0x46, 98  },	/* 2322 -17 */
		{ 1, 0x46, 99  },	/* 2327 -16 */
		{ 1, 0x46, 100 },	/* 2332 -15 */
		{ 1, 0x46, 101 },	/* 2337 -14 */
		{ 1, 0x46, 102 },	/* 2342 -13 */
		{ 1, 0x46, 103 },	/* 2347 -12 */
		{ 1, 0x46, 104 },	/* 2352 -11 */
		{ 1, 0x46, 105 },	/* 2357 -10 */
		{ 1, 0x46, 106 },	/* 2362  -9 */
		{ 1, 0x46, 107 },	/* 2367  -8 */
		{ 1, 0x46, 108 },	/* 2372  -7 */
		/* index -6 to 0 are pad to make this a nolookup table */
		{ 1, 0x46, 116 },	/*       -6 */
		{ 1, 0x46, 116 },	/*       -5 */
		{ 1, 0x46, 116 },	/*       -4 */
		{ 1, 0x46, 116 },	/*       -3 */
		{ 1, 0x46, 116 },	/*       -2 */
		{ 1, 0x46, 116 },	/*       -1 */
		{ 1, 0x46, 116 },	/*        0 */
		{ 1, 0x46, 116 },	/* 2412   1 */
		{ 1, 0x46, 117 },	/* 2417   2 */
		{ 1, 0x46, 118 },	/* 2422   3 */
		{ 1, 0x46, 119 },	/* 2427   4 */
		{ 1, 0x46, 120 },	/* 2432   5 */
		{ 1, 0x46, 121 },	/* 2437   6 */
		{ 1, 0x46, 122 },	/* 2442   7 */
		{ 1, 0x46, 123 },	/* 2447   8 */
		{ 1, 0x46, 124 },	/* 2452   9 */
		{ 1, 0x46, 125 },	/* 2457  10 */
		{ 1, 0x46, 126 },	/* 2462  11 */
		{ 1, 0x46, 127 },	/* 2467  12 */
		{ 1, 0x46, 128 },	/* 2472  13 */
		{ 1, 0x44, 124 },	/* 2484  14 */
		{ 1, 0x46, 136 },	/* 2512  15 */
		{ 1, 0x46, 140 },	/* 2532  16 */
		{ 1, 0x46, 144 },	/* 2552  17 */
		{ 1, 0x46, 148 },	/* 2572  18 */
		{ 1, 0x46, 152 },	/* 2592  19 */
		{ 1, 0x46, 156 },	/* 2612  20 */
		{ 1, 0x46, 160 },	/* 2632  21 */
		{ 1, 0x46, 164 },	/* 2652  22 */
		{ 1, 0x46, 168 },	/* 2672  23 */
		{ 1, 0x46, 172 },	/* 2692  24 */
		{ 1, 0x46, 176 },	/* 2712  25 */
		{ 1, 0x46, 180 } 	/* 2732  26 */
	};

	OS_MARK(ah, AH_MARK_SETCHANNEL, freq);

	chanIEEE = chan->ic_ieee;
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		const CHAN_INFO_2GHZ* ci =
			&chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];
		uint32_t txctl;

		data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
				<< 5)
			 | (ci->refClkSel << 4);
		chan5111 = ci->channel5111;
		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
		if (freq == 2484) {
			/* Enable channel spreading for channel 14 */
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
				txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
		} else {
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
				txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
		}
	} else {
		chan5111 = chanIEEE;	/* no conversion needed */
		data2111 = 0;
	}

	/* Rest of the code is common for 5 GHz and 2.4 GHz. */
	if (chan5111 >= 145 || (chan5111 & 0x1)) {
		reg32  = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff;
		refClk = 1;
	} else {
		reg32  = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff;
		refClk = 0;
	}

	reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
	OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
	reg32 >>= 8;
	OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));

	AH_PRIVATE(ah)->ah_curchan = chan;
	return AH_TRUE;
#undef CI_2GHZ_INDEX_CORRECTION
}
Example #5
0
/*
 * Reads EEPROM header info from device structure and programs
 * all rf registers
 *
 * REQUIRES: Access to the analog rf device
 */
static HAL_BOOL
ar5111SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan,
	uint16_t modesIndex, uint16_t *rfXpdGain)
{
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	struct ath_hal_5212 *ahp = AH5212(ah);
	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
	uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI;
	uint16_t tempOB, tempDB;
	uint32_t ob2GHz, db2GHz, rfReg[NELEM(ar5212Bank6_5111)];
	int i, regWrites = 0;

	HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n",
	    __func__, chan->ic_freq, chan->ic_flags, modesIndex);

	/* Setup rf parameters */
	switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
	case IEEE80211_CHAN_A:
		if (4000 < freq && freq < 5260) {
			tempOB = ee->ee_ob1;
			tempDB = ee->ee_db1;
		} else if (5260 <= freq && freq < 5500) {
			tempOB = ee->ee_ob2;
			tempDB = ee->ee_db2;
		} else if (5500 <= freq && freq < 5725) {
			tempOB = ee->ee_ob3;
			tempDB = ee->ee_db3;
		} else if (freq >= 5725) {
			tempOB = ee->ee_ob4;
			tempDB = ee->ee_db4;
		} else {
			/* XXX when does this happen??? */
			tempOB = tempDB = 0;
		}
		ob2GHz = db2GHz = 0;

		rfXpdGainFixed = ee->ee_xgain[headerInfo11A];
		rfPloSel = ee->ee_xpd[headerInfo11A];
		rfPwdXpd = !ee->ee_xpd[headerInfo11A];
		gainI = ee->ee_gainI[headerInfo11A];
		break;
	case IEEE80211_CHAN_B:
		tempOB = ee->ee_obFor24;
		tempDB = ee->ee_dbFor24;
		ob2GHz = ee->ee_ob2GHz[0];
		db2GHz = ee->ee_db2GHz[0];

		rfXpdGainFixed = ee->ee_xgain[headerInfo11B];
		rfPloSel = ee->ee_xpd[headerInfo11B];
		rfPwdXpd = !ee->ee_xpd[headerInfo11B];
		gainI = ee->ee_gainI[headerInfo11B];
		break;
	case IEEE80211_CHAN_G:
	case IEEE80211_CHAN_PUREG:	/* NB: really 108G */
		tempOB = ee->ee_obFor24g;
		tempDB = ee->ee_dbFor24g;
		ob2GHz = ee->ee_ob2GHz[1];
		db2GHz = ee->ee_db2GHz[1];

		rfXpdGainFixed = ee->ee_xgain[headerInfo11G];
		rfPloSel = ee->ee_xpd[headerInfo11G];
		rfPwdXpd = !ee->ee_xpd[headerInfo11G];
		gainI = ee->ee_gainI[headerInfo11G];
		break;
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
		    __func__, chan->ic_flags);
		return AH_FALSE;
	}

	HALASSERT(1 <= tempOB && tempOB <= 5);
	HALASSERT(1 <= tempDB && tempDB <= 5);

	/* Bank 0 Write */
	for (i = 0; i < NELEM(ar5212Bank0_5111); i++)
		rfReg[i] = ar5212Bank0_5111[i][modesIndex];
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0);
		ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0);
	}
	HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites);

	/* Bank 1 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites);

	/* Bank 2 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites);

	/* Bank 3 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites);

	/* Bank 6 Write */
	for (i = 0; i < NELEM(ar5212Bank6_5111); i++)
		rfReg[i] = ar5212Bank6_5111[i][modesIndex];
	if (IEEE80211_IS_CHAN_A(chan)) {	/* NB: CHANNEL_A | CHANNEL_T */
		ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3);
		ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3);
	}
	ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0);
	ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0);
	/* Set 5212 OB & DB */
	ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0);
	ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0);
	HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites);

	/* Bank 7 Write */
	for (i = 0; i < NELEM(ar5212Bank7_5111); i++)
		rfReg[i] = ar5212Bank7_5111[i][modesIndex];
	ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0);   
	ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0);   

	if (IEEE80211_IS_CHAN_QUARTER(chan) || IEEE80211_IS_CHAN_HALF(chan)) {
        	uint32_t	rfWaitI, rfWaitS, rfMaxTime;

        	rfWaitS = 0x1f;
        	rfWaitI = (IEEE80211_IS_CHAN_HALF(chan)) ?  0x10 : 0x1f;
        	rfMaxTime = 3;
        	ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0);
        	ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0);
        	ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0);

	}

	HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites);

	/* Now that we have reprogrammed rfgain value, clear the flag. */
	ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;

	return AH_TRUE;
}