1219393Sadrian/* 2219393Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. 3219393Sadrian * 4219393Sadrian * Redistribution and use in source and binary forms, with or without 5219393Sadrian * modification, are permitted provided that the following conditions 6219393Sadrian * are met: 7219393Sadrian * 1. Redistributions of source code must retain the above copyright 8219393Sadrian * notice, this list of conditions and the following disclaimer. 9219393Sadrian * 2. Redistributions in binary form must reproduce the above copyright 10219393Sadrian * notice, this list of conditions and the following disclaimer in the 11219393Sadrian * documentation and/or other materials provided with the distribution. 12219393Sadrian * 13219393Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14219393Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15219393Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16219393Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17219393Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18219393Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19219393Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20219393Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21219393Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22219393Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23219393Sadrian * SUCH DAMAGE. 24219393Sadrian * 25219393Sadrian * $FreeBSD$ 26219393Sadrian */ 27219393Sadrian#include "opt_ah.h" 28219393Sadrian 29219393Sadrian#include "ah.h" 30219393Sadrian#include "ah_internal.h" 31219393Sadrian 32219393Sadrian#include "ah_eeprom_v14.h" 33219393Sadrian 34219393Sadrian#include "ar9002/ar9280.h" 35219393Sadrian#include "ar5416/ar5416reg.h" 36219393Sadrian#include "ar5416/ar5416phy.h" 37219393Sadrian#include "ar9002/ar9002phy.h" 38219393Sadrian 39219393Sadrian#include "ar9002/ar9280_olc.h" 40219393Sadrian 41219393Sadrianvoid 42219393Sadrianar9280olcInit(struct ath_hal *ah) 43219393Sadrian{ 44219393Sadrian uint32_t i; 45219393Sadrian 46221837Sadrian /* Only do OLC if it's enabled for this chipset */ 47221837Sadrian if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) 48221837Sadrian return; 49221837Sadrian 50221837Sadrian HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Setting up TX gain tables.\n", __func__); 51221837Sadrian 52219393Sadrian for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) 53219393Sadrian AH9280(ah)->originalGain[i] = MS(OS_REG_READ(ah, 54219393Sadrian AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_GAIN); 55219393Sadrian 56219393Sadrian AH9280(ah)->PDADCdelta = 0; 57219393Sadrian} 58219393Sadrian 59219393Sadrianvoid 60219393Sadrianar9280olcGetTxGainIndex(struct ath_hal *ah, 61219393Sadrian const struct ieee80211_channel *chan, 62219393Sadrian struct calDataPerFreqOpLoop *rawDatasetOpLoop, 63219393Sadrian uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx) 64219393Sadrian{ 65219393Sadrian uint8_t pcdac, i = 0; 66219393Sadrian uint16_t idxL = 0, idxR = 0, numPiers; 67219393Sadrian HAL_BOOL match; 68219393Sadrian CHAN_CENTERS centers; 69219393Sadrian 70219393Sadrian ar5416GetChannelCenters(ah, chan, ¢ers); 71219393Sadrian 72219393Sadrian for (numPiers = 0; numPiers < availPiers; numPiers++) 73219393Sadrian if (calChans[numPiers] == AR5416_BCHAN_UNUSED) 74219393Sadrian break; 75219393Sadrian 76219586Sadrian match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, 77219393Sadrian IEEE80211_IS_CHAN_2GHZ(chan)), calChans, numPiers, 78219393Sadrian &idxL, &idxR); 79219393Sadrian if (match) { 80219393Sadrian pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; 81219393Sadrian *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; 82219393Sadrian } else { 83219393Sadrian pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; 84219393Sadrian *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + 85219393Sadrian rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; 86219393Sadrian } 87219393Sadrian while (pcdac > AH9280(ah)->originalGain[i] && 88219393Sadrian i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) 89219393Sadrian i++; 90219393Sadrian 91219393Sadrian *pcdacIdx = i; 92219393Sadrian} 93219393Sadrian 94219393Sadrian/* 95219393Sadrian * XXX txPower here is likely not the target txPower in the traditional 96219393Sadrian * XXX sense, but is set by a call to ar9280olcGetTxGainIndex(). 97219393Sadrian * XXX Thus, be careful if you're trying to use this routine yourself. 98219393Sadrian */ 99219393Sadrianvoid 100219393Sadrianar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, int txPower, 101219393Sadrian uint8_t *pPDADCValues) 102219393Sadrian{ 103219393Sadrian uint32_t i; 104219393Sadrian uint32_t offset; 105219393Sadrian 106219393Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 107219393Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 108219393Sadrian 109219393Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); 110219393Sadrian 111219393Sadrian offset = txPower; 112219393Sadrian for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) 113219393Sadrian if (i < offset) 114219393Sadrian pPDADCValues[i] = 0x0; 115219393Sadrian else 116219393Sadrian pPDADCValues[i] = 0xFF; 117219393Sadrian} 118219393Sadrian 119219393Sadrian/* 120219393Sadrian * Run temperature compensation calibration. 121219393Sadrian * 122219393Sadrian * The TX gain table is adjusted depending upon the difference 123219393Sadrian * between the initial PDADC value and the currently read 124219393Sadrian * average TX power sample value. This value is only valid if 125219393Sadrian * frames have been transmitted, so currPDADC will be 0 if 126219393Sadrian * no frames have yet been transmitted. 127219393Sadrian */ 128219393Sadrianvoid 129219393Sadrianar9280olcTemperatureCompensation(struct ath_hal *ah) 130219393Sadrian{ 131219393Sadrian uint32_t rddata, i; 132219393Sadrian int delta, currPDADC, regval; 133219393Sadrian uint8_t hpwr_5g = 0; 134219393Sadrian 135221837Sadrian if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) 136221837Sadrian return; 137221837Sadrian 138219393Sadrian rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); 139219393Sadrian currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 140219393Sadrian 141219393Sadrian HALDEBUG(ah, HAL_DEBUG_PERCAL, 142219393Sadrian "%s: called: initPDADC=%d, currPDADC=%d\n", 143219393Sadrian __func__, AH5416(ah)->initPDADC, currPDADC); 144219393Sadrian 145219393Sadrian if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) 146219393Sadrian return; 147219393Sadrian 148219393Sadrian (void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g)); 149219393Sadrian 150219393Sadrian if (hpwr_5g) 151219393Sadrian delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8; 152219393Sadrian else 153219393Sadrian delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10; 154219393Sadrian 155219393Sadrian HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n", 156219393Sadrian __func__, delta, AH9280(ah)->PDADCdelta); 157219393Sadrian 158219393Sadrian if (delta != AH9280(ah)->PDADCdelta) { 159219393Sadrian AH9280(ah)->PDADCdelta = delta; 160219393Sadrian for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { 161219393Sadrian regval = AH9280(ah)->originalGain[i] - delta; 162219393Sadrian if (regval < 0) 163219393Sadrian regval = 0; 164219393Sadrian 165219393Sadrian OS_REG_RMW_FIELD(ah, 166219393Sadrian AR_PHY_TX_GAIN_TBL1 + i * 4, 167219393Sadrian AR_PHY_TX_GAIN, regval); 168219393Sadrian } 169219393Sadrian } 170219393Sadrian} 171219393Sadrian 172219444Sadrian 173219444Sadrianstatic int16_t 174219444Sadrianar9280ChangeGainBoundarySettings(struct ath_hal *ah, uint16_t *gb, 175219444Sadrian uint16_t numXpdGain, uint16_t pdGainOverlap_t2, int8_t pwr_table_offset, 176219444Sadrian int16_t *diff) 177219444Sadrian{ 178219444Sadrian uint16_t k; 179219444Sadrian 180219444Sadrian /* Prior to writing the boundaries or the pdadc vs. power table 181219444Sadrian * into the chip registers the default starting point on the pdadc 182219444Sadrian * vs. power table needs to be checked and the curve boundaries 183219444Sadrian * adjusted accordingly 184219444Sadrian */ 185219444Sadrian if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 186219444Sadrian uint16_t gb_limit; 187219444Sadrian 188219444Sadrian if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 189219444Sadrian /* get the difference in dB */ 190219444Sadrian *diff = (uint16_t)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); 191219444Sadrian /* get the number of half dB steps */ 192219444Sadrian *diff *= 2; 193219444Sadrian /* change the original gain boundary settings 194219444Sadrian * by the number of half dB steps 195219444Sadrian */ 196219444Sadrian for (k = 0; k < numXpdGain; k++) 197219444Sadrian gb[k] = (uint16_t)(gb[k] - *diff); 198219444Sadrian } 199219444Sadrian /* Because of a hardware limitation, ensure the gain boundary 200219444Sadrian * is not larger than (63 - overlap) 201219444Sadrian */ 202219444Sadrian gb_limit = (uint16_t)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); 203219444Sadrian 204219444Sadrian for (k = 0; k < numXpdGain; k++) 205219444Sadrian gb[k] = (uint16_t)min(gb_limit, gb[k]); 206219444Sadrian } 207219444Sadrian 208219444Sadrian return *diff; 209219444Sadrian} 210219444Sadrian 211219444Sadrianstatic void 212219444Sadrianar9280AdjustPDADCValues(struct ath_hal *ah, int8_t pwr_table_offset, 213219444Sadrian int16_t diff, uint8_t *pdadcValues) 214219444Sadrian{ 215219444Sadrian#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) 216219444Sadrian uint16_t k; 217219444Sadrian 218219444Sadrian /* If this is a board that has a pwrTableOffset that differs from 219219444Sadrian * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the 220219444Sadrian * pdadc vs pwr table needs to be adjusted prior to writing to the 221219444Sadrian * chip. 222219444Sadrian */ 223219444Sadrian if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 224219444Sadrian if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 225219444Sadrian /* shift the table to start at the new offset */ 226219444Sadrian for (k = 0; k < (uint16_t)NUM_PDADC(diff); k++ ) { 227219444Sadrian pdadcValues[k] = pdadcValues[k + diff]; 228219444Sadrian } 229219444Sadrian 230219444Sadrian /* fill the back of the table */ 231219444Sadrian for (k = (uint16_t)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { 232219444Sadrian pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; 233219444Sadrian } 234219444Sadrian } 235219444Sadrian } 236219444Sadrian#undef NUM_PDADC 237219444Sadrian} 238219393Sadrian/* 239219393Sadrian * This effectively disables the gain boundaries leaving it 240219393Sadrian * to the open-loop TX power control. 241219393Sadrian */ 242219393Sadrianstatic void 243219585Sadrianar9280SetGainBoundariesOpenLoop(struct ath_hal *ah, int i, 244219393Sadrian uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) 245219393Sadrian{ 246219585Sadrian int regChainOffset; 247219585Sadrian 248219585Sadrian regChainOffset = ar5416GetRegChainOffset(ah, i); 249219585Sadrian 250219393Sadrian /* These are unused for OLC */ 251219393Sadrian (void) pdGainOverlap_t2; 252219393Sadrian (void) gainBoundaries; 253219393Sadrian 254219585Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: writing closed loop values\n", 255219585Sadrian __func__, i); 256219585Sadrian 257219393Sadrian OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, 258219393Sadrian SM(0x6, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 259219393Sadrian SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 260219393Sadrian SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 261219393Sadrian SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 262219393Sadrian SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); 263219393Sadrian} 264219393Sadrian 265219393Sadrian/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ 266219393Sadrian/* XXX shouldn't be here! */ 267219393Sadrian#define EEP_MINOR(_ah) \ 268219393Sadrian (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) 269219393Sadrian#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) 270219393Sadrian#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) 271219393Sadrian 272219393Sadrian/************************************************************** 273219393Sadrian * ar9280SetPowerCalTable 274219393Sadrian * 275219393Sadrian * Pull the PDADC piers from cal data and interpolate them across the given 276219393Sadrian * points as well as from the nearest pier(s) to get a power detector 277219393Sadrian * linear voltage to power level table. 278219393Sadrian * 279219393Sadrian * Handle OLC for Merlin where required. 280219393Sadrian */ 281219393SadrianHAL_BOOL 282219393Sadrianar9280SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, 283219393Sadrian const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) 284219393Sadrian{ 285219393Sadrian CAL_DATA_PER_FREQ *pRawDataset; 286219393Sadrian uint8_t *pCalBChans = AH_NULL; 287219393Sadrian uint16_t pdGainOverlap_t2; 288219393Sadrian static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; 289219393Sadrian uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 290219393Sadrian uint16_t numPiers, i; 291219393Sadrian int16_t tMinCalPower; 292219393Sadrian uint16_t numXpdGain, xpdMask; 293219393Sadrian uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; 294219393Sadrian uint32_t regChainOffset; 295219444Sadrian int8_t pwr_table_offset; 296219393Sadrian 297219393Sadrian OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); 298219393Sadrian 299219393Sadrian xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain; 300219393Sadrian 301219444Sadrian (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); 302219444Sadrian 303219444Sadrian 304219393Sadrian if (IS_EEP_MINOR_V2(ah)) { 305219393Sadrian pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; 306219393Sadrian } else { 307219393Sadrian pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 308219393Sadrian } 309219393Sadrian 310219393Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 311219393Sadrian pCalBChans = pEepData->calFreqPier2G; 312219393Sadrian numPiers = AR5416_NUM_2G_CAL_PIERS; 313219393Sadrian } else { 314219393Sadrian pCalBChans = pEepData->calFreqPier5G; 315219393Sadrian numPiers = AR5416_NUM_5G_CAL_PIERS; 316219393Sadrian } 317219393Sadrian 318219393Sadrian /* If OLC is being done, set the init PDADC value appropriately */ 319219393Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan) && AR_SREV_MERLIN_20_OR_LATER(ah) && 320219393Sadrian ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { 321219393Sadrian struct calDataPerFreq *pRawDataset = pEepData->calPierData2G[0]; 322219393Sadrian AH5416(ah)->initPDADC = ((struct calDataPerFreqOpLoop *) pRawDataset)->vpdPdg[0][0]; 323219393Sadrian } else { 324219393Sadrian /* 325219393Sadrian * XXX ath9k doesn't clear this for 5ghz mode if 326219393Sadrian * it were set in 2ghz mode before! 327219393Sadrian * The Merlin OLC temperature compensation code 328219393Sadrian * uses this to calculate the PDADC delta during 329219393Sadrian * calibration ; 0 here effectively stops the 330219393Sadrian * temperature compensation calibration from 331219393Sadrian * occuring. 332219393Sadrian */ 333219393Sadrian AH5416(ah)->initPDADC = 0; 334219393Sadrian } 335219393Sadrian 336219393Sadrian /* Calculate the value of xpdgains from the xpdGain Mask */ 337219393Sadrian numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); 338219393Sadrian 339219393Sadrian /* Write the detector gain biases and their number */ 340219393Sadrian ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); 341219393Sadrian 342219393Sadrian for (i = 0; i < AR5416_MAX_CHAINS; i++) { 343219393Sadrian regChainOffset = ar5416GetRegChainOffset(ah, i); 344219393Sadrian if (pEepData->baseEepHeader.txMask & (1 << i)) { 345219444Sadrian uint16_t diff; 346219444Sadrian 347219393Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 348219393Sadrian pRawDataset = pEepData->calPierData2G[i]; 349219393Sadrian } else { 350219393Sadrian pRawDataset = pEepData->calPierData5G[i]; 351219393Sadrian } 352219393Sadrian 353219393Sadrian /* Fetch the gain boundaries and the PDADC values */ 354219393Sadrian if (AR_SREV_MERLIN_20_OR_LATER(ah) && 355219393Sadrian ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { 356219393Sadrian uint8_t pcdacIdx; 357219393Sadrian uint8_t txPower; 358219393Sadrian 359219393Sadrian ar9280olcGetTxGainIndex(ah, chan, 360219393Sadrian (struct calDataPerFreqOpLoop *) pRawDataset, 361219393Sadrian pCalBChans, numPiers, &txPower, &pcdacIdx); 362219393Sadrian ar9280olcGetPDADCs(ah, pcdacIdx, txPower / 2, pdadcValues); 363219393Sadrian } else { 364219393Sadrian ar5416GetGainBoundariesAndPdadcs(ah, chan, 365219393Sadrian pRawDataset, pCalBChans, numPiers, 366219393Sadrian pdGainOverlap_t2, &tMinCalPower, 367219393Sadrian gainBoundaries, pdadcValues, numXpdGain); 368219393Sadrian } 369219393Sadrian 370219393Sadrian /* 371219393Sadrian * Prior to writing the boundaries or the pdadc vs. power table 372219393Sadrian * into the chip registers the default starting point on the pdadc 373219393Sadrian * vs. power table needs to be checked and the curve boundaries 374219393Sadrian * adjusted accordingly 375219393Sadrian */ 376219444Sadrian diff = ar9280ChangeGainBoundarySettings(ah, 377219444Sadrian gainBoundaries, numXpdGain, pdGainOverlap_t2, 378219444Sadrian pwr_table_offset, &diff); 379219393Sadrian 380221574Sadrian if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { 381219393Sadrian /* Set gain boundaries for either open- or closed-loop TPC */ 382219393Sadrian if (AR_SREV_MERLIN_20_OR_LATER(ah) && 383219393Sadrian ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) 384219393Sadrian ar9280SetGainBoundariesOpenLoop(ah, 385219585Sadrian i, pdGainOverlap_t2, 386219393Sadrian gainBoundaries); 387219393Sadrian else 388219393Sadrian ar5416SetGainBoundariesClosedLoop(ah, 389219585Sadrian i, pdGainOverlap_t2, 390219393Sadrian gainBoundaries); 391219393Sadrian } 392219393Sadrian 393219393Sadrian /* 394219393Sadrian * If this is a board that has a pwrTableOffset that differs from 395219393Sadrian * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the 396219393Sadrian * pdadc vs pwr table needs to be adjusted prior to writing to the 397219393Sadrian * chip. 398219393Sadrian */ 399219444Sadrian ar9280AdjustPDADCValues(ah, pwr_table_offset, diff, pdadcValues); 400219393Sadrian 401219393Sadrian /* Write the power values into the baseband power table */ 402219585Sadrian ar5416WritePdadcValues(ah, i, pdadcValues); 403219393Sadrian } 404219393Sadrian } 405219393Sadrian *pTxPowerIndexOffset = 0; 406219393Sadrian 407219393Sadrian return AH_TRUE; 408219393Sadrian} 409