/block/

0'>81cb7623ad3b408f871fa36b774fc20d8dfccac0 (diff)
ath9k: Add open loop control support
This patch adds Open Loop Control support for Atheros chipsets that supports open loop power control. Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath9k/calib.c31
-rw-r--r--drivers/net/wireless/ath9k/eeprom.c210
-rw-r--r--drivers/net/wireless/ath9k/eeprom.h13
-rw-r--r--drivers/net/wireless/ath9k/hw.c26
-rw-r--r--drivers/net/wireless/ath9k/hw.h7
-rw-r--r--drivers/net/wireless/ath9k/phy.h25
-rw-r--r--drivers/net/wireless/ath9k/rc.c4
7 files changed, 277 insertions, 39 deletions
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c
index a7ce8c5d48f..e5abe6564ca 100644
--- a/drivers/net/wireless/ath9k/calib.c
+++ b/drivers/net/wireless/ath9k/calib.c
@@ -718,10 +718,39 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
718 return nf; 718 return nf;
719} 719}
720 720
721static void ath9k_olc_temp_compensation(struct ath_hw *ah)
722{
723 u32 rddata, i;
724 int delta, currPDADC, regval;
725
726 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
727
728 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
729
730 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
731 delta = (currPDADC - ah->initPDADC + 4) / 8;
732 else
733 delta = (currPDADC - ah->initPDADC + 5) / 10;
734
735 if (delta != ah->PDADCdelta) {
736 ah->PDADCdelta = delta;
737 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
738 regval = ah->originalGain[i] - delta;
739 if (regval < 0)
740 regval = 0;
741
742 REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
743 AR_PHY_TX_GAIN, regval);
744 }
745 }
746}
747
721bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, 748bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
722 u8 rxchainmask, bool longcal, 749 u8 rxchainmask, bool longcal,
723 bool *isCalDone) 750 bool *isCalDone)
724{ 751{
752#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
753 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
725 struct hal_cal_list *currCal = ah->cal_list_curr; 754 struct hal_cal_list *currCal = ah->cal_list_curr;
726 755
727 *isCalDone = true; 756 *isCalDone = true;
@@ -742,6 +771,8 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
742 } 771 }
743 772
744 if (longcal) { 773 if (longcal) {
774 if (OLC_FOR_AR9280_20_LATER)
775 ath9k_olc_temp_compensation(ah);
745 ath9k_hw_getnf(ah, chan); 776 ath9k_hw_getnf(ah, chan);
746 ath9k_hw_loadnf(ah, ah->curchan); 777 ath9k_hw_loadnf(ah, ah->curchan);
747 ath9k_hw_start_nfcal(ah); 778 ath9k_hw_start_nfcal(ah);
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c
index b6f9c31ddfc..fff7a1b6fbf 100644
--- a/drivers/net/wireless/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath9k/eeprom.c
@@ -179,6 +179,69 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
179 } 179 }
180} 180}
181 181
182static void ath9k_get_txgain_index(struct ath_hw *ah,
183 struct ath9k_channel *chan,
184 struct calDataPerFreqOpLoop *rawDatasetOpLoop,
185 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
186{
187 u8 pcdac, i = 0;
188 u16 idxL = 0, idxR = 0, numPiers;
189 bool match;
190 struct chan_centers centers;
191
192 ath9k_hw_get_channel_centers(ah, chan, &centers);
193
194 for (numPiers = 0; numPiers < availPiers; numPiers++)
195 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
196 break;
197
198 match = ath9k_hw_get_lower_upper_index(
199 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
200 calChans, numPiers, &idxL, &idxR);
201 if (match) {
202 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
203 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
204 } else {
205 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
206 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
207 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
208 }
209
210 while (pcdac > ah->originalGain[i] &&
211 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
212 i++;
213
214 *pcdacIdx = i;
215 return;
216}
217
218static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
219 u32 initTxGain,
220 int txPower,
221 u8 *pPDADCValues)
222{
223 u32 i;
224 u32 offset;
225
226 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
227 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
228 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
229 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
230
231 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
232 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
233
234 offset = txPower;
235 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
236 if (i < offset)
237 pPDADCValues[i] = 0x0;
238 else
239 pPDADCValues[i] = 0xFF;
240}
241
242
243
244
182static void ath9k_hw_get_target_powers(struct ath_hw *ah, 245static void ath9k_hw_get_target_powers(struct ath_hw *ah,
183 struct ath9k_channel *chan, 246 struct ath9k_channel *chan,
184 struct cal_target_power_ht *powInfo, 247 struct cal_target_power_ht *powInfo,
@@ -1596,6 +1659,16 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
1596 return pBase->rxGainType; 1659 return pBase->rxGainType;
1597 case EEP_TXGAIN_TYPE: 1660 case EEP_TXGAIN_TYPE:
1598 return pBase->txGainType; 1661 return pBase->txGainType;
1662 case EEP_OL_PWRCTRL:
1663 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1664 return pBase->openLoopPwrCntl ? true : false;
1665 else
1666 return false;
1667 case EEP_RC_CHAIN_MASK:
1668 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1669 return pBase->rcChainMask;
1670 else
1671 return 0;
1599 case EEP_DAC_HPWR_5G: 1672 case EEP_DAC_HPWR_5G:
1600 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) 1673 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
1601 return pBase->dacHiPwrMode_5G; 1674 return pBase->dacHiPwrMode_5G;
@@ -1839,8 +1912,15 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
1839 pModal->swSettleHt40); 1912 pModal->swSettleHt40);
1840 } 1913 }
1841 1914
1915 if (AR_SREV_9280_20_OR_LATER(ah) &&
1916 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1917 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
1918 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
1919 pModal->miscBits);
1920
1921
1842 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { 1922 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
1843 if (IS_CHAN_HT20(chan)) 1923 if (IS_CHAN_2GHZ(chan))
1844 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 1924 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1845 eep->baseEepHeader.dacLpMode); 1925 eep->baseEepHeader.dacLpMode);
1846 else if (eep->baseEepHeader.dacHiPwrMode_5G) 1926 else if (eep->baseEepHeader.dacHiPwrMode_5G)
@@ -1851,6 +1931,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
1851 1931
1852 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, 1932 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
1853 pModal->miscBits >> 2); 1933 pModal->miscBits >> 2);
1934
1935 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
1936 AR_PHY_TX_DESIRED_SCALE_CCK,
1937 eep->baseEepHeader.desiredScaleCCK);
1854 } 1938 }
1855 1939
1856 return true; 1940 return true;
@@ -2080,6 +2164,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2080 struct ath9k_channel *chan, 2164 struct ath9k_channel *chan,