diff options
author | Senthil Balasubramanian <senthilkumar@atheros.com> | 2009-02-12 03:27:03 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-27 14:51:46 -0500 |
commit | 8bd1d07f9345750bd4d767e6c1600919672f98ba (patch) | |
tree | 42b201403637888b4c5cde5e1fd096c373d4ca05 /drivers/net/wireless/ath9k | |
parent | 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/ath9k')
-rw-r--r-- | drivers/net/wireless/ath9k/calib.c | 31 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/eeprom.c | 210 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/eeprom.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/phy.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/rc.c | 4 |
7 files changed, 277 insertions, 39 deletions
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index a7ce8c5d48f5..e5abe6564ca7 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 | ||
721 | static 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 | |||
721 | bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | 748 | bool 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 b6f9c31ddfcf..fff7a1b6fbf2 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 | ||
182 | static 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, ¢ers); | ||
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 | |||
218 | static 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 | |||
182 | static void ath9k_hw_get_target_powers(struct ath_hw *ah, | 245 | static 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, |
2081 | int16_t *pTxPowerIndexOffset) | 2165 | int16_t *pTxPowerIndexOffset) |
2082 | { | 2166 | { |
2167 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ | ||
2168 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
2169 | #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) | ||
2170 | #define SM_PDGAIN_B(x, y) \ | ||
2171 | SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) | ||
2172 | |||
2083 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 2173 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
2084 | struct cal_data_per_freq *pRawDataset; | 2174 | struct cal_data_per_freq *pRawDataset; |
2085 | u8 *pCalBChans = NULL; | 2175 | u8 *pCalBChans = NULL; |
@@ -2113,6 +2203,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
2113 | numPiers = AR5416_NUM_5G_CAL_PIERS; | 2203 | numPiers = AR5416_NUM_5G_CAL_PIERS; |
2114 | } | 2204 | } |
2115 | 2205 | ||
2206 | if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { | ||
2207 | pRawDataset = pEepData->calPierData2G[0]; | ||
2208 | ah->initPDADC = ((struct calDataPerFreqOpLoop *) | ||
2209 | pRawDataset)->vpdPdg[0][0]; | ||
2210 | } | ||
2211 | |||
2116 | numXpdGain = 0; | 2212 | numXpdGain = 0; |
2117 | 2213 | ||
2118 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | 2214 | 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, | |||
2148 | else | 2244 | else |
2149 | pRawDataset = pEepData->calPierData5G[i]; | 2245 | pRawDataset = pEepData->calPierData5G[i]; |
2150 | 2246 | ||
2151 | ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan, | 2247 | |
2152 | pRawDataset, pCalBChans, | 2248 | if (OLC_FOR_AR9280_20_LATER) { |
2153 | numPiers, pdGainOverlap_t2, | 2249 | u8 pcdacIdx; |
2154 | &tMinCalPower, gainBoundaries, | 2250 | u8 txPower; |
2155 | pdadcValues, numXpdGain); | 2251 | |
2252 | ath9k_get_txgain_index(ah, chan, | ||
2253 | (struct calDataPerFreqOpLoop *)pRawDataset, | ||
2254 | pCalBChans, numPiers, &txPower, &pcdacIdx); | ||
2255 | ath9k_olc_get_pdadcs(ah, pcdacIdx, | ||
2256 | txPower/2, pdadcValues); | ||
2257 | } else { | ||
2258 | ath9k_hw_get_def_gain_boundaries_pdadcs(ah, | ||
2259 | chan, pRawDataset, | ||
2260 | pCalBChans, numPiers, | ||
2261 | pdGainOverlap_t2, | ||
2262 | &tMinCalPower, | ||
2263 | gainBoundaries, | ||
2264 | pdadcValues, | ||
2265 | numXpdGain); | ||
2266 | } | ||
2156 | 2267 | ||
2157 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | 2268 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { |
2158 | REG_WRITE(ah, | 2269 | if (OLC_FOR_AR9280_20_LATER) { |
2159 | AR_PHY_TPCRG5 + regChainOffset, | 2270 | REG_WRITE(ah, |
2160 | SM(pdGainOverlap_t2, | 2271 | AR_PHY_TPCRG5 + regChainOffset, |
2161 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 2272 | SM(0x6, |
2162 | | SM(gainBoundaries[0], | 2273 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | |
2163 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 2274 | SM_PD_GAIN(1) | SM_PD_GAIN(2) | |
2164 | | SM(gainBoundaries[1], | 2275 | SM_PD_GAIN(3) | SM_PD_GAIN(4)); |
2165 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 2276 | } else { |
2166 | | SM(gainBoundaries[2], | 2277 | REG_WRITE(ah, |
2167 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 2278 | AR_PHY_TPCRG5 + regChainOffset, |
2168 | | SM(gainBoundaries[3], | 2279 | SM(pdGainOverlap_t2, |
2169 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | 2280 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| |
2281 | SM_PDGAIN_B(0, 1) | | ||
2282 | SM_PDGAIN_B(1, 2) | | ||
2283 | SM_PDGAIN_B(2, 3) | | ||
2284 | SM_PDGAIN_B(3, 4)); | ||
2285 | } | ||
2170 | } | 2286 | } |
2171 | 2287 | ||
2172 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | 2288 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; |
@@ -2200,6 +2316,8 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
2200 | *pTxPowerIndexOffset = 0; | 2316 | *pTxPowerIndexOffset = 0; |
2201 | 2317 | ||
2202 | return true; | 2318 | return true; |
2319 | #undef SM_PD_GAIN | ||
2320 | #undef SM_PDGAIN_B | ||
2203 | } | 2321 | } |
2204 | 2322 | ||
2205 | static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | 2323 | 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, | |||
2500 | u8 twiceMaxRegulatoryPower, | 2618 | u8 twiceMaxRegulatoryPower, |
2501 | u8 powerLimit) | 2619 | u8 powerLimit) |
2502 | { | 2620 | { |
2621 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) | ||
2503 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 2622 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
2504 | struct modal_eep_header *pModal = | 2623 | struct modal_eep_header *pModal = |
2505 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | 2624 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); |
2506 | int16_t ratesArray[Ar5416RateSize]; | 2625 | int16_t ratesArray[Ar5416RateSize]; |
2507 | int16_t txPowerIndexOffset = 0; | 2626 | int16_t txPowerIndexOffset = 0; |
2508 | u8 ht40PowerIncForPdadc = 2; | 2627 | u8 ht40PowerIncForPdadc = 2; |
2509 | int i; | 2628 | int i, cck_ofdm_delta = 0; |
2510 | 2629 | ||
2511 | memset(ratesArray, 0, sizeof(ratesArray)); | 2630 | memset(ratesArray, 0, sizeof(ratesArray)); |
2512 | 2631 | ||
@@ -2555,16 +2674,30 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
2555 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | 2674 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); |
2556 | 2675 | ||
2557 | if (IS_CHAN_2GHZ(chan)) { | 2676 | if (IS_CHAN_2GHZ(chan)) { |
2558 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | 2677 | if (OLC_FOR_AR9280_20_LATER) { |
2559 | ATH9K_POW_SM(ratesArray[rate2s], 24) | 2678 | cck_ofdm_delta = 2; |
2560 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | 2679 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, |
2561 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | 2680 | ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) |
2562 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | 2681 | | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) |
2563 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | 2682 | | ATH9K_POW_SM(ratesArray[rateXr], 8) |
2564 | ATH9K_POW_SM(ratesArray[rate11s], 24) | 2683 | | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); |
2565 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | 2684 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, |
2566 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | 2685 | ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) |
2567 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | 2686 | | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) |
2687 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) | ||
2688 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); | ||
2689 | } else { | ||
2690 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
2691 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
2692 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
2693 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
2694 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
2695 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
2696 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
2697 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
2698 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
2699 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
2700 | } | ||
2568 | } | 2701 | } |
2569 | 2702 | ||
2570 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | 2703 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, |
@@ -2597,12 +2730,19 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
2597 | ht40PowerIncForPdadc, 8) | 2730 | ht40PowerIncForPdadc, 8) |
2598 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | 2731 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + |
2599 | ht40PowerIncForPdadc, 0)); | 2732 | ht40PowerIncForPdadc, 0)); |
2600 | 2733 | if (OLC_FOR_AR9280_20_LATER) { | |
2601 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | 2734 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, |
2602 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | 2735 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
2603 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | 2736 | | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) |
2604 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | 2737 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
2605 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | 2738 | | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); |
2739 | } else { | ||
2740 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
2741 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
2742 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
2743 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
2744 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
2745 | } | ||
2606 | } | 2746 | } |
2607 | 2747 | ||
2608 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, | 2748 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, |
diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 60cb23de97c6..2cfea5d56d10 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h | |||
@@ -168,6 +168,8 @@ | |||
168 | #define AR5416_EEP4K_PD_GAIN_ICEPTS 5 | 168 | #define AR5416_EEP4K_PD_GAIN_ICEPTS 5 |
169 | #define AR5416_EEP4K_MAX_CHAINS 1 | 169 | #define AR5416_EEP4K_MAX_CHAINS 1 |
170 | 170 | ||
171 | #define AR9280_TX_GAIN_TABLE_SIZE 22 | ||
172 | |||
171 | enum eeprom_param { | 173 | enum eeprom_param { |
172 | EEP_NFTHRESH_5, | 174 | EEP_NFTHRESH_5, |
173 | EEP_NFTHRESH_2, | 175 | EEP_NFTHRESH_2, |
@@ -188,6 +190,8 @@ enum eeprom_param { | |||
188 | EEP_RX_MASK, | 190 | EEP_RX_MASK, |
189 | EEP_RXGAIN_TYPE, | 191 | EEP_RXGAIN_TYPE, |
190 | EEP_TXGAIN_TYPE, | 192 | EEP_TXGAIN_TYPE, |
193 | EEP_OL_PWRCTRL, | ||
194 | EEP_RC_CHAIN_MASK, | ||
191 | EEP_DAC_HPWR_5G, | 195 | EEP_DAC_HPWR_5G, |
192 | EEP_FRAC_N_5G | 196 | EEP_FRAC_N_5G |
193 | }; | 197 | }; |
@@ -229,7 +233,7 @@ struct base_eep_header { | |||
229 | u8 futureBase_1[2]; | 233 | u8 futureBase_1[2]; |
230 | u8 rxGainType; | 234 | u8 rxGainType; |
231 | u8 dacHiPwrMode_5G; | 235 | u8 dacHiPwrMode_5G; |
232 | u8 futureBase_2; | 236 | u8 openLoopPwrCntl; |
233 | u8 dacLpMode; | 237 | u8 dacLpMode; |
234 | u8 txGainType; | 238 | u8 txGainType; |
235 | u8 rcChainMask; | 239 | u8 rcChainMask; |
@@ -310,6 +314,13 @@ struct modal_eep_header { | |||
310 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | 314 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; |
311 | } __packed; | 315 | } __packed; |
312 | 316 | ||
317 | struct calDataPerFreqOpLoop { | ||
318 | u8 pwrPdg[2][5]; | ||
319 | u8 vpdPdg[2][5]; | ||
320 | u8 pcdac[2][5]; | ||
321 | u8 empty[2][5]; | ||
322 | } __packed; | ||
323 | |||
313 | struct modal_eep_4k_header { | 324 | struct modal_eep_4k_header { |
314 | u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; | 325 | u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; |
315 | u32 antCtrlCommon; | 326 | u32 antCtrlCommon; |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 4af1aac16785..e33c53fb6b7e 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -1202,10 +1202,23 @@ static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, | |||
1202 | return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); | 1202 | return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); |
1203 | } | 1203 | } |
1204 | 1204 | ||
1205 | static void ath9k_olc_init(struct ath_hw *ah) | ||
1206 | { | ||
1207 | u32 i; | ||
1208 | |||
1209 | for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) | ||
1210 | ah->originalGain[i] = | ||
1211 | MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), | ||
1212 | AR_PHY_TX_GAIN); | ||
1213 | ah->PDADCdelta = 0; | ||
1214 | } | ||
1215 | |||
1205 | static int ath9k_hw_process_ini(struct ath_hw *ah, | 1216 | static int ath9k_hw_process_ini(struct ath_hw *ah, |
1206 | struct ath9k_channel *chan, | 1217 | struct ath9k_channel *chan, |
1207 | enum ath9k_ht_macmode macmode) | 1218 | enum ath9k_ht_macmode macmode) |
1208 | { | 1219 | { |
1220 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ | ||
1221 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
1209 | int i, regWrites = 0; | 1222 | int i, regWrites = 0; |
1210 | struct ieee80211_channel *channel = chan->chan; | 1223 | struct ieee80211_channel *channel = chan->chan; |
1211 | u32 modesIndex, freqIndex; | 1224 | u32 modesIndex, freqIndex; |
@@ -1308,6 +1321,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1308 | ath9k_hw_set_regs(ah, chan, macmode); | 1321 | ath9k_hw_set_regs(ah, chan, macmode); |
1309 | ath9k_hw_init_chain_masks(ah); | 1322 | ath9k_hw_init_chain_masks(ah); |
1310 | 1323 | ||
1324 | if (OLC_FOR_AR9280_20_LATER) | ||
1325 | ath9k_olc_init(ah); | ||
1326 | |||
1311 | status = ah->eep_ops->set_txpower(ah, chan, | 1327 | status = ah->eep_ops->set_txpower(ah, chan, |
1312 | ath9k_regd_get_ctl(ah, chan), | 1328 | ath9k_regd_get_ctl(ah, chan), |
1313 | channel->max_antenna_gain * 2, | 1329 | channel->max_antenna_gain * 2, |
@@ -1515,6 +1531,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1515 | AR_RTC_FORCE_WAKE_ON_INT); | 1531 | AR_RTC_FORCE_WAKE_ON_INT); |
1516 | 1532 | ||
1517 | REG_WRITE(ah, AR_RTC_RESET, 0); | 1533 | REG_WRITE(ah, AR_RTC_RESET, 0); |
1534 | udelay(2); | ||
1518 | REG_WRITE(ah, AR_RTC_RESET, 1); | 1535 | REG_WRITE(ah, AR_RTC_RESET, 1); |
1519 | 1536 | ||
1520 | if (!ath9k_hw_wait(ah, | 1537 | if (!ath9k_hw_wait(ah, |
@@ -1582,7 +1599,10 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1582 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, | 1599 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, |
1583 | struct ath9k_channel *chan) | 1600 | struct ath9k_channel *chan) |
1584 | { | 1601 | { |
1585 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | 1602 | if (OLC_FOR_AR9280_20_LATER) { |
1603 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) | ||
1604 | return false; | ||
1605 | } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | ||
1586 | return false; | 1606 | return false; |
1587 | 1607 | ||
1588 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1608 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
@@ -3404,6 +3424,10 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | |||
3404 | return 0; | 3424 | return 0; |
3405 | } | 3425 | } |
3406 | return false; | 3426 | return false; |
3427 | case ATH9K_CAP_DS: | ||
3428 | return (AR_SREV_9280_20_OR_LATER(ah) && | ||
3429 | (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) | ||
3430 | ? false : true; | ||
3407 | default: | 3431 | default: |
3408 | return false; | 3432 | return false; |
3409 | } | 3433 | } |
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 587a78db748d..08469d9525bc 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -162,7 +162,8 @@ enum ath9k_capability_type { | |||
162 | ATH9K_CAP_WME_TKIPMIC, | 162 | ATH9K_CAP_WME_TKIPMIC, |
163 | ATH9K_CAP_RFSILENT, | 163 | ATH9K_CAP_RFSILENT, |
164 | ATH9K_CAP_ANT_CFG_2GHZ, | 164 | ATH9K_CAP_ANT_CFG_2GHZ, |
165 | ATH9K_CAP_ANT_CFG_5GHZ | 165 | ATH9K_CAP_ANT_CFG_5GHZ, |
166 | ATH9K_CAP_DS | ||
166 | }; | 167 | }; |
167 | 168 | ||
168 | struct ath9k_hw_capabilities { | 169 | struct ath9k_hw_capabilities { |
@@ -551,6 +552,10 @@ struct ath_hw { | |||
551 | u8 txchainmask; | 552 | u8 txchainmask; |
552 | u8 rxchainmask; | 553 | u8 rxchainmask; |
553 | 554 | ||
555 | u32 originalGain[22]; | ||
556 | int initPDADC; | ||
557 | int PDADCdelta; | ||
558 | |||
554 | struct ar5416IniArray iniModes; | 559 | struct ar5416IniArray iniModes; |
555 | struct ar5416IniArray iniCommon; | 560 | struct ar5416IniArray iniCommon; |
556 | struct ar5416IniArray iniBank0; | 561 | struct ar5416IniArray iniBank0; |
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 4758c37e4b88..3dbdd54be4e9 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h | |||
@@ -387,6 +387,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
387 | 387 | ||
388 | #define AR_PHY_CCK_TX_CTRL 0xA204 | 388 | #define AR_PHY_CCK_TX_CTRL 0xA204 |
389 | #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 | 389 | #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 |
390 | #define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C | ||
391 | #define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 | ||
390 | 392 | ||
391 | #define AR_PHY_CCK_DETECT 0xA208 | 393 | #define AR_PHY_CCK_DETECT 0xA208 |
392 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F | 394 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F |
@@ -444,6 +446,29 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
444 | #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 | 446 | #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 |
445 | #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 | 447 | #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 |
446 | 448 | ||
449 | #define AR_PHY_TX_PWRCTRL4 0xa264 | ||
450 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 | ||
451 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 | ||
452 | #define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE | ||
453 | #define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 | ||
454 | |||
455 | #define AR_PHY_TX_PWRCTRL6_0 0xa270 | ||
456 | #define AR_PHY_TX_PWRCTRL6_1 0xb270 | ||
457 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 | ||
458 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 | ||
459 | |||
460 | #define AR_PHY_TX_PWRCTRL7 0xa274 | ||
461 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 | ||
462 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | ||
463 | |||
464 | #define AR_PHY_TX_PWRCTRL9 0xa27C | ||
465 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 | ||
466 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 | ||
467 | |||
468 | #define AR_PHY_TX_GAIN_TBL1 0xa300 | ||
469 | #define AR_PHY_TX_GAIN 0x0007F000 | ||
470 | #define AR_PHY_TX_GAIN_S 12 | ||
471 | |||
447 | #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 | 472 | #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 |
448 | #define AR_PHY_MASK2_M_31_45 0xa3a4 | 473 | #define AR_PHY_MASK2_M_31_45 0xa3a4 |
449 | #define AR_PHY_MASK2_M_16_30 0xa3a8 | 474 | #define AR_PHY_MASK2_M_16_30 0xa3a8 |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index a4e863191766..6b4731c24736 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1392,6 +1392,7 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1392 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; | 1392 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; |
1393 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; | 1393 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; |
1394 | u8 i, j, k, hi = 0, hthi = 0; | 1394 | u8 i, j, k, hi = 0, hthi = 0; |
1395 | struct ath_hw *ah = sc->sc_ah; | ||
1395 | 1396 | ||
1396 | /* FIXME: Adhoc */ | 1397 | /* FIXME: Adhoc */ |
1397 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || | 1398 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || |
@@ -1412,7 +1413,8 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1412 | 1413 | ||
1413 | if (sta->ht_cap.ht_supported) { | 1414 | if (sta->ht_cap.ht_supported) { |
1414 | ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG; | 1415 | ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG; |
1415 | if (sc->sc_ah->caps.tx_chainmask != 1) | 1416 | if (sc->sc_ah->caps.tx_chainmask != 1 && |
1417 | ath9k_hw_getcapability(ah, ATH9K_CAP_DS, 0, NULL)) | ||
1416 | ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG; | 1418 | ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG; |
1417 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 1419 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
1418 | ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; | 1420 | ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; |