ar9280_olc.c revision 219586
11541Srgrimes/* 21541Srgrimes * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. 31541Srgrimes * 41541Srgrimes * Redistribution and use in source and binary forms, with or without 51541Srgrimes * modification, are permitted provided that the following conditions 61541Srgrimes * are met: 71541Srgrimes * 1. Redistributions of source code must retain the above copyright 81541Srgrimes * notice, this list of conditions and the following disclaimer. 91541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 101541Srgrimes * notice, this list of conditions and the following disclaimer in the 111541Srgrimes * documentation and/or other materials provided with the distribution. 121541Srgrimes * 131541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 141541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 151541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 171541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 181541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 191541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 201541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 211541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 221541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 231541Srgrimes * SUCH DAMAGE. 241541Srgrimes * 251541Srgrimes * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c 219586 2011-03-13 05:54:05Z adrian $ 261541Srgrimes */ 271541Srgrimes#include "opt_ah.h" 281541Srgrimes 291541Srgrimes#include "ah.h" 301541Srgrimes#include "ah_internal.h" 311541Srgrimes 321541Srgrimes#include "ah_eeprom_v14.h" 331541Srgrimes 341541Srgrimes#include "ar9002/ar9280.h" 351541Srgrimes#include "ar5416/ar5416reg.h" 3622521Sdyson#include "ar5416/ar5416phy.h" 371541Srgrimes#include "ar9002/ar9002phy.h" 3822521Sdyson 3922521Sdyson#include "ar9002/ar9280_olc.h" 4030431Sphk 4122521Sdysonvoid 4222521Sdysonar9280olcInit(struct ath_hal *ah) 4322521Sdyson{ 4430431Sphk uint32_t i; 451541Srgrimes 461541Srgrimes for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) 471541Srgrimes AH9280(ah)->originalGain[i] = MS(OS_REG_READ(ah, 481541Srgrimes AR_PHY_TX_GAIN_TBL1 + i * 4), AR_PHY_TX_GAIN); 491541Srgrimes 501541Srgrimes AH9280(ah)->PDADCdelta = 0; 511541Srgrimes} 521541Srgrimes 531541Srgrimesvoid 541541Srgrimesar9280olcGetTxGainIndex(struct ath_hal *ah, 551541Srgrimes const struct ieee80211_channel *chan, 561541Srgrimes struct calDataPerFreqOpLoop *rawDatasetOpLoop, 571541Srgrimes uint8_t *calChans, uint16_t availPiers, uint8_t *pwr, uint8_t *pcdacIdx) 581541Srgrimes{ 591541Srgrimes uint8_t pcdac, i = 0; 601541Srgrimes uint16_t idxL = 0, idxR = 0, numPiers; 611541Srgrimes HAL_BOOL match; 621541Srgrimes CHAN_CENTERS centers; 631541Srgrimes 641541Srgrimes ar5416GetChannelCenters(ah, chan, ¢ers); 651541Srgrimes 661541Srgrimes for (numPiers = 0; numPiers < availPiers; numPiers++) 671541Srgrimes if (calChans[numPiers] == AR5416_BCHAN_UNUSED) 681541Srgrimes break; 691541Srgrimes 701541Srgrimes match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, 711541Srgrimes IEEE80211_IS_CHAN_2GHZ(chan)), calChans, numPiers, 721541Srgrimes &idxL, &idxR); 731541Srgrimes if (match) { 741541Srgrimes pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; 751541Srgrimes *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; 761541Srgrimes } else { 771541Srgrimes pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; 781541Srgrimes *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + 791541Srgrimes rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; 801541Srgrimes } 811541Srgrimes while (pcdac > AH9280(ah)->originalGain[i] && 821541Srgrimes i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) 831541Srgrimes i++; 841541Srgrimes 851541Srgrimes *pcdacIdx = i; 8626963Salex} 871541Srgrimes 881541Srgrimes/* 891541Srgrimes * XXX txPower here is likely not the target txPower in the traditional 901541Srgrimes * XXX sense, but is set by a call to ar9280olcGetTxGainIndex(). 911541Srgrimes * XXX Thus, be careful if you're trying to use this routine yourself. 921541Srgrimes */ 931541Srgrimesvoid 941541Srgrimesar9280olcGetPDADCs(struct ath_hal *ah, uint32_t initTxGain, int txPower, 951541Srgrimes uint8_t *pPDADCValues) 961541Srgrimes{ 9722521Sdyson uint32_t i; 9822521Sdyson uint32_t offset; 9922521Sdyson 10022521Sdyson OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 10122521Sdyson OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 1021541Srgrimes 10322521Sdyson OS_REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); 10422521Sdyson 10522521Sdyson offset = txPower; 10622521Sdyson for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) 10722521Sdyson if (i < offset) 10822521Sdyson pPDADCValues[i] = 0x0; 10922521Sdyson else 11022521Sdyson pPDADCValues[i] = 0xFF; 11122521Sdyson} 1121541Srgrimes 1131541Srgrimes/* 1141541Srgrimes * Run temperature compensation calibration. 1151541Srgrimes * 1161541Srgrimes * The TX gain table is adjusted depending upon the difference 1171541Srgrimes * between the initial PDADC value and the currently read 1181541Srgrimes * average TX power sample value. This value is only valid if 1191541Srgrimes * frames have been transmitted, so currPDADC will be 0 if 1201541Srgrimes * no frames have yet been transmitted. 1211541Srgrimes */ 1221541Srgrimesvoid 1231541Srgrimesar9280olcTemperatureCompensation(struct ath_hal *ah) 1241541Srgrimes{ 1251541Srgrimes uint32_t rddata, i; 1268876Srgrimes int delta, currPDADC, regval; 1271541Srgrimes uint8_t hpwr_5g = 0; 1281541Srgrimes 1291541Srgrimes rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4); 1301541Srgrimes currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 1311541Srgrimes 1321541Srgrimes HALDEBUG(ah, HAL_DEBUG_PERCAL, 1331541Srgrimes "%s: called: initPDADC=%d, currPDADC=%d\n", 1341541Srgrimes __func__, AH5416(ah)->initPDADC, currPDADC); 1351541Srgrimes 1368876Srgrimes if (AH5416(ah)->initPDADC == 0 || currPDADC == 0) 1371541Srgrimes return; 1381541Srgrimes 1391541Srgrimes (void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g)); 1401541Srgrimes 1411541Srgrimes if (hpwr_5g) 1421541Srgrimes delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8; 1431541Srgrimes else 1441541Srgrimes delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10; 1451541Srgrimes 1461541Srgrimes HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n", 1471541Srgrimes __func__, delta, AH9280(ah)->PDADCdelta); 1481541Srgrimes 1491541Srgrimes if (delta != AH9280(ah)->PDADCdelta) { 1508876Srgrimes AH9280(ah)->PDADCdelta = delta; 1511541Srgrimes for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { 1521541Srgrimes regval = AH9280(ah)->originalGain[i] - delta; 1531541Srgrimes if (regval < 0) 1541541Srgrimes regval = 0; 1551541Srgrimes 1568876Srgrimes OS_REG_RMW_FIELD(ah, 1571541Srgrimes AR_PHY_TX_GAIN_TBL1 + i * 4, 1581541Srgrimes AR_PHY_TX_GAIN, regval); 1591541Srgrimes } 1601541Srgrimes } 1611541Srgrimes} 1621541Srgrimes 1631541Srgrimes 1641541Srgrimesstatic int16_t 16526964Salexar9280ChangeGainBoundarySettings(struct ath_hal *ah, uint16_t *gb, 1661541Srgrimes uint16_t numXpdGain, uint16_t pdGainOverlap_t2, int8_t pwr_table_offset, 1671541Srgrimes int16_t *diff) 1681541Srgrimes{ 16926964Salex uint16_t k; 1701541Srgrimes 1711541Srgrimes /* Prior to writing the boundaries or the pdadc vs. power table 1721541Srgrimes * into the chip registers the default starting point on the pdadc 17326964Salex * vs. power table needs to be checked and the curve boundaries 1741541Srgrimes * adjusted accordingly 1751541Srgrimes */ 1761541Srgrimes if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 1771541Srgrimes uint16_t gb_limit; 1781541Srgrimes 1792960Swollman if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 18012769Sphk /* get the difference in dB */ 1811541Srgrimes *diff = (uint16_t)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); 1821541Srgrimes /* get the number of half dB steps */ 1831541Srgrimes *diff *= 2; 1841541Srgrimes /* change the original gain boundary settings 1851541Srgrimes * by the number of half dB steps 1861541Srgrimes */ 1871541Srgrimes for (k = 0; k < numXpdGain; k++) 18812769Sphk gb[k] = (uint16_t)(gb[k] - *diff); 18912769Sphk } 19012769Sphk /* Because of a hardware limitation, ensure the gain boundary 1911541Srgrimes * is not larger than (63 - overlap) 19222597Smpp */ 19312769Sphk gb_limit = (uint16_t)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); 19412769Sphk 19512769Sphk for (k = 0; k < numXpdGain; k++) 19622597Smpp gb[k] = (uint16_t)min(gb_limit, gb[k]); 19722597Smpp } 19812769Sphk 19912769Sphk return *diff; 20022597Smpp} 20112769Sphk 20222597Smppstatic void 20312595Sbdear9280AdjustPDADCValues(struct ath_hal *ah, int8_t pwr_table_offset, 2041541Srgrimes int16_t diff, uint8_t *pdadcValues) 2051541Srgrimes{ 2061541Srgrimes#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) 2071541Srgrimes uint16_t k; 2081541Srgrimes 2091541Srgrimes /* If this is a board that has a pwrTableOffset that differs from 2101541Srgrimes * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the 2111541Srgrimes * pdadc vs pwr table needs to be adjusted prior to writing to the 2121541Srgrimes * chip. 2131541Srgrimes */ 2141541Srgrimes if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 2151541Srgrimes if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 2161541Srgrimes /* shift the table to start at the new offset */ 2171541Srgrimes for (k = 0; k < (uint16_t)NUM_PDADC(diff); k++ ) { 2181541Srgrimes pdadcValues[k] = pdadcValues[k + diff]; 2191541Srgrimes } 2201541Srgrimes 2211541Srgrimes /* fill the back of the table */ 2221541Srgrimes for (k = (uint16_t)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { 2231541Srgrimes pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; 2241541Srgrimes } 2251541Srgrimes } 2261541Srgrimes } 2271541Srgrimes#undef NUM_PDADC 2288876Srgrimes} 22922521Sdyson/* 2301541Srgrimes * This effectively disables the gain boundaries leaving it 2311541Srgrimes * to the open-loop TX power control. 2321541Srgrimes */ 2331541Srgrimesstatic void 2341541Srgrimesar9280SetGainBoundariesOpenLoop(struct ath_hal *ah, int i, 2351541Srgrimes uint16_t pdGainOverlap_t2, uint16_t gainBoundaries[]) 2361541Srgrimes{ 2371541Srgrimes int regChainOffset; 2381541Srgrimes 2391541Srgrimes regChainOffset = ar5416GetRegChainOffset(ah, i); 2401541Srgrimes 2411541Srgrimes /* These are unused for OLC */ 2421541Srgrimes (void) pdGainOverlap_t2; 2431541Srgrimes (void) gainBoundaries; 2441541Srgrimes 2451541Srgrimes HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: chain %d: writing closed loop values\n", 2461541Srgrimes __func__, i); 2471541Srgrimes 2481541Srgrimes OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, 2491541Srgrimes SM(0x6, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 2501541Srgrimes SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 2511541Srgrimes SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 2521541Srgrimes SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 2537170Sdg SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); 2541541Srgrimes} 2551541Srgrimes 2561541Srgrimes/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ 2571541Srgrimes/* XXX shouldn't be here! */ 2581541Srgrimes#define EEP_MINOR(_ah) \ 2591541Srgrimes (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) 2601541Srgrimes#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) 2611541Srgrimes#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) 2621541Srgrimes 2631541Srgrimes/************************************************************** 2641541Srgrimes * ar9280SetPowerCalTable 2658876Srgrimes * 2661541Srgrimes * Pull the PDADC piers from cal data and interpolate them across the given 2671541Srgrimes * points as well as from the nearest pier(s) to get a power detector 2681541Srgrimes * linear voltage to power level table. 2691541Srgrimes * 2701541Srgrimes * Handle OLC for Merlin where required. 2711541Srgrimes */ 27224987SkatoHAL_BOOL 27322521Sdysonar9280SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, 27424987Skato const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) 2751541Srgrimes{ 2761541Srgrimes CAL_DATA_PER_FREQ *pRawDataset; 2771541Srgrimes uint8_t *pCalBChans = AH_NULL; 2781541Srgrimes uint16_t pdGainOverlap_t2; 2791541Srgrimes static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; 2801541Srgrimes uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 2811541Srgrimes uint16_t numPiers, i; 2821541Srgrimes int16_t tMinCalPower; 2831541Srgrimes uint16_t numXpdGain, xpdMask; 2841541Srgrimes uint16_t xpdGainValues[AR5416_NUM_PD_GAINS]; 2851541Srgrimes uint32_t regChainOffset; 2868876Srgrimes int8_t pwr_table_offset; 2871541Srgrimes 2881541Srgrimes OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); 2891541Srgrimes 2901541Srgrimes xpdMask = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].xpdGain; 2911541Srgrimes 2921541Srgrimes (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); 2931541Srgrimes 2941541Srgrimes 2951541Srgrimes if (IS_EEP_MINOR_V2(ah)) { 2961541Srgrimes pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; 2971541Srgrimes } else { 2981541Srgrimes pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 2991541Srgrimes } 3001541Srgrimes 3011541Srgrimes if (IEEE80211_IS_CHAN_2GHZ(chan)) { 3021541Srgrimes pCalBChans = pEepData->calFreqPier2G; 3031541Srgrimes numPiers = AR5416_NUM_2G_CAL_PIERS; 3041541Srgrimes } else { 3051541Srgrimes pCalBChans = pEepData->calFreqPier5G; 3061541Srgrimes numPiers = AR5416_NUM_5G_CAL_PIERS; 3071541Srgrimes } 3081541Srgrimes 3091541Srgrimes /* If OLC is being done, set the init PDADC value appropriately */ 3101541Srgrimes if (IEEE80211_IS_CHAN_2GHZ(chan) && AR_SREV_MERLIN_20_OR_LATER(ah) && 3111541Srgrimes ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { 3121541Srgrimes struct calDataPerFreq *pRawDataset = pEepData->calPierData2G[0]; 3131541Srgrimes AH5416(ah)->initPDADC = ((struct calDataPerFreqOpLoop *) pRawDataset)->vpdPdg[0][0]; 3141541Srgrimes } else { 3151541Srgrimes /* 3161541Srgrimes * XXX ath9k doesn't clear this for 5ghz mode if 3171541Srgrimes * it were set in 2ghz mode before! 3181541Srgrimes * The Merlin OLC temperature compensation code 3191541Srgrimes * uses this to calculate the PDADC delta during 3201541Srgrimes * calibration ; 0 here effectively stops the 3211541Srgrimes * temperature compensation calibration from 3221541Srgrimes * occuring. 3231541Srgrimes */ 3241541Srgrimes AH5416(ah)->initPDADC = 0; 3251541Srgrimes } 3261541Srgrimes 3271541Srgrimes /* Calculate the value of xpdgains from the xpdGain Mask */ 3281541Srgrimes numXpdGain = ar5416GetXpdGainValues(ah, xpdMask, xpdGainValues); 32929584Sphk 33029584Sphk /* Write the detector gain biases and their number */ 3311541Srgrimes ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); 3321541Srgrimes 3331541Srgrimes for (i = 0; i < AR5416_MAX_CHAINS; i++) { 3341541Srgrimes regChainOffset = ar5416GetRegChainOffset(ah, i); 3351541Srgrimes if (pEepData->baseEepHeader.txMask & (1 << i)) { 3361541Srgrimes uint16_t diff; 33722521Sdyson 33822521Sdyson if (IEEE80211_IS_CHAN_2GHZ(chan)) { 33922521Sdyson pRawDataset = pEepData->calPierData2G[i]; 34022521Sdyson } else { 34122521Sdyson pRawDataset = pEepData->calPierData5G[i]; 34222521Sdyson } 34322521Sdyson 34422521Sdyson /* Fetch the gain boundaries and the PDADC values */ 34522521Sdyson if (AR_SREV_MERLIN_20_OR_LATER(ah) && 34622521Sdyson ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { 34722521Sdyson uint8_t pcdacIdx; 34822521Sdyson uint8_t txPower; 34922521Sdyson 35022521Sdyson ar9280olcGetTxGainIndex(ah, chan, 35122521Sdyson (struct calDataPerFreqOpLoop *) pRawDataset, 35222521Sdyson pCalBChans, numPiers, &txPower, &pcdacIdx); 35322521Sdyson ar9280olcGetPDADCs(ah, pcdacIdx, txPower / 2, pdadcValues); 35422521Sdyson } else { 35522521Sdyson ar5416GetGainBoundariesAndPdadcs(ah, chan, 35622521Sdyson pRawDataset, pCalBChans, numPiers, 3571541Srgrimes pdGainOverlap_t2, &tMinCalPower, 35822521Sdyson gainBoundaries, pdadcValues, numXpdGain); 35922521Sdyson } 36022521Sdyson 36122607Smpp /* 36222521Sdyson * Prior to writing the boundaries or the pdadc vs. power table 36322521Sdyson * into the chip registers the default starting point on the pdadc 36422521Sdyson * vs. power table needs to be checked and the curve boundaries 36522521Sdyson * adjusted accordingly 36622521Sdyson */ 36722521Sdyson diff = ar9280ChangeGainBoundarySettings(ah, 36822521Sdyson gainBoundaries, numXpdGain, pdGainOverlap_t2, 36922521Sdyson pwr_table_offset, &diff); 37022521Sdyson 37122521Sdyson if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) { 37222521Sdyson /* Set gain boundaries for either open- or closed-loop TPC */ 37322521Sdyson if (AR_SREV_MERLIN_20_OR_LATER(ah) && 37422521Sdyson ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) 37522521Sdyson ar9280SetGainBoundariesOpenLoop(ah, 37622521Sdyson i, pdGainOverlap_t2, 37722521Sdyson gainBoundaries); 37822521Sdyson else 37922521Sdyson ar5416SetGainBoundariesClosedLoop(ah, 38022521Sdyson i, pdGainOverlap_t2, 38122521Sdyson gainBoundaries); 38222521Sdyson } 38322521Sdyson 38424987Skato /* 38522521Sdyson * If this is a board that has a pwrTableOffset that differs from 38622521Sdyson * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the 38722521Sdyson * pdadc vs pwr table needs to be adjusted prior to writing to the 38822521Sdyson * chip. 38922521Sdyson */ 39022521Sdyson ar9280AdjustPDADCValues(ah, pwr_table_offset, diff, pdadcValues); 39122521Sdyson 39222521Sdyson /* Write the power values into the baseband power table */ 3931541Srgrimes ar5416WritePdadcValues(ah, i, pdadcValues); 39422521Sdyson } 39522521Sdyson } 39622521Sdyson *pTxPowerIndexOffset = 0; 39722521Sdyson 39822521Sdyson return AH_TRUE; 39922521Sdyson} 40022521Sdyson