|
@@ -179,6 +179,69 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void ath9k_get_txgain_index(struct ath_hw *ah,
|
|
|
+ struct ath9k_channel *chan,
|
|
|
+ struct calDataPerFreqOpLoop *rawDatasetOpLoop,
|
|
|
+ u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
|
|
|
+{
|
|
|
+ u8 pcdac, i = 0;
|
|
|
+ u16 idxL = 0, idxR = 0, numPiers;
|
|
|
+ bool match;
|
|
|
+ struct chan_centers centers;
|
|
|
+
|
|
|
+ ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
|
|
+
|
|
|
+ for (numPiers = 0; numPiers < availPiers; numPiers++)
|
|
|
+ if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
|
|
|
+ break;
|
|
|
+
|
|
|
+ match = ath9k_hw_get_lower_upper_index(
|
|
|
+ (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
|
|
|
+ calChans, numPiers, &idxL, &idxR);
|
|
|
+ if (match) {
|
|
|
+ pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
|
|
|
+ *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
|
|
|
+ } else {
|
|
|
+ pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
|
|
|
+ *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
|
|
|
+ rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (pcdac > ah->originalGain[i] &&
|
|
|
+ i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
|
|
|
+ i++;
|
|
|
+
|
|
|
+ *pcdacIdx = i;
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
|
|
|
+ u32 initTxGain,
|
|
|
+ int txPower,
|
|
|
+ u8 *pPDADCValues)
|
|
|
+{
|
|
|
+ u32 i;
|
|
|
+ u32 offset;
|
|
|
+
|
|
|
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
|
|
|
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
|
|
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
|
|
|
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
|
|
|
+
|
|
|
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
|
|
|
+ AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
|
|
|
+
|
|
|
+ offset = txPower;
|
|
|
+ for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
|
|
|
+ if (i < offset)
|
|
|
+ pPDADCValues[i] = 0x0;
|
|
|
+ else
|
|
|
+ pPDADCValues[i] = 0xFF;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
static void ath9k_hw_get_target_powers(struct ath_hw *ah,
|
|
|
struct ath9k_channel *chan,
|
|
|
struct cal_target_power_ht *powInfo,
|
|
@@ -1596,6 +1659,16 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
|
|
return pBase->rxGainType;
|
|
|
case EEP_TXGAIN_TYPE:
|
|
|
return pBase->txGainType;
|
|
|
+ case EEP_OL_PWRCTRL:
|
|
|
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
|
|
|
+ return pBase->openLoopPwrCntl ? true : false;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ case EEP_RC_CHAIN_MASK:
|
|
|
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
|
|
|
+ return pBase->rcChainMask;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
case EEP_DAC_HPWR_5G:
|
|
|
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
|
|
|
return pBase->dacHiPwrMode_5G;
|
|
@@ -1839,8 +1912,15 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
|
|
pModal->swSettleHt40);
|
|
|
}
|
|
|
|
|
|
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
|
|
|
+ AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
|
|
|
+ REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
|
|
|
+ AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
|
|
|
+ pModal->miscBits);
|
|
|
+
|
|
|
+
|
|
|
if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
|
|
|
- if (IS_CHAN_HT20(chan))
|
|
|
+ if (IS_CHAN_2GHZ(chan))
|
|
|
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
|
|
|
eep->baseEepHeader.dacLpMode);
|
|
|
else if (eep->baseEepHeader.dacHiPwrMode_5G)
|
|
@@ -1851,6 +1931,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
|
|
|
|
|
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
|
|
|
pModal->miscBits >> 2);
|
|
|
+
|
|
|
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
|
|
|
+ AR_PHY_TX_DESIRED_SCALE_CCK,
|
|
|
+ eep->baseEepHeader.desiredScaleCCK);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
@@ -2080,6 +2164,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
|
|
struct ath9k_channel *chan,
|
|
|
int16_t *pTxPowerIndexOffset)
|
|
|
{
|
|
|
+#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
|
|
|
+ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
|
|
+#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
|
|
|
+#define SM_PDGAIN_B(x, y) \
|
|
|
+ SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
|
|
|
+
|
|
|
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
|
|
struct cal_data_per_freq *pRawDataset;
|
|
|
u8 *pCalBChans = NULL;
|
|
@@ -2113,6 +2203,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
|
|
numPiers = AR5416_NUM_5G_CAL_PIERS;
|
|
|
}
|
|
|
|
|
|
+ if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
|
|
|
+ pRawDataset = pEepData->calPierData2G[0];
|
|
|
+ ah->initPDADC = ((struct calDataPerFreqOpLoop *)
|
|
|
+ pRawDataset)->vpdPdg[0][0];
|
|
|
+ }
|
|
|
+
|
|
|
numXpdGain = 0;
|
|
|
|
|
|
for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
|
|
@@ -2148,25 +2244,45 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
|
|
else
|
|
|
pRawDataset = pEepData->calPierData5G[i];
|
|
|
|
|
|
- ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
|
|
|
- pRawDataset, pCalBChans,
|
|
|
- numPiers, pdGainOverlap_t2,
|
|
|
- &tMinCalPower, gainBoundaries,
|
|
|
- pdadcValues, numXpdGain);
|
|
|
+
|
|
|
+ if (OLC_FOR_AR9280_20_LATER) {
|
|
|
+ u8 pcdacIdx;
|
|
|
+ u8 txPower;
|
|
|
+
|
|
|
+ ath9k_get_txgain_index(ah, chan,
|
|
|
+ (struct calDataPerFreqOpLoop *)pRawDataset,
|
|
|
+ pCalBChans, numPiers, &txPower, &pcdacIdx);
|
|
|
+ ath9k_olc_get_pdadcs(ah, pcdacIdx,
|
|
|
+ txPower/2, pdadcValues);
|
|
|
+ } else {
|
|
|
+ ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
|
|
|
+ chan, pRawDataset,
|
|
|
+ pCalBChans, numPiers,
|
|
|
+ pdGainOverlap_t2,
|
|
|
+ &tMinCalPower,
|
|
|
+ gainBoundaries,
|
|
|
+ pdadcValues,
|
|
|
+ numXpdGain);
|
|
|
+ }
|
|
|
|
|
|
if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
|
|
|
- REG_WRITE(ah,
|
|
|
- AR_PHY_TPCRG5 + regChainOffset,
|
|
|
- SM(pdGainOverlap_t2,
|
|
|
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
|
|
|
- | SM(gainBoundaries[0],
|
|
|
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
|
|
|
- | SM(gainBoundaries[1],
|
|
|
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
|
|
|
- | SM(gainBoundaries[2],
|
|
|
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
|
|
|
- | SM(gainBoundaries[3],
|
|
|
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
|
|
|
+ if (OLC_FOR_AR9280_20_LATER) {
|
|
|
+ REG_WRITE(ah,
|
|
|
+ AR_PHY_TPCRG5 + regChainOffset,
|
|
|
+ SM(0x6,
|
|
|
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
|
|
|
+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
|
|
|
+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
|
|
|
+ } else {
|
|
|
+ REG_WRITE(ah,
|
|
|
+ AR_PHY_TPCRG5 + regChainOffset,
|
|
|
+ SM(pdGainOverlap_t2,
|
|
|
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
|
|
|
+ SM_PDGAIN_B(0, 1) |
|
|
|
+ SM_PDGAIN_B(1, 2) |
|
|
|
+ SM_PDGAIN_B(2, 3) |
|
|
|
+ SM_PDGAIN_B(3, 4));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
|
|
@@ -2200,6 +2316,8 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
|
|
*pTxPowerIndexOffset = 0;
|
|
|
|
|
|
return true;
|
|
|
+#undef SM_PD_GAIN
|
|
|
+#undef SM_PDGAIN_B
|
|
|
}
|
|
|
|
|
|
static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
|
|
@@ -2500,13 +2618,14 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
|
|
u8 twiceMaxRegulatoryPower,
|
|
|
u8 powerLimit)
|
|
|
{
|
|
|
+#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
|
|
|
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
|
|
struct modal_eep_header *pModal =
|
|
|
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
|
|
|
int16_t ratesArray[Ar5416RateSize];
|
|
|
int16_t txPowerIndexOffset = 0;
|
|
|
u8 ht40PowerIncForPdadc = 2;
|
|
|
- int i;
|
|
|
+ int i, cck_ofdm_delta = 0;
|
|
|
|
|
|
memset(ratesArray, 0, sizeof(ratesArray));
|
|
|
|
|
@@ -2555,16 +2674,30 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
|
|
| ATH9K_POW_SM(ratesArray[rate24mb], 0));
|
|
|
|
|
|
if (IS_CHAN_2GHZ(chan)) {
|
|
|
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
|
|
|
- ATH9K_POW_SM(ratesArray[rate2s], 24)
|
|
|
- | ATH9K_POW_SM(ratesArray[rate2l], 16)
|
|
|
- | ATH9K_POW_SM(ratesArray[rateXr], 8)
|
|
|
- | ATH9K_POW_SM(ratesArray[rate1l], 0));
|
|
|
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
|
|
|
- ATH9K_POW_SM(ratesArray[rate11s], 24)
|
|
|
- | ATH9K_POW_SM(ratesArray[rate11l], 16)
|
|
|
- | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
|
|
|
- | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
|
|
|
+ if (OLC_FOR_AR9280_20_LATER) {
|
|
|
+ cck_ofdm_delta = 2;
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
|
|
|
+ ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
|
|
|
+ ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
|
|
|
+ } else {
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
|
|
|
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
|
|
|
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
|
|
@@ -2597,12 +2730,19 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
|
|
ht40PowerIncForPdadc, 8)
|
|
|
| ATH9K_POW_SM(ratesArray[rateHt40_4] +
|
|
|
ht40PowerIncForPdadc, 0));
|
|
|
-
|
|
|
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
|
|
|
- ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
|
|
|
- | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
|
|
|
- | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
|
|
|
- | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
|
|
|
+ if (OLC_FOR_AR9280_20_LATER) {
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
|
|
|
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
|
|
|
+ | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
|
|
|
+ } else {
|
|
|
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
|
|
|
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
|
|
|
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
|