aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/eeprom.c
diff options
context:
space:
mode:
authorSenthil Balasubramanian <senthilkumar@atheros.com>2009-02-12 03:27:03 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:51:46 -0500
commit8bd1d07f9345750bd4d767e6c1600919672f98ba (patch)
tree42b201403637888b4c5cde5e1fd096c373d4ca05 /drivers/net/wireless/ath9k/eeprom.c
parent81cb7623ad3b408f871fa36b774fc20d8dfccac0 (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/eeprom.c')
-rw-r--r--drivers/net/wireless/ath9k/eeprom.c210
1 files changed, 175 insertions, 35 deletions
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
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,
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
2205static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, 2323static 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,