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
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to