Home | History | Annotate | Line # | Download | only in ar5212
      1  1.1  alc /*
      2  1.1  alc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  1.1  alc  * Copyright (c) 2002-2008 Atheros Communications, Inc.
      4  1.1  alc  *
      5  1.1  alc  * Permission to use, copy, modify, and/or distribute this software for any
      6  1.1  alc  * purpose with or without fee is hereby granted, provided that the above
      7  1.1  alc  * copyright notice and this permission notice appear in all copies.
      8  1.1  alc  *
      9  1.1  alc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  1.1  alc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  1.1  alc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  1.1  alc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  1.1  alc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  1.1  alc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  1.1  alc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  1.1  alc  *
     17  1.1  alc  * $Id: ar5112.c,v 1.1.1.1 2008/12/11 04:46:37 alc Exp $
     18  1.1  alc  */
     19  1.1  alc #include "opt_ah.h"
     20  1.1  alc 
     21  1.1  alc #include "ah.h"
     22  1.1  alc #include "ah_internal.h"
     23  1.1  alc 
     24  1.1  alc #include "ah_eeprom_v3.h"
     25  1.1  alc 
     26  1.1  alc #include "ar5212/ar5212.h"
     27  1.1  alc #include "ar5212/ar5212reg.h"
     28  1.1  alc #include "ar5212/ar5212phy.h"
     29  1.1  alc 
     30  1.1  alc #define AH_5212_5112
     31  1.1  alc #include "ar5212/ar5212.ini"
     32  1.1  alc 
     33  1.1  alc #define	N(a)	(sizeof(a)/sizeof(a[0]))
     34  1.1  alc 
     35  1.1  alc struct ar5112State {
     36  1.1  alc 	RF_HAL_FUNCS	base;		/* public state, must be first */
     37  1.1  alc 	uint16_t	pcdacTable[PWR_TABLE_SIZE];
     38  1.1  alc 
     39  1.1  alc 	uint32_t	Bank1Data[N(ar5212Bank1_5112)];
     40  1.1  alc 	uint32_t	Bank2Data[N(ar5212Bank2_5112)];
     41  1.1  alc 	uint32_t	Bank3Data[N(ar5212Bank3_5112)];
     42  1.1  alc 	uint32_t	Bank6Data[N(ar5212Bank6_5112)];
     43  1.1  alc 	uint32_t	Bank7Data[N(ar5212Bank7_5112)];
     44  1.1  alc };
     45  1.1  alc #define	AR5112(ah)	((struct ar5112State *) AH5212(ah)->ah_rfHal)
     46  1.1  alc 
     47  1.1  alc static	void ar5212GetLowerUpperIndex(uint16_t v,
     48  1.1  alc 		uint16_t *lp, uint16_t listSize,
     49  1.1  alc 		uint32_t *vlo, uint32_t *vhi);
     50  1.1  alc static HAL_BOOL getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs,
     51  1.1  alc 		int16_t *power, int16_t maxPower, int16_t *retVals);
     52  1.1  alc static int16_t getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4,
     53  1.1  alc 		uint16_t retVals[]);
     54  1.1  alc static int16_t getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4,
     55  1.1  alc 		int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid);
     56  1.1  alc static int16_t interpolate_signed(uint16_t target,
     57  1.1  alc 		uint16_t srcLeft, uint16_t srcRight,
     58  1.1  alc 		int16_t targetLeft, int16_t targetRight);
     59  1.1  alc 
     60  1.1  alc extern	void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
     61  1.1  alc 		uint32_t numBits, uint32_t firstBit, uint32_t column);
     62  1.1  alc 
     63  1.1  alc static void
     64  1.1  alc ar5112WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
     65  1.1  alc 	int writes)
     66  1.1  alc {
     67  1.1  alc 	HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5112, modesIndex, writes);
     68  1.1  alc 	HAL_INI_WRITE_ARRAY(ah, ar5212Common_5112, 1, writes);
     69  1.1  alc 	HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5112, freqIndex, writes);
     70  1.1  alc }
     71  1.1  alc 
     72  1.1  alc /*
     73  1.1  alc  * Take the MHz channel value and set the Channel value
     74  1.1  alc  *
     75  1.1  alc  * ASSUMES: Writes enabled to analog bus
     76  1.1  alc  */
     77  1.1  alc static HAL_BOOL
     78  1.1  alc ar5112SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
     79  1.1  alc {
     80  1.1  alc 	uint32_t channelSel  = 0;
     81  1.1  alc 	uint32_t bModeSynth  = 0;
     82  1.1  alc 	uint32_t aModeRefSel = 0;
     83  1.1  alc 	uint32_t reg32       = 0;
     84  1.1  alc 	uint16_t freq;
     85  1.1  alc 
     86  1.1  alc 	OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);
     87  1.1  alc 
     88  1.1  alc 	if (chan->channel < 4800) {
     89  1.1  alc 		uint32_t txctl;
     90  1.1  alc 
     91  1.1  alc 		if (((chan->channel - 2192) % 5) == 0) {
     92  1.1  alc 			channelSel = ((chan->channel - 672) * 2 - 3040)/10;
     93  1.1  alc 			bModeSynth = 0;
     94  1.1  alc 		} else if (((chan->channel - 2224) % 5) == 0) {
     95  1.1  alc 			channelSel = ((chan->channel - 704) * 2 - 3040) / 10;
     96  1.1  alc 			bModeSynth = 1;
     97  1.1  alc 		} else {
     98  1.1  alc 			HALDEBUG(ah, HAL_DEBUG_ANY,
     99  1.1  alc 			    "%s: invalid channel %u MHz\n",
    100  1.1  alc 			    __func__, chan->channel);
    101  1.1  alc 			return AH_FALSE;
    102  1.1  alc 		}
    103  1.1  alc 
    104  1.1  alc 		channelSel = (channelSel << 2) & 0xff;
    105  1.1  alc 		channelSel = ath_hal_reverseBits(channelSel, 8);
    106  1.1  alc 
    107  1.1  alc 		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
    108  1.1  alc 		if (chan->channel == 2484) {
    109  1.1  alc 			/* Enable channel spreading for channel 14 */
    110  1.1  alc 			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
    111  1.1  alc 				txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
    112  1.1  alc 		} else {
    113  1.1  alc 			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
    114  1.1  alc 				txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
    115  1.1  alc 		}
    116  1.1  alc 	} else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) {
    117  1.1  alc 		freq = chan->channel - 2; /* Align to even 5MHz raster */
    118  1.1  alc 		channelSel = ath_hal_reverseBits(
    119  1.1  alc 			(uint32_t)(((freq - 4800)*10)/25 + 1), 8);
    120  1.1  alc             	aModeRefSel = ath_hal_reverseBits(0, 2);
    121  1.1  alc 	} else if ((chan->channel % 20) == 0 && chan->channel >= 5120) {
    122  1.1  alc 		channelSel = ath_hal_reverseBits(
    123  1.1  alc 			((chan->channel - 4800) / 20 << 2), 8);
    124  1.1  alc 		aModeRefSel = ath_hal_reverseBits(3, 2);
    125  1.1  alc 	} else if ((chan->channel % 10) == 0) {
    126  1.1  alc 		channelSel = ath_hal_reverseBits(
    127  1.1  alc 			((chan->channel - 4800) / 10 << 1), 8);
    128  1.1  alc 		aModeRefSel = ath_hal_reverseBits(2, 2);
    129  1.1  alc 	} else if ((chan->channel % 5) == 0) {
    130  1.1  alc 		channelSel = ath_hal_reverseBits(
    131  1.1  alc 			(chan->channel - 4800) / 5, 8);
    132  1.1  alc 		aModeRefSel = ath_hal_reverseBits(1, 2);
    133  1.1  alc 	} else {
    134  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
    135  1.1  alc 		    __func__, chan->channel);
    136  1.1  alc 		return AH_FALSE;
    137  1.1  alc 	}
    138  1.1  alc 
    139  1.1  alc 	reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) |
    140  1.1  alc 			(1 << 12) | 0x1;
    141  1.1  alc 	OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff);
    142  1.1  alc 
    143  1.1  alc 	reg32 >>= 8;
    144  1.1  alc 	OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f);
    145  1.1  alc 
    146  1.1  alc 	AH_PRIVATE(ah)->ah_curchan = chan;
    147  1.1  alc 	return AH_TRUE;
    148  1.1  alc }
    149  1.1  alc 
    150  1.1  alc /*
    151  1.1  alc  * Return a reference to the requested RF Bank.
    152  1.1  alc  */
    153  1.1  alc static uint32_t *
    154  1.1  alc ar5112GetRfBank(struct ath_hal *ah, int bank)
    155  1.1  alc {
    156  1.1  alc 	struct ar5112State *priv = AR5112(ah);
    157  1.1  alc 
    158  1.1  alc 	HALASSERT(priv != AH_NULL);
    159  1.1  alc 	switch (bank) {
    160  1.1  alc 	case 1: return priv->Bank1Data;
    161  1.1  alc 	case 2: return priv->Bank2Data;
    162  1.1  alc 	case 3: return priv->Bank3Data;
    163  1.1  alc 	case 6: return priv->Bank6Data;
    164  1.1  alc 	case 7: return priv->Bank7Data;
    165  1.1  alc 	}
    166  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
    167  1.1  alc 	    __func__, bank);
    168  1.1  alc 	return AH_NULL;
    169  1.1  alc }
    170  1.1  alc 
    171  1.1  alc /*
    172  1.1  alc  * Reads EEPROM header info from device structure and programs
    173  1.1  alc  * all rf registers
    174  1.1  alc  *
    175  1.1  alc  * REQUIRES: Access to the analog rf device
    176  1.1  alc  */
    177  1.1  alc static HAL_BOOL
    178  1.1  alc ar5112SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
    179  1.1  alc 	uint16_t modesIndex, uint16_t *rfXpdGain)
    180  1.1  alc {
    181  1.1  alc #define	RF_BANK_SETUP(_priv, _ix, _col) do {				    \
    182  1.1  alc 	int i;								    \
    183  1.1  alc 	for (i = 0; i < N(ar5212Bank##_ix##_5112); i++)			    \
    184  1.1  alc 		(_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5112[i][_col];\
    185  1.1  alc } while (0)
    186  1.1  alc 	struct ath_hal_5212 *ahp = AH5212(ah);
    187  1.1  alc 	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
    188  1.1  alc 	uint16_t rfXpdSel, gainI;
    189  1.1  alc 	uint16_t ob5GHz = 0, db5GHz = 0;
    190  1.1  alc 	uint16_t ob2GHz = 0, db2GHz = 0;
    191  1.1  alc 	struct ar5112State *priv = AR5112(ah);
    192  1.1  alc 	GAIN_VALUES *gv = &ahp->ah_gainValues;
    193  1.1  alc 	int regWrites = 0;
    194  1.1  alc 
    195  1.1  alc 	HALASSERT(priv);
    196  1.1  alc 
    197  1.1  alc 	/* Setup rf parameters */
    198  1.1  alc 	switch (chan->channelFlags & CHANNEL_ALL) {
    199  1.1  alc 	case CHANNEL_A:
    200  1.1  alc 	case CHANNEL_T:
    201  1.1  alc 		if (chan->channel > 4000 && chan->channel < 5260) {
    202  1.1  alc 			ob5GHz = ee->ee_ob1;
    203  1.1  alc 			db5GHz = ee->ee_db1;
    204  1.1  alc 		} else if (chan->channel >= 5260 && chan->channel < 5500) {
    205  1.1  alc 			ob5GHz = ee->ee_ob2;
    206  1.1  alc 			db5GHz = ee->ee_db2;
    207  1.1  alc 		} else if (chan->channel >= 5500 && chan->channel < 5725) {
    208  1.1  alc 			ob5GHz = ee->ee_ob3;
    209  1.1  alc 			db5GHz = ee->ee_db3;
    210  1.1  alc 		} else if (chan->channel >= 5725) {
    211  1.1  alc 			ob5GHz = ee->ee_ob4;
    212  1.1  alc 			db5GHz = ee->ee_db4;
    213  1.1  alc 		} else {
    214  1.1  alc 			/* XXX else */
    215  1.1  alc 		}
    216  1.1  alc 		rfXpdSel = ee->ee_xpd[headerInfo11A];
    217  1.1  alc 		gainI = ee->ee_gainI[headerInfo11A];
    218  1.1  alc 		break;
    219  1.1  alc 	case CHANNEL_B:
    220  1.1  alc 		ob2GHz = ee->ee_ob2GHz[0];
    221  1.1  alc 		db2GHz = ee->ee_db2GHz[0];
    222  1.1  alc 		rfXpdSel = ee->ee_xpd[headerInfo11B];
    223  1.1  alc 		gainI = ee->ee_gainI[headerInfo11B];
    224  1.1  alc 		break;
    225  1.1  alc 	case CHANNEL_G:
    226  1.1  alc 	case CHANNEL_108G:
    227  1.1  alc 		ob2GHz = ee->ee_ob2GHz[1];
    228  1.1  alc 		db2GHz = ee->ee_ob2GHz[1];
    229  1.1  alc 		rfXpdSel = ee->ee_xpd[headerInfo11G];
    230  1.1  alc 		gainI = ee->ee_gainI[headerInfo11G];
    231  1.1  alc 		break;
    232  1.1  alc 	default:
    233  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
    234  1.1  alc 		    __func__, chan->channelFlags);
    235  1.1  alc 		return AH_FALSE;
    236  1.1  alc 	}
    237  1.1  alc 
    238  1.1  alc 	/* Setup Bank 1 Write */
    239  1.1  alc 	RF_BANK_SETUP(priv, 1, 1);
    240  1.1  alc 
    241  1.1  alc 	/* Setup Bank 2 Write */
    242  1.1  alc 	RF_BANK_SETUP(priv, 2, modesIndex);
    243  1.1  alc 
    244  1.1  alc 	/* Setup Bank 3 Write */
    245  1.1  alc 	RF_BANK_SETUP(priv, 3, modesIndex);
    246  1.1  alc 
    247  1.1  alc 	/* Setup Bank 6 Write */
    248  1.1  alc 	RF_BANK_SETUP(priv, 6, modesIndex);
    249  1.1  alc 
    250  1.1  alc 	ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdSel,     1, 302, 0);
    251  1.1  alc 
    252  1.1  alc 	ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[0], 2, 270, 0);
    253  1.1  alc 	ar5212ModifyRfBuffer(priv->Bank6Data, rfXpdGain[1], 2, 257, 0);
    254  1.1  alc 
    255  1.1  alc 	if (IS_CHAN_OFDM(chan)) {
    256  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    257  1.1  alc 			gv->currStep->paramVal[GP_PWD_138], 1, 168, 3);
    258  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    259  1.1  alc 			gv->currStep->paramVal[GP_PWD_137], 1, 169, 3);
    260  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    261  1.1  alc 			gv->currStep->paramVal[GP_PWD_136], 1, 170, 3);
    262  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    263  1.1  alc 			gv->currStep->paramVal[GP_PWD_132], 1, 174, 3);
    264  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    265  1.1  alc 			gv->currStep->paramVal[GP_PWD_131], 1, 175, 3);
    266  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data,
    267  1.1  alc 			gv->currStep->paramVal[GP_PWD_130], 1, 176, 3);
    268  1.1  alc 	}
    269  1.1  alc 
    270  1.1  alc 	/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
    271  1.1  alc 	if (IS_CHAN_2GHZ(chan)) {
    272  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 287, 0);
    273  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 290, 0);
    274  1.1  alc 	} else {
    275  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 279, 0);
    276  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 282, 0);
    277  1.1  alc 	}
    278  1.1  alc 
    279  1.1  alc 	/* Lower synth voltage for X112 Rev 2.0 only */
    280  1.1  alc 	if (IS_RADX112_REV2(ah)) {
    281  1.1  alc 		/* Non-Reversed analyg registers - so values are pre-reversed */
    282  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 90, 2);
    283  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 92, 2);
    284  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, 2, 2, 94, 2);
    285  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank6Data, 2, 1, 254, 2);
    286  1.1  alc 	}
    287  1.1  alc 
    288  1.1  alc     /* Decrease Power Consumption for 5312/5213 and up */
    289  1.1  alc     if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
    290  1.1  alc         ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 281, 1);
    291  1.1  alc         ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 1, 3);
    292  1.1  alc         ar5212ModifyRfBuffer(priv->Bank6Data, 1, 2, 3, 3);
    293  1.1  alc         ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 139, 3);
    294  1.1  alc         ar5212ModifyRfBuffer(priv->Bank6Data, 1, 1, 140, 3);
    295  1.1  alc     }
    296  1.1  alc 
    297  1.1  alc 	/* Setup Bank 7 Setup */
    298  1.1  alc 	RF_BANK_SETUP(priv, 7, modesIndex);
    299  1.1  alc 	if (IS_CHAN_OFDM(chan))
    300  1.1  alc 		ar5212ModifyRfBuffer(priv->Bank7Data,
    301  1.1  alc 			gv->currStep->paramVal[GP_MIXGAIN_OVR], 2, 37, 0);
    302  1.1  alc 
    303  1.1  alc 	ar5212ModifyRfBuffer(priv->Bank7Data, gainI, 6, 14, 0);
    304  1.1  alc 
    305  1.1  alc 	/* Adjust params for Derby TX power control */
    306  1.1  alc 	if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {
    307  1.1  alc         	uint32_t	rfDelay, rfPeriod;
    308  1.1  alc 
    309  1.1  alc         	rfDelay = 0xf;
    310  1.1  alc         	rfPeriod = (IS_CHAN_HALF_RATE(chan)) ?  0x8 : 0xf;
    311  1.1  alc         	ar5212ModifyRfBuffer(priv->Bank7Data, rfDelay, 4, 58, 0);
    312  1.1  alc         	ar5212ModifyRfBuffer(priv->Bank7Data, rfPeriod, 4, 70, 0);
    313  1.1  alc 	}
    314  1.1  alc 
    315  1.1  alc #ifdef notyet
    316  1.1  alc 	/* Analog registers are setup - EAR can modify */
    317  1.1  alc 	if (ar5212IsEarEngaged(pDev, chan))
    318  1.1  alc 		uint32_t modifier;
    319  1.1  alc 		ar5212EarModify(pDev, EAR_LC_RF_WRITE, chan, &modifier);
    320  1.1  alc #endif
    321  1.1  alc 	/* Write Analog registers */
    322  1.1  alc 	HAL_INI_WRITE_BANK(ah, ar5212Bank1_5112, priv->Bank1Data, regWrites);
    323  1.1  alc 	HAL_INI_WRITE_BANK(ah, ar5212Bank2_5112, priv->Bank2Data, regWrites);
    324  1.1  alc 	HAL_INI_WRITE_BANK(ah, ar5212Bank3_5112, priv->Bank3Data, regWrites);
    325  1.1  alc 	HAL_INI_WRITE_BANK(ah, ar5212Bank6_5112, priv->Bank6Data, regWrites);
    326  1.1  alc 	HAL_INI_WRITE_BANK(ah, ar5212Bank7_5112, priv->Bank7Data, regWrites);
    327  1.1  alc 
    328  1.1  alc 	/* Now that we have reprogrammed rfgain value, clear the flag. */
    329  1.1  alc 	ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
    330  1.1  alc 	return AH_TRUE;
    331  1.1  alc #undef	RF_BANK_SETUP
    332  1.1  alc }
    333  1.1  alc 
    334  1.1  alc /*
    335  1.1  alc  * Read the transmit power levels from the structures taken from EEPROM
    336  1.1  alc  * Interpolate read transmit power values for this channel
    337  1.1  alc  * Organize the transmit power values into a table for writing into the hardware
    338  1.1  alc  */
    339  1.1  alc static HAL_BOOL
    340  1.1  alc ar5112SetPowerTable(struct ath_hal *ah,
    341  1.1  alc 	int16_t *pPowerMin, int16_t *pPowerMax, HAL_CHANNEL_INTERNAL *chan,
    342  1.1  alc 	uint16_t *rfXpdGain)
    343  1.1  alc {
    344  1.1  alc 	struct ath_hal_5212 *ahp = AH5212(ah);
    345  1.1  alc 	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
    346  1.1  alc 	uint32_t numXpdGain = IS_RADX112_REV2(ah) ? 2 : 1;
    347  1.1  alc 	uint32_t    xpdGainMask = 0;
    348  1.1  alc 	int16_t     powerMid, *pPowerMid = &powerMid;
    349  1.1  alc 
    350  1.1  alc 	const EXPN_DATA_PER_CHANNEL_5112 *pRawCh;
    351  1.1  alc 	const EEPROM_POWER_EXPN_5112     *pPowerExpn = AH_NULL;
    352  1.1  alc 
    353  1.1  alc 	uint32_t    ii, jj, kk;
    354  1.1  alc 	int16_t     minPwr_t4, maxPwr_t4, Pmin, Pmid;
    355  1.1  alc 
    356  1.1  alc 	uint32_t    chan_idx_L = 0, chan_idx_R = 0;
    357  1.1  alc 	uint16_t    chan_L, chan_R;
    358  1.1  alc 
    359  1.1  alc 	int16_t     pwr_table0[64];
    360  1.1  alc 	int16_t     pwr_table1[64];
    361  1.1  alc 	uint16_t    pcdacs[10];
    362  1.1  alc 	int16_t     powers[10];
    363  1.1  alc 	uint16_t    numPcd;
    364  1.1  alc 	int16_t     powTableLXPD[2][64];
    365  1.1  alc 	int16_t     powTableHXPD[2][64];
    366  1.1  alc 	int16_t     tmpPowerTable[64];
    367  1.1  alc 	uint16_t    xgainList[2];
    368  1.1  alc 	uint16_t    xpdMask;
    369  1.1  alc 
    370  1.1  alc 	switch (chan->channelFlags & CHANNEL_ALL) {
    371  1.1  alc 	case CHANNEL_A:
    372  1.1  alc 	case CHANNEL_T:
    373  1.1  alc 		pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11A];
    374  1.1  alc 		xpdGainMask = ee->ee_xgain[headerInfo11A];
    375  1.1  alc 		break;
    376  1.1  alc 	case CHANNEL_B:
    377  1.1  alc 		pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11B];
    378  1.1  alc 		xpdGainMask = ee->ee_xgain[headerInfo11B];
    379  1.1  alc 		break;
    380  1.1  alc 	case CHANNEL_G:
    381  1.1  alc 	case CHANNEL_108G:
    382  1.1  alc 		pPowerExpn = &ee->ee_modePowerArray5112[headerInfo11G];
    383  1.1  alc 		xpdGainMask = ee->ee_xgain[headerInfo11G];
    384  1.1  alc 		break;
    385  1.1  alc 	default:
    386  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown channel flags 0x%x\n",
    387  1.1  alc 		    __func__, chan->channelFlags & CHANNEL_ALL);
    388  1.1  alc 		return AH_FALSE;
    389  1.1  alc 	}
    390  1.1  alc 
    391  1.1  alc 	if ((xpdGainMask & pPowerExpn->xpdMask) < 1) {
    392  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
    393  1.1  alc 		    "%s: desired xpdGainMask 0x%x not supported by "
    394  1.1  alc 		    "calibrated xpdMask 0x%x\n", __func__,
    395  1.1  alc 		    xpdGainMask, pPowerExpn->xpdMask);
    396  1.1  alc 		return AH_FALSE;
    397  1.1  alc 	}
    398  1.1  alc 
    399  1.1  alc 	maxPwr_t4 = (int16_t)(2*(*pPowerMax));	/* pwr_t2 -> pwr_t4 */
    400  1.1  alc 	minPwr_t4 = (int16_t)(2*(*pPowerMin));	/* pwr_t2 -> pwr_t4 */
    401  1.1  alc 
    402  1.1  alc 	xgainList[0] = 0xDEAD;
    403  1.1  alc 	xgainList[1] = 0xDEAD;
    404  1.1  alc 
    405  1.1  alc 	kk = 0;
    406  1.1  alc 	xpdMask = pPowerExpn->xpdMask;
    407  1.1  alc 	for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
    408  1.1  alc 		if (((xpdMask >> jj) & 1) > 0) {
    409  1.1  alc 			if (kk > 1) {
    410  1.1  alc 				HALDEBUG(ah, HAL_DEBUG_ANY,
    411  1.1  alc 				    "A maximum of 2 xpdGains supported"
    412  1.1  alc 				    "in pExpnPower data\n");
    413  1.1  alc 				return AH_FALSE;
    414  1.1  alc 			}
    415  1.1  alc 			xgainList[kk++] = (uint16_t)jj;
    416  1.1  alc 		}
    417  1.1  alc 	}
    418  1.1  alc 
    419  1.1  alc 	ar5212GetLowerUpperIndex(chan->channel, &pPowerExpn->pChannels[0],
    420  1.1  alc 		pPowerExpn->numChannels, &chan_idx_L, &chan_idx_R);
    421  1.1  alc 
    422  1.1  alc 	kk = 0;
    423  1.1  alc 	for (ii = chan_idx_L; ii <= chan_idx_R; ii++) {
    424  1.1  alc 		pRawCh = &(pPowerExpn->pDataPerChannel[ii]);
    425  1.1  alc 		if (xgainList[1] == 0xDEAD) {
    426  1.1  alc 			jj = xgainList[0];
    427  1.1  alc 			numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
    428  1.1  alc 			OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
    429  1.1  alc 				numPcd * sizeof(uint16_t));
    430  1.1  alc 			OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0],
    431  1.1  alc 				numPcd * sizeof(int16_t));
    432  1.1  alc 			if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
    433  1.1  alc 				pRawCh->maxPower_t4, &tmpPowerTable[0])) {
    434  1.1  alc 				return AH_FALSE;
    435  1.1  alc 			}
    436  1.1  alc 			OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0],
    437  1.1  alc 				64*sizeof(int16_t));
    438  1.1  alc 		} else {
    439  1.1  alc 			jj = xgainList[0];
    440  1.1  alc 			numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
    441  1.1  alc 			OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
    442  1.1  alc 				numPcd*sizeof(uint16_t));
    443  1.1  alc 			OS_MEMCPY(&powers[0],
    444  1.1  alc 				&pRawCh->pDataPerXPD[jj].pwr_t4[0],
    445  1.1  alc 				numPcd*sizeof(int16_t));
    446  1.1  alc 			if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
    447  1.1  alc 				pRawCh->maxPower_t4, &tmpPowerTable[0])) {
    448  1.1  alc 				return AH_FALSE;
    449  1.1  alc 			}
    450  1.1  alc 			OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0],
    451  1.1  alc 				64 * sizeof(int16_t));
    452  1.1  alc 
    453  1.1  alc 			jj = xgainList[1];
    454  1.1  alc 			numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;
    455  1.1  alc 			OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],
    456  1.1  alc 				numPcd * sizeof(uint16_t));
    457  1.1  alc 			OS_MEMCPY(&powers[0],
    458  1.1  alc 				&pRawCh->pDataPerXPD[jj].pwr_t4[0],
    459  1.1  alc 				numPcd * sizeof(int16_t));
    460  1.1  alc 			if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],
    461  1.1  alc 				pRawCh->maxPower_t4, &tmpPowerTable[0])) {
    462  1.1  alc 				return AH_FALSE;
    463  1.1  alc 			}
    464  1.1  alc 			OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0],
    465  1.1  alc 				64 * sizeof(int16_t));
    466  1.1  alc 		}
    467  1.1  alc 		kk++;
    468  1.1  alc 	}
    469  1.1  alc 
    470  1.1  alc 	chan_L = pPowerExpn->pChannels[chan_idx_L];
    471  1.1  alc 	chan_R = pPowerExpn->pChannels[chan_idx_R];
    472  1.1  alc 	kk = chan_idx_R - chan_idx_L;
    473  1.1  alc 
    474  1.1  alc 	if (xgainList[1] == 0xDEAD) {
    475  1.1  alc 		for (jj = 0; jj < 64; jj++) {
    476  1.1  alc 			pwr_table0[jj] = interpolate_signed(
    477  1.1  alc 				chan->channel, chan_L, chan_R,
    478  1.1  alc 				powTableLXPD[0][jj], powTableLXPD[kk][jj]);
    479  1.1  alc 		}
    480  1.1  alc 		Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0],
    481  1.1  alc 				ahp->ah_pcdacTable);
    482  1.1  alc 		*pPowerMin = (int16_t) (Pmin / 2);
    483  1.1  alc 		*pPowerMid = (int16_t) (pwr_table0[63] / 2);
    484  1.1  alc 		*pPowerMax = (int16_t) (pwr_table0[63] / 2);
    485  1.1  alc 		rfXpdGain[0] = xgainList[0];
    486  1.1  alc 		rfXpdGain[1] = rfXpdGain[0];
    487  1.1  alc 	} else {
    488  1.1  alc 		for (jj = 0; jj < 64; jj++) {
    489  1.1  alc 			pwr_table0[jj] = interpolate_signed(
    490  1.1  alc 				chan->channel, chan_L, chan_R,
    491  1.1  alc 				powTableLXPD[0][jj], powTableLXPD[kk][jj]);
    492  1.1  alc 			pwr_table1[jj] = interpolate_signed(
    493  1.1  alc 				chan->channel, chan_L, chan_R,
    494  1.1  alc 				powTableHXPD[0][jj], powTableHXPD[kk][jj]);
    495  1.1  alc 		}
    496  1.1  alc 		if (numXpdGain == 2) {
    497  1.1  alc 			Pmin = getPminAndPcdacTableFromTwoPowerTables(
    498  1.1  alc 				&pwr_table0[0], &pwr_table1[0],
    499  1.1  alc 				ahp->ah_pcdacTable, &Pmid);
    500  1.1  alc 			*pPowerMin = (int16_t) (Pmin / 2);
    501  1.1  alc 			*pPowerMid = (int16_t) (Pmid / 2);
    502  1.1  alc 			*pPowerMax = (int16_t) (pwr_table0[63] / 2);
    503  1.1  alc 			rfXpdGain[0] = xgainList[0];
    504  1.1  alc 			rfXpdGain[1] = xgainList[1];
    505  1.1  alc 		} else if (minPwr_t4 <= pwr_table1[63] &&
    506  1.1  alc 			   maxPwr_t4 <= pwr_table1[63]) {
    507  1.1  alc 			Pmin = getPminAndPcdacTableFromPowerTable(
    508  1.1  alc 				&pwr_table1[0], ahp->ah_pcdacTable);
    509  1.1  alc 			rfXpdGain[0] = xgainList[1];
    510  1.1  alc 			rfXpdGain[1] = rfXpdGain[0];
    511  1.1  alc 			*pPowerMin = (int16_t) (Pmin / 2);
    512  1.1  alc 			*pPowerMid = (int16_t) (pwr_table1[63] / 2);
    513  1.1  alc 			*pPowerMax = (int16_t) (pwr_table1[63] / 2);
    514  1.1  alc 		} else {
    515  1.1  alc 			Pmin = getPminAndPcdacTableFromPowerTable(
    516  1.1  alc 				&pwr_table0[0], ahp->ah_pcdacTable);
    517  1.1  alc 			rfXpdGain[0] = xgainList[0];
    518  1.1  alc 			rfXpdGain[1] = rfXpdGain[0];
    519  1.1  alc 			*pPowerMin = (int16_t) (Pmin/2);
    520  1.1  alc 			*pPowerMid = (int16_t) (pwr_table0[63] / 2);
    521  1.1  alc 			*pPowerMax = (int16_t) (pwr_table0[63] / 2);
    522  1.1  alc 		}
    523  1.1  alc 	}
    524  1.1  alc 
    525  1.1  alc 	/*
    526  1.1  alc 	 * Move 5112 rates to match power tables where the max
    527  1.1  alc 	 * power table entry corresponds with maxPower.
    528  1.1  alc 	 */
    529  1.1  alc 	HALASSERT(*pPowerMax <= PCDAC_STOP);
    530  1.1  alc 	ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax;
    531  1.1  alc 
    532  1.1  alc 	return AH_TRUE;
    533  1.1  alc }
    534  1.1  alc 
    535  1.1  alc /*
    536  1.1  alc  * Returns interpolated or the scaled up interpolated value
    537  1.1  alc  */
    538  1.1  alc static int16_t
    539  1.1  alc interpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
    540  1.1  alc 	int16_t targetLeft, int16_t targetRight)
    541  1.1  alc {
    542  1.1  alc 	int16_t rv;
    543  1.1  alc 
    544  1.1  alc 	if (srcRight != srcLeft) {
    545  1.1  alc 		rv = ((target - srcLeft)*targetRight +
    546  1.1  alc 		      (srcRight - target)*targetLeft) / (srcRight - srcLeft);
    547  1.1  alc 	} else {
    548  1.1  alc 		rv = targetLeft;
    549  1.1  alc 	}
    550  1.1  alc 	return rv;
    551  1.1  alc }
    552  1.1  alc 
    553  1.1  alc /*
    554  1.1  alc  * Return indices surrounding the value in sorted integer lists.
    555  1.1  alc  *
    556  1.1  alc  * NB: the input list is assumed to be sorted in ascending order
    557  1.1  alc  */
    558  1.1  alc static void
    559  1.1  alc ar5212GetLowerUpperIndex(uint16_t v, uint16_t *lp, uint16_t listSize,
    560  1.1  alc                           uint32_t *vlo, uint32_t *vhi)
    561  1.1  alc {
    562  1.1  alc 	uint32_t target = v;
    563  1.1  alc 	uint16_t *ep = lp+listSize;
    564  1.1  alc 	uint16_t *tp;
    565  1.1  alc 
    566  1.1  alc 	/*
    567  1.1  alc 	 * Check first and last elements for out-of-bounds conditions.
    568  1.1  alc 	 */
    569  1.1  alc 	if (target < lp[0]) {
    570  1.1  alc 		*vlo = *vhi = 0;
    571  1.1  alc 		return;
    572  1.1  alc 	}
    573  1.1  alc 	if (target >= ep[-1]) {
    574  1.1  alc 		*vlo = *vhi = listSize - 1;
    575  1.1  alc 		return;
    576  1.1  alc 	}
    577  1.1  alc 
    578  1.1  alc 	/* look for value being near or between 2 values in list */
    579  1.1  alc 	for (tp = lp; tp < ep; tp++) {
    580  1.1  alc 		/*
    581  1.1  alc 		 * If value is close to the current value of the list
    582  1.1  alc 		 * then target is not between values, it is one of the values
    583  1.1  alc 		 */
    584  1.1  alc 		if (*tp == target) {
    585  1.1  alc 			*vlo = *vhi = tp - lp;
    586  1.1  alc 			return;
    587  1.1  alc 		}
    588  1.1  alc 		/*
    589  1.1  alc 		 * Look for value being between current value and next value
    590  1.1  alc 		 * if so return these 2 values
    591  1.1  alc 		 */
    592  1.1  alc 		if (target < tp[1]) {
    593  1.1  alc 			*vlo = tp - lp;
    594  1.1  alc 			*vhi = *vlo + 1;
    595  1.1  alc 			return;
    596  1.1  alc 		}
    597  1.1  alc 	}
    598  1.1  alc }
    599  1.1  alc 
    600  1.1  alc static HAL_BOOL
    601  1.1  alc getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals)
    602  1.1  alc {
    603  1.1  alc 	uint16_t    ii;
    604  1.1  alc 	uint16_t    idxL = 0;
    605  1.1  alc 	uint16_t    idxR = 1;
    606  1.1  alc 
    607  1.1  alc 	if (numPcdacs < 2) {
    608  1.1  alc 		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
    609  1.1  alc 		     "%s: at least 2 pcdac values needed [%d]\n",
    610  1.1  alc 		     __func__, numPcdacs);
    611  1.1  alc 		return AH_FALSE;
    612  1.1  alc 	}
    613  1.1  alc 	for (ii = 0; ii < 64; ii++) {
    614  1.1  alc 		if (ii>pcdacs[idxR] && idxR < numPcdacs-1) {
    615  1.1  alc 			idxL++;
    616  1.1  alc 			idxR++;
    617  1.1  alc 		}
    618  1.1  alc 		retVals[ii] = interpolate_signed(ii,
    619  1.1  alc 			pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]);
    620  1.1  alc 		if (retVals[ii] >= maxPower) {
    621  1.1  alc 			while (ii < 64)
    622  1.1  alc 				retVals[ii++] = maxPower;
    623  1.1  alc 		}
    624  1.1  alc 	}
    625  1.1  alc 	return AH_TRUE;
    626  1.1  alc }
    627  1.1  alc 
    628  1.1  alc /*
    629  1.1  alc  * Takes a single calibration curve and creates a power table.
    630  1.1  alc  * Adjusts the new power table so the max power is relative
    631  1.1  alc  * to the maximum index in the power table.
    632  1.1  alc  *
    633  1.1  alc  * WARNING: rates must be adjusted for this relative power table
    634  1.1  alc  */
    635  1.1  alc static int16_t
    636  1.1  alc getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, uint16_t retVals[])
    637  1.1  alc {
    638  1.1  alc     int16_t ii, jj, jjMax;
    639  1.1  alc     int16_t pMin, currPower, pMax;
    640  1.1  alc 
    641  1.1  alc     /* If the spread is > 31.5dB, keep the upper 31.5dB range */
    642  1.1  alc     if ((pwrTableT4[63] - pwrTableT4[0]) > 126) {
    643  1.1  alc         pMin = pwrTableT4[63] - 126;
    644  1.1  alc     } else {
    645  1.1  alc         pMin = pwrTableT4[0];
    646  1.1  alc     }
    647  1.1  alc 
    648  1.1  alc     pMax = pwrTableT4[63];
    649  1.1  alc     jjMax = 63;
    650  1.1  alc 
    651  1.1  alc     /* Search for highest pcdac 0.25dB below maxPower */
    652  1.1  alc     while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) {
    653  1.1  alc         jjMax--;
    654  1.1  alc     }
    655  1.1  alc 
    656  1.1  alc     jj = jjMax;
    657  1.1  alc     currPower = pMax;
    658  1.1  alc     for (ii = 63; ii >= 0; ii--) {
    659  1.1  alc         while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) {
    660  1.1  alc             jj--;
    661  1.1  alc         }
    662  1.1  alc         if (jj == 0) {
    663  1.1  alc             while (ii >= 0) {
    664  1.1  alc                 retVals[ii] = retVals[ii + 1];
    665  1.1  alc                 ii--;
    666  1.1  alc             }
    667  1.1  alc             break;
    668  1.1  alc         }
    669  1.1  alc         retVals[ii] = jj;
    670  1.1  alc         currPower -= 2;  // corresponds to a 0.5dB step
    671  1.1  alc     }
    672  1.1  alc     return pMin;
    673  1.1  alc }
    674  1.1  alc 
    675  1.1  alc /*
    676  1.1  alc  * Combines the XPD curves from two calibration sets into a single
    677  1.1  alc  * power table and adjusts the power table so the max power is relative
    678  1.1  alc  * to the maximum index in the power table
    679  1.1  alc  *
    680  1.1  alc  * WARNING: rates must be adjusted for this relative power table
    681  1.1  alc  */
    682  1.1  alc static int16_t
    683  1.1  alc getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4,
    684  1.1  alc 	int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid)
    685  1.1  alc {
    686  1.1  alc     int16_t     ii, jj, jjMax;
    687  1.1  alc     int16_t     pMin, pMax, currPower;
    688  1.1  alc     int16_t     *pwrTableT4;
    689  1.1  alc     uint16_t    msbFlag = 0x40;  // turns on the 7th bit of the pcdac
    690  1.1  alc 
    691  1.1  alc     /* If the spread is > 31.5dB, keep the upper 31.5dB range */
    692  1.1  alc     if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) {
    693  1.1  alc         pMin = pwrTableLXpdT4[63] - 126;
    694  1.1  alc     } else {
    695  1.1  alc         pMin = pwrTableHXpdT4[0];
    696  1.1  alc     }
    697  1.1  alc 
    698  1.1  alc     pMax = pwrTableLXpdT4[63];
    699  1.1  alc     jjMax = 63;
    700  1.1  alc     /* Search for highest pcdac 0.25dB below maxPower */
    701  1.1  alc     while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){
    702  1.1  alc         jjMax--;
    703  1.1  alc     }
    704  1.1  alc 
    705  1.1  alc     *pMid = pwrTableHXpdT4[63];
    706  1.1  alc     jj = jjMax;
    707  1.1  alc     ii = 63;
    708  1.1  alc     currPower = pMax;
    709  1.1  alc     pwrTableT4 = &(pwrTableLXpdT4[0]);
    710  1.1  alc     while (ii >= 0) {
    711  1.1  alc         if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){
    712  1.1  alc             msbFlag = 0x00;
    713  1.1  alc             pwrTableT4 = &(pwrTableHXpdT4[0]);
    714  1.1  alc             jj = 63;
    715  1.1  alc         }
    716  1.1  alc         while ((jj > 0) && (pwrTableT4[jj] >= currPower)) {
    717  1.1  alc             jj--;
    718  1.1  alc         }
    719  1.1  alc         if ((jj == 0) && (msbFlag == 0x00)) {
    720  1.1  alc             while (ii >= 0) {
    721  1.1  alc                 retVals[ii] = retVals[ii+1];
    722  1.1  alc                 ii--;
    723  1.1  alc             }
    724  1.1  alc             break;
    725  1.1  alc         }
    726  1.1  alc         retVals[ii] = jj | msbFlag;
    727  1.1  alc         currPower -= 2;  // corresponds to a 0.5dB step
    728  1.1  alc         ii--;
    729  1.1  alc     }
    730  1.1  alc     return pMin;
    731  1.1  alc }
    732  1.1  alc 
    733  1.1  alc static int16_t
    734  1.1  alc ar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data)
    735  1.1  alc {
    736  1.1  alc 	int i, minIndex;
    737  1.1  alc 	int16_t minGain,minPwr,minPcdac,retVal;
    738  1.1  alc 
    739  1.1  alc 	/* Assume NUM_POINTS_XPD0 > 0 */
    740  1.1  alc 	minGain = data->pDataPerXPD[0].xpd_gain;
    741  1.1  alc 	for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {
    742  1.1  alc 		if (data->pDataPerXPD[i].xpd_gain < minGain) {
    743  1.1  alc 			minIndex = i;
    744  1.1  alc 			minGain = data->pDataPerXPD[i].xpd_gain;
    745  1.1  alc 		}
    746  1.1  alc 	}
    747  1.1  alc 	minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];
    748  1.1  alc 	minPcdac = data->pDataPerXPD[minIndex].pcdac[0];
    749  1.1  alc 	for (i=1; i<NUM_POINTS_XPD0; i++) {
    750  1.1  alc 		if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {
    751  1.1  alc 			minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];
    752  1.1  alc 			minPcdac = data->pDataPerXPD[minIndex].pcdac[i];
    753  1.1  alc 		}
    754  1.1  alc 	}
    755  1.1  alc 	retVal = minPwr - (minPcdac*2);
    756  1.1  alc 	return(retVal);
    757  1.1  alc }
    758  1.1  alc 
    759  1.1  alc static HAL_BOOL
    760  1.1  alc ar5112GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan,
    761  1.1  alc 	int16_t *maxPow, int16_t *minPow)
    762  1.1  alc {
    763  1.1  alc 	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
    764  1.1  alc 	int numChannels=0,i,last;
    765  1.1  alc 	int totalD, totalF,totalMin;
    766  1.1  alc 	const EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;
    767  1.1  alc 	const EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;
    768  1.1  alc 
    769  1.1  alc 	*maxPow = 0;
    770  1.1  alc 	if (IS_CHAN_A(chan)) {
    771  1.1  alc 		powerArray = ee->ee_modePowerArray5112;
    772  1.1  alc 		data = powerArray[headerInfo11A].pDataPerChannel;
    773  1.1  alc 		numChannels = powerArray[headerInfo11A].numChannels;
    774  1.1  alc 	} else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {
    775  1.1  alc 		/* XXX - is this correct? Should we also use the same power for turbo G? */
    776  1.1  alc 		powerArray = ee->ee_modePowerArray5112;
    777  1.1  alc 		data = powerArray[headerInfo11G].pDataPerChannel;
    778  1.1  alc 		numChannels = powerArray[headerInfo11G].numChannels;
    779  1.1  alc 	} else if (IS_CHAN_B(chan)) {
    780  1.1  alc 		powerArray = ee->ee_modePowerArray5112;
    781  1.1  alc 		data = powerArray[headerInfo11B].pDataPerChannel;
    782  1.1  alc 		numChannels = powerArray[headerInfo11B].numChannels;
    783  1.1  alc 	} else {
    784  1.1  alc 		return (AH_TRUE);
    785  1.1  alc 	}
    786  1.1  alc 	/* Make sure the channel is in the range of the TP values
    787  1.1  alc 	 *  (freq piers)
    788  1.1  alc 	 */
    789  1.1  alc 	if (numChannels < 1)
    790  1.1  alc 		return(AH_FALSE);
    791  1.1  alc 
    792  1.1  alc 	if ((chan->channel < data[0].channelValue) ||
    793  1.1  alc 	    (chan->channel > data[numChannels-1].channelValue)) {
    794  1.1  alc 		if (chan->channel < data[0].channelValue) {
    795  1.1  alc 			*maxPow = data[0].maxPower_t4;
    796  1.1  alc 			*minPow = ar5112GetMinPower(ah, &data[0]);
    797  1.1  alc 			return(AH_TRUE);
    798  1.1  alc 		} else {
    799  1.1  alc 			*maxPow = data[numChannels - 1].maxPower_t4;
    800  1.1  alc 			*minPow = ar5112GetMinPower(ah, &data[numChannels - 1]);
    801  1.1  alc 			return(AH_TRUE);
    802  1.1  alc 		}
    803  1.1  alc 	}
    804  1.1  alc 
    805  1.1  alc 	/* Linearly interpolate the power value now */
    806  1.1  alc 	for (last=0,i=0;
    807  1.1  alc 	     (i<numChannels) && (chan->channel > data[i].channelValue);
    808  1.1  alc 	     last=i++);
    809  1.1  alc 	totalD = data[i].channelValue - data[last].channelValue;
    810  1.1  alc 	if (totalD > 0) {
    811  1.1  alc 		totalF = data[i].maxPower_t4 - data[last].maxPower_t4;
    812  1.1  alc 		*maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);
    813  1.1  alc 
    814  1.1  alc 		totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]);
    815  1.1  alc 		*minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD);
    816  1.1  alc 		return (AH_TRUE);
    817  1.1  alc 	} else {
    818  1.1  alc 		if (chan->channel == data[i].channelValue) {
    819  1.1  alc 			*maxPow = data[i].maxPower_t4;
    820  1.1  alc 			*minPow = ar5112GetMinPower(ah, &data[i]);
    821  1.1  alc 			return(AH_TRUE);
    822  1.1  alc 		} else
    823  1.1  alc 			return(AH_FALSE);
    824  1.1  alc 	}
    825  1.1  alc }
    826  1.1  alc 
    827  1.1  alc /*
    828  1.1  alc  * Free memory for analog bank scratch buffers
    829  1.1  alc  */
    830  1.1  alc static void
    831  1.1  alc ar5112RfDetach(struct ath_hal *ah)
    832  1.1  alc {
    833  1.1  alc 	struct ath_hal_5212 *ahp = AH5212(ah);
    834  1.1  alc 
    835  1.1  alc 	HALASSERT(ahp->ah_rfHal != AH_NULL);
    836  1.1  alc 	ath_hal_free(ahp->ah_rfHal);
    837  1.1  alc 	ahp->ah_rfHal = AH_NULL;
    838  1.1  alc }
    839  1.1  alc 
    840  1.1  alc /*
    841  1.1  alc  * Allocate memory for analog bank scratch buffers
    842  1.1  alc  * Scratch Buffer will be reinitialized every reset so no need to zero now
    843  1.1  alc  */
    844  1.1  alc static HAL_BOOL
    845  1.1  alc ar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status)
    846  1.1  alc {
    847  1.1  alc 	struct ath_hal_5212 *ahp = AH5212(ah);
    848  1.1  alc 	struct ar5112State *priv;
    849  1.1  alc 
    850  1.1  alc 	HALASSERT(ah->ah_magic == AR5212_MAGIC);
    851  1.1  alc 
    852  1.1  alc 	HALASSERT(ahp->ah_rfHal == AH_NULL);
    853  1.1  alc 	priv = ath_hal_malloc(sizeof(struct ar5112State));
    854  1.1  alc 	if (priv == AH_NULL) {
    855  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
    856  1.1  alc 		    "%s: cannot allocate private state\n", __func__);
    857  1.1  alc 		*status = HAL_ENOMEM;		/* XXX */
    858  1.1  alc 		return AH_FALSE;
    859  1.1  alc 	}
    860  1.1  alc 	priv->base.rfDetach		= ar5112RfDetach;
    861  1.1  alc 	priv->base.writeRegs		= ar5112WriteRegs;
    862  1.1  alc 	priv->base.getRfBank		= ar5112GetRfBank;
    863  1.1  alc 	priv->base.setChannel		= ar5112SetChannel;
    864  1.1  alc 	priv->base.setRfRegs		= ar5112SetRfRegs;
    865  1.1  alc 	priv->base.setPowerTable	= ar5112SetPowerTable;
    866  1.1  alc 	priv->base.getChannelMaxMinPower = ar5112GetChannelMaxMinPower;
    867  1.1  alc 	priv->base.getNfAdjust		= ar5212GetNfAdjust;
    868  1.1  alc 
    869  1.1  alc 	ahp->ah_pcdacTable = priv->pcdacTable;
    870  1.1  alc 	ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
    871  1.1  alc 	ahp->ah_rfHal = &priv->base;
    872  1.1  alc 
    873  1.1  alc 	return AH_TRUE;
    874  1.1  alc }
    875  1.1  alc 
    876  1.1  alc static HAL_BOOL
    877  1.1  alc ar5112Probe(struct ath_hal *ah)
    878  1.1  alc {
    879  1.1  alc 	return IS_RAD5112(ah);
    880  1.1  alc }
    881  1.1  alc AH_RF(RF5112, ar5112Probe, ar5112RfAttach);
    882