Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 May 2011 15:01:38 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222310 - head/sys/dev/ath/ath_hal/ar9002
Message-ID:  <201105261501.p4QF1cla069356@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Thu May 26 15:01:37 2011
New Revision: 222310
URL: http://svn.freebsd.org/changeset/base/222310

Log:
  Flesh out ar9287SetTransmitPower() based on the AR9285 routine.
  
  Hard-code the per-rate TX power at 5dBm for now so testing can be done.
  
  This passes initial TX testing in 11g mode (but, obviously, at 5dBm.)

Modified:
  head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Thu May 26 14:34:22 2011	(r222309)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Thu May 26 15:01:37 2011	(r222310)
@@ -111,26 +111,136 @@ ar9287SetPowerCalTable(struct ath_hal *a
         *pTxPowerIndexOffset = 0;
 }
 
+/*
+ * Fetch the maximum TX power per rate.
+ *
+ * For now, this is hard-coded at 5dBm until this code has been ported
+ * from Atheros/ath9k and tested.
+ */
+static HAL_BOOL
+ar9285SetPowerPerRateTable(struct ath_hal *ah,
+    struct ar9287_eeprom *pEepData,
+    const struct ieee80211_channel *chan,
+    int16_t *ratesArray, uint16_t cfgCtl,
+    uint16_t AntennaReduction,
+    uint16_t twiceMaxRegulatoryPower,
+    uint16_t powerLimit)
+{
+	int i;
+
+	/* For now, set all tx power rates to 5 dBm */
+	for (i = 0; i < Ar5416RateSize; i++)
+		ratesArray[i] = 10;
+
+	return AH_TRUE;
+}
+
+/*
+ * This is based off of the AR5416/AR9285 code and likely could
+ * be unified in the future.
+ */
 HAL_BOOL
 ar9287SetTransmitPower(struct ath_hal *ah,
 	const struct ieee80211_channel *chan, uint16_t *rfXpdGain)
 {
-	int16_t txPowerIndexOffset = 0;
+#define	POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
+#define	N(a)            (sizeof (a) / sizeof (a[0]))
+
+	const struct modal_eep_ar9287_header *pModal;
+	struct ath_hal_5212 *ahp = AH5212(ah);
+	int16_t             ratesArray[Ar5416RateSize];
+	int16_t             txPowerIndexOffset = 0;
+	uint8_t             ht40PowerIncForPdadc = 2;
+	int                 i;
+
+	uint16_t            cfgCtl;
+	uint16_t            powerLimit;
+	uint16_t            twiceAntennaReduction;
+	uint16_t            twiceMaxRegulatoryPower;
+	int16_t             maxPower;
+	HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom;
+	struct ar9287_eeprom *pEepData = &ee->ee_base;
+
+	/* Setup info for the actual eeprom */
+	OS_MEMZERO(ratesArray, sizeof(ratesArray));
+	cfgCtl = ath_hal_getctl(ah, chan);
+	powerLimit = chan->ic_maxregpower * 2;
+	twiceAntennaReduction = chan->ic_maxantgain;
+	twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
+	pModal = &pEepData->modalHeader;
+	HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n",
+	    __func__,chan->ic_freq, cfgCtl );
 
-	/* XXX TODO */
+	/* XXX Assume Minor is v2 or later */
+	ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
 
 	/* Fetch per-rate power table for the given channel */
+	if (!ar9285SetPowerPerRateTable(ah, pEepData,  chan,
+            &ratesArray[0],cfgCtl,
+            twiceAntennaReduction,
+            twiceMaxRegulatoryPower, powerLimit)) {
+		HALDEBUG(ah, HAL_DEBUG_ANY,
+		    "%s: unable to set tx power per rate table\n", __func__);
+		return AH_FALSE;
+	}
 
-	/* Set open-loop TX power control calibration */
+	/* Set TX power control calibration curves for each TX chain */
 	ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset);
 
-	/* Calculate regulatory maximum power level */
+	/* Calculate maximum power level */
+	maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
+	maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+
+	if (IEEE80211_IS_CHAN_HT40(chan))
+		maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+
+	ahp->ah_tx6PowerInHalfDbm = maxPower;
+	AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower;
+	ahp->ah_txPowerIndexOffset = txPowerIndexOffset;
+
+	/*
+	 * txPowerIndexOffset is set by the SetPowerTable() call -
+	 *  adjust the rate table (0 offset if rates EEPROM not loaded)
+	 */
+	/* XXX what about the pwrTableOffset? */
+	for (i = 0; i < N(ratesArray); i++) {
+		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+		/* -5 dBm offset for Merlin and later; this includes Kiwi */
+		ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+			ratesArray[i] = AR5416_MAX_RATE_POWER;
+		if (ratesArray[i] < 0)
+			ratesArray[i] = 0;
+	}
 
-	/* Kiwi TX power starts at -5 dBm */
+#ifdef AH_EEPROM_DUMP
+	ar5416PrintPowerPerRate(ah, ratesArray);
+#endif
+
+	/*
+	 * Adjust the HT40 power to meet the correct target TX power
+	 * for 40MHz mode, based on TX power curves that are established
+	 * for 20MHz mode.
+	 *
+	 * XXX handle overflow/too high power level?
+	 */
+	if (IEEE80211_IS_CHAN_HT40(chan)) {
+		ratesArray[rateHt40_0] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_1] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_2] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_3] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_4] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_5] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_6] += ht40PowerIncForPdadc;
+		ratesArray[rateHt40_7] += ht40PowerIncForPdadc;
+	}
 
-	/* Write TX power registers */
+	/* Write the TX power rate registers */
+	ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray);
 
 	return AH_TRUE;
+#undef POW_SM
+#undef N
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105261501.p4QF1cla069356>