diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2010-06-01 05:44:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-03 14:10:46 -0400 |
commit | a55f858852e4345d0a31af593c46738ca8614bff (patch) | |
tree | 0859e47e0d7414658937139c85a8bc0307ad3351 /drivers/net/wireless/ath | |
parent | 79d7f4bcf8519abbea46d909ff01a1358b431e1d (diff) |
ath9k_hw: Cleanup TX power calculation for AR9287
* Add a few comments, and move the updation of max_power_level
to a helper routine. This is also done by non-4K based chipsets,
this will be fixed in a separate patch.
* Remove two WARs which are required for old AR5416 chipsets,
and are not needed for AR9287.
* Fix indentation and make things readable.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_9287.c | 287 |
3 files changed, 168 insertions, 141 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index a29b2d94c802..1266333f586d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -258,6 +258,27 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | |||
258 | return twiceMaxEdgePower; | 258 | return twiceMaxEdgePower; |
259 | } | 259 | } |
260 | 260 | ||
261 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) | ||
262 | { | ||
263 | struct ath_common *common = ath9k_hw_common(ah); | ||
264 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
265 | |||
266 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
267 | case 1: | ||
268 | break; | ||
269 | case 2: | ||
270 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
271 | break; | ||
272 | case 3: | ||
273 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
274 | break; | ||
275 | default: | ||
276 | ath_print(common, ATH_DBG_EEPROM, | ||
277 | "Invalid chainmask configuration\n"); | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
261 | int ath9k_hw_eeprom_init(struct ath_hw *ah) | 282 | int ath9k_hw_eeprom_init(struct ath_hw *ah) |
262 | { | 283 | { |
263 | int status; | 284 | int status; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 14186f2fc113..7da7d73c0847 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -705,6 +705,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, | |||
705 | u16 numRates, bool isHt40Target); | 705 | u16 numRates, bool isHt40Target); |
706 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | 706 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, |
707 | bool is2GHz, int num_band_edges); | 707 | bool is2GHz, int num_band_edges); |
708 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); | ||
708 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | 709 | int ath9k_hw_eeprom_init(struct ath_hw *ah); |
709 | 710 | ||
710 | #define ar5416_get_ntxchains(_txchainmask) \ | 711 | #define ar5416_get_ntxchains(_txchainmask) \ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 27abfba0b69f..5f3b20b54d35 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -317,21 +317,18 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
317 | pPdGainBoundaries[i]); | 317 | pPdGainBoundaries[i]); |
318 | 318 | ||
319 | 319 | ||
320 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | 320 | minDelta = 0; |
321 | minDelta = pPdGainBoundaries[0] - 23; | ||
322 | pPdGainBoundaries[0] = 23; | ||
323 | } else | ||
324 | minDelta = 0; | ||
325 | 321 | ||
326 | if (i == 0) { | 322 | if (i == 0) { |
327 | if (AR_SREV_9280_10_OR_LATER(ah)) | 323 | if (AR_SREV_9280_10_OR_LATER(ah)) |
328 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | 324 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); |
329 | else | 325 | else |
330 | ss = 0; | 326 | ss = 0; |
331 | } else | 327 | } else { |
332 | ss = (int16_t)((pPdGainBoundaries[i-1] - | 328 | ss = (int16_t)((pPdGainBoundaries[i-1] - |
333 | (minPwrT4[i] / 2)) - | 329 | (minPwrT4[i] / 2)) - |
334 | tPdGainOverlap + 1 + minDelta); | 330 | tPdGainOverlap + 1 + minDelta); |
331 | } | ||
335 | 332 | ||
336 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | 333 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); |
337 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | 334 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); |
@@ -396,8 +393,8 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | |||
396 | } | 393 | } |
397 | 394 | ||
398 | match = ath9k_hw_get_lower_upper_index( | 395 | match = ath9k_hw_get_lower_upper_index( |
399 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | 396 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), |
400 | pCalChans, numPiers, &idxL, &idxR); | 397 | pCalChans, numPiers, &idxL, &idxR); |
401 | 398 | ||
402 | if (match) { | 399 | if (match) { |
403 | *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | 400 | *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; |
@@ -463,7 +460,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
463 | int16_t tMinCalPower; | 460 | int16_t tMinCalPower; |
464 | u16 numXpdGain, xpdMask; | 461 | u16 numXpdGain, xpdMask; |
465 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | 462 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; |
466 | u32 reg32, regOffset, regChainOffset; | 463 | u32 reg32, regOffset, regChainOffset, regval; |
467 | int16_t modalIdx, diff = 0; | 464 | int16_t modalIdx, diff = 0; |
468 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 465 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
469 | 466 | ||
@@ -471,7 +468,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
471 | xpdMask = pEepData->modalHeader.xpdGain; | 468 | xpdMask = pEepData->modalHeader.xpdGain; |
472 | 469 | ||
473 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | 470 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= |
474 | AR9287_EEP_MINOR_VER_2) | 471 | AR9287_EEP_MINOR_VER_2) |
475 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; | 472 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; |
476 | else | 473 | else |
477 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | 474 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), |
@@ -482,14 +479,14 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
482 | numPiers = AR9287_NUM_2G_CAL_PIERS; | 479 | numPiers = AR9287_NUM_2G_CAL_PIERS; |
483 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 480 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
484 | pRawDatasetOpenLoop = | 481 | pRawDatasetOpenLoop = |
485 | (struct cal_data_op_loop_ar9287 *) | 482 | (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; |
486 | pEepData->calPierData2G[0]; | ||
487 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; | 483 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; |
488 | } | 484 | } |
489 | } | 485 | } |
490 | 486 | ||
491 | numXpdGain = 0; | 487 | numXpdGain = 0; |
492 | 488 | ||
489 | /* Calculate the value of xpdgains from the xpdGain Mask */ | ||
493 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | 490 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { |
494 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | 491 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { |
495 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | 492 | if (numXpdGain >= AR9287_NUM_PD_GAINS) |
@@ -511,77 +508,79 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
511 | 508 | ||
512 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | 509 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { |
513 | regChainOffset = i * 0x1000; | 510 | regChainOffset = i * 0x1000; |
511 | |||
514 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | 512 | if (pEepData->baseEepHeader.txMask & (1 << i)) { |
515 | pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) | 513 | pRawDatasetOpenLoop = |
516 | pEepData->calPierData2G[i]; | 514 | (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; |
515 | |||
517 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 516 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
518 | int8_t txPower; | 517 | int8_t txPower; |
519 | ar9287_eeprom_get_tx_gain_index(ah, chan, | 518 | ar9287_eeprom_get_tx_gain_index(ah, chan, |
520 | pRawDatasetOpenLoop, | 519 | pRawDatasetOpenLoop, |
521 | pCalBChans, numPiers, | 520 | pCalBChans, numPiers, |
522 | &txPower); | 521 | &txPower); |
523 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); | 522 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); |
524 | } else { | 523 | } else { |
525 | pRawDataset = | 524 | pRawDataset = |
526 | (struct cal_data_per_freq_ar9287 *) | 525 | (struct cal_data_per_freq_ar9287 *) |
527 | pEepData->calPierData2G[i]; | 526 | pEepData->calPierData2G[i]; |
528 | ath9k_hw_get_ar9287_gain_boundaries_pdadcs( | 527 | |
529 | ah, chan, pRawDataset, | 528 | ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan, |
530 | pCalBChans, numPiers, | 529 | pRawDataset, |
531 | pdGainOverlap_t2, | 530 | pCalBChans, numPiers, |
532 | &tMinCalPower, gainBoundaries, | 531 | pdGainOverlap_t2, |
533 | pdadcValues, numXpdGain); | 532 | &tMinCalPower, |
533 | gainBoundaries, | ||
534 | pdadcValues, | ||
535 | numXpdGain); | ||
534 | } | 536 | } |
535 | 537 | ||
536 | if (i == 0) { | 538 | if (i == 0) { |
537 | if (!ath9k_hw_ar9287_get_eeprom( | 539 | if (!ath9k_hw_ar9287_get_eeprom(ah, |
538 | ah, EEP_OL_PWRCTRL)) { | 540 | EEP_OL_PWRCTRL)) { |
539 | REG_WRITE(ah, AR_PHY_TPCRG5 + | 541 | |
540 | regChainOffset, | 542 | regval = SM(pdGainOverlap_t2, |
541 | SM(pdGainOverlap_t2, | 543 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
542 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | 544 | | SM(gainBoundaries[0], |
543 | SM(gainBoundaries[0], | 545 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
544 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 546 | | SM(gainBoundaries[1], |
545 | | SM(gainBoundaries[1], | 547 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
546 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 548 | | SM(gainBoundaries[2], |
547 | | SM(gainBoundaries[2], | 549 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
548 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 550 | | SM(gainBoundaries[3], |
549 | | SM(gainBoundaries[3], | 551 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4); |
550 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | 552 | |
553 | REG_WRITE(ah, | ||
554 | AR_PHY_TPCRG5 + regChainOffset, | ||
555 | regval); | ||
551 | } | 556 | } |
552 | } | 557 | } |
553 | 558 | ||
554 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != | 559 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != |
555 | pEepData->baseEepHeader.pwrTableOffset) { | 560 | pEepData->baseEepHeader.pwrTableOffset) { |
556 | diff = (u16) | 561 | diff = (u16)(pEepData->baseEepHeader.pwrTableOffset - |
557 | (pEepData->baseEepHeader.pwrTableOffset | 562 | (int32_t)AR9287_PWR_TABLE_OFFSET_DB); |
558 | - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | ||
559 | diff *= 2; | 563 | diff *= 2; |
560 | 564 | ||
561 | for (j = 0; | 565 | for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++) |
562 | j < ((u16)AR9287_NUM_PDADC_VALUES-diff); | ||
563 | j++) | ||
564 | pdadcValues[j] = pdadcValues[j+diff]; | 566 | pdadcValues[j] = pdadcValues[j+diff]; |
565 | 567 | ||
566 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | 568 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); |
567 | j < AR9287_NUM_PDADC_VALUES; j++) | 569 | j < AR9287_NUM_PDADC_VALUES; j++) |
568 | pdadcValues[j] = | 570 | pdadcValues[j] = |
569 | pdadcValues[ | 571 | pdadcValues[AR9287_NUM_PDADC_VALUES-diff]; |
570 | AR9287_NUM_PDADC_VALUES-diff]; | ||
571 | } | 572 | } |
572 | 573 | ||
573 | if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 574 | if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
574 | regOffset = AR_PHY_BASE + (672 << 2) + | 575 | regOffset = AR_PHY_BASE + |
575 | regChainOffset; | 576 | (672 << 2) + regChainOffset; |
577 | |||
576 | for (j = 0; j < 32; j++) { | 578 | for (j = 0; j < 32; j++) { |
577 | reg32 = ((pdadcValues[4*j + 0] | 579 | reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) |
578 | & 0xFF) << 0) | | 580 | | ((pdadcValues[4*j + 1] & 0xFF) << 8) |
579 | ((pdadcValues[4*j + 1] | 581 | | ((pdadcValues[4*j + 2] & 0xFF) << 16) |
580 | & 0xFF) << 8) | | 582 | | ((pdadcValues[4*j + 3] & 0xFF) << 24); |
581 | ((pdadcValues[4*j + 2] | 583 | |
582 | & 0xFF) << 16) | | ||
583 | ((pdadcValues[4*j + 3] | ||
584 | & 0xFF) << 24) ; | ||
585 | REG_WRITE(ah, regOffset, reg32); | 584 | REG_WRITE(ah, regOffset, reg32); |
586 | regOffset += 4; | 585 | regOffset += 4; |
587 | } | 586 | } |
@@ -600,6 +599,14 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
600 | u16 twiceMaxRegulatoryPower, | 599 | u16 twiceMaxRegulatoryPower, |
601 | u16 powerLimit) | 600 | u16 powerLimit) |
602 | { | 601 | { |
602 | #define CMP_CTL \ | ||
603 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
604 | pEepData->ctlIndex[i]) | ||
605 | |||
606 | #define CMP_NO_CTL \ | ||
607 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
608 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) | ||
609 | |||
603 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | 610 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 |
604 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | 611 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 |
605 | 612 | ||
@@ -617,9 +624,12 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
617 | struct cal_target_power_ht targetPowerHt20, | 624 | struct cal_target_power_ht targetPowerHt20, |
618 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | 625 | targetPowerHt40 = {0, {0, 0, 0, 0} }; |
619 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 626 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
620 | u16 ctlModesFor11g[] = | 627 | u16 ctlModesFor11g[] = {CTL_11B, |
621 | {CTL_11B, CTL_11G, CTL_2GHT20, | 628 | CTL_11G, |
622 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; | 629 | CTL_2GHT20, |
630 | CTL_11B_EXT, | ||
631 | CTL_11G_EXT, | ||
632 | CTL_2GHT40}; | ||
623 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | 633 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; |
624 | struct chan_centers centers; | 634 | struct chan_centers centers; |
625 | int tx_chainmask; | 635 | int tx_chainmask; |
@@ -629,19 +639,28 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
629 | 639 | ||
630 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 640 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
631 | 641 | ||
642 | /* Compute TxPower reduction due to Antenna Gain */ | ||
632 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], | 643 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], |
633 | pEepData->modalHeader.antennaGainCh[1]); | 644 | pEepData->modalHeader.antennaGainCh[1]); |
634 | |||
635 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | 645 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - |
636 | twiceLargestAntenna, 0); | 646 | twiceLargestAntenna, 0); |
637 | 647 | ||
648 | /* | ||
649 | * scaledPower is the minimum of the user input power level | ||
650 | * and the regulatory allowed power level. | ||
651 | */ | ||
638 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | 652 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; |
653 | |||
639 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) | 654 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) |
640 | maxRegAllowedPower -= | 655 | maxRegAllowedPower -= |
641 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); | 656 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); |
642 | 657 | ||
643 | scaledPower = min(powerLimit, maxRegAllowedPower); | 658 | scaledPower = min(powerLimit, maxRegAllowedPower); |
644 | 659 | ||
660 | /* | ||
661 | * Reduce scaled Power by number of chains active | ||
662 | * to get the per chain tx power level. | ||
663 | */ | ||
645 | switch (ar5416_get_ntxchains(tx_chainmask)) { | 664 | switch (ar5416_get_ntxchains(tx_chainmask)) { |
646 | case 1: | 665 | case 1: |
647 | break; | 666 | break; |
@@ -654,7 +673,11 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
654 | } | 673 | } |
655 | scaledPower = max((u16)0, scaledPower); | 674 | scaledPower = max((u16)0, scaledPower); |
656 | 675 | ||
676 | /* | ||
677 | * Get TX power from EEPROM. | ||
678 | */ | ||
657 | if (IS_CHAN_2GHZ(chan)) { | 679 | if (IS_CHAN_2GHZ(chan)) { |
680 | /* CTL_11B, CTL_11G, CTL_2GHT20 */ | ||
658 | numCtlModes = | 681 | numCtlModes = |
659 | ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | 682 | ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; |
660 | 683 | ||
@@ -674,6 +697,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
674 | &targetPowerHt20, 8, false); | 697 | &targetPowerHt20, 8, false); |
675 | 698 | ||
676 | if (IS_CHAN_HT40(chan)) { | 699 | if (IS_CHAN_HT40(chan)) { |
700 | /* All 2G CTLs */ | ||
677 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | 701 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); |
678 | ath9k_hw_get_target_powers(ah, chan, | 702 | ath9k_hw_get_target_powers(ah, chan, |
679 | pEepData->calTargetPower2GHT40, | 703 | pEepData->calTargetPower2GHT40, |
@@ -691,8 +715,9 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
691 | } | 715 | } |
692 | 716 | ||
693 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | 717 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { |
694 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | 718 | bool isHt40CtlMode = |
695 | (pCtlMode[ctlMode] == CTL_2GHT40); | 719 | (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false; |
720 | |||
696 | if (isHt40CtlMode) | 721 | if (isHt40CtlMode) |
697 | freq = centers.synth_center; | 722 | freq = centers.synth_center; |
698 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | 723 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) |
@@ -700,31 +725,28 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
700 | else | 725 | else |
701 | freq = centers.ctl_center; | 726 | freq = centers.ctl_center; |
702 | 727 | ||
703 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 728 | /* Walk through the CTL indices stored in EEPROM */ |
704 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
705 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
706 | |||
707 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | 729 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { |
708 | if ((((cfgCtl & ~CTL_MODE_M) | | 730 | struct cal_ctl_edges *pRdEdgesPower; |
709 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
710 | pEepData->ctlIndex[i]) || | ||
711 | (((cfgCtl & ~CTL_MODE_M) | | ||
712 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
713 | ((pEepData->ctlIndex[i] & | ||
714 | CTL_MODE_M) | SD_NO_CTL))) { | ||
715 | 731 | ||
732 | /* | ||
733 | * Compare test group from regulatory channel list | ||
734 | * with test mode from pCtlMode list | ||
735 | */ | ||
736 | if (CMP_CTL || CMP_NO_CTL) { | ||
716 | rep = &(pEepData->ctlData[i]); | 737 | rep = &(pEepData->ctlData[i]); |
717 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | 738 | pRdEdgesPower = |
718 | freq, | 739 | rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1]; |
719 | rep->ctlEdges[ar5416_get_ntxchains( | 740 | |
720 | tx_chainmask) - 1], | 741 | twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, |
721 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | 742 | pRdEdgesPower, |
722 | 743 | IS_CHAN_2GHZ(chan), | |
723 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | 744 | AR5416_NUM_BAND_EDGES); |
724 | twiceMaxEdgePower = min( | 745 | |
725 | twiceMaxEdgePower, | 746 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { |
726 | twiceMinEdgePower); | 747 | twiceMaxEdgePower = min(twiceMaxEdgePower, |
727 | else { | 748 | twiceMinEdgePower); |
749 | } else { | ||
728 | twiceMaxEdgePower = twiceMinEdgePower; | 750 | twiceMaxEdgePower = twiceMinEdgePower; |
729 | break; | 751 | break; |
730 | } | 752 | } |
@@ -733,55 +755,48 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
733 | 755 | ||
734 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | 756 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); |
735 | 757 | ||
758 | /* Apply ctl mode to correct target power set */ | ||
736 | switch (pCtlMode[ctlMode]) { | 759 | switch (pCtlMode[ctlMode]) { |
737 | case CTL_11B: | 760 | case CTL_11B: |
738 | for (i = 0; | 761 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { |
739 | i < ARRAY_SIZE(targetPowerCck.tPow2x); | 762 | targetPowerCck.tPow2x[i] = |
740 | i++) { | 763 | (u8)min((u16)targetPowerCck.tPow2x[i], |
741 | targetPowerCck.tPow2x[i] = (u8)min( | 764 | minCtlPower); |
742 | (u16)targetPowerCck.tPow2x[i], | ||
743 | minCtlPower); | ||
744 | } | 765 | } |
745 | break; | 766 | break; |
746 | case CTL_11A: | 767 | case CTL_11A: |
747 | case CTL_11G: | 768 | case CTL_11G: |
748 | for (i = 0; | 769 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { |
749 | i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | 770 | targetPowerOfdm.tPow2x[i] = |
750 | i++) { | 771 | (u8)min((u16)targetPowerOfdm.tPow2x[i], |
751 | targetPowerOfdm.tPow2x[i] = (u8)min( | 772 | minCtlPower); |
752 | (u16)targetPowerOfdm.tPow2x[i], | ||
753 | minCtlPower); | ||
754 | } | 773 | } |
755 | break; | 774 | break; |
756 | case CTL_5GHT20: | 775 | case CTL_5GHT20: |
757 | case CTL_2GHT20: | 776 | case CTL_2GHT20: |
758 | for (i = 0; | 777 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { |
759 | i < ARRAY_SIZE(targetPowerHt20.tPow2x); | 778 | targetPowerHt20.tPow2x[i] = |
760 | i++) { | 779 | (u8)min((u16)targetPowerHt20.tPow2x[i], |
761 | targetPowerHt20.tPow2x[i] = (u8)min( | 780 | minCtlPower); |
762 | (u16)targetPowerHt20.tPow2x[i], | ||
763 | minCtlPower); | ||
764 | } | 781 | } |
765 | break; | 782 | break; |
766 | case CTL_11B_EXT: | 783 | case CTL_11B_EXT: |
767 | targetPowerCckExt.tPow2x[0] = (u8)min( | 784 | targetPowerCckExt.tPow2x[0] = |
768 | (u16)targetPowerCckExt.tPow2x[0], | 785 | (u8)min((u16)targetPowerCckExt.tPow2x[0], |
769 | minCtlPower); | 786 | minCtlPower); |
770 | break; | 787 | break; |
771 | case CTL_11A_EXT: | 788 | case CTL_11A_EXT: |
772 | case CTL_11G_EXT: | 789 | case CTL_11G_EXT: |
773 | targetPowerOfdmExt.tPow2x[0] = (u8)min( | 790 | targetPowerOfdmExt.tPow2x[0] = |
774 | (u16)targetPowerOfdmExt.tPow2x[0], | 791 | (u8)min((u16)targetPowerOfdmExt.tPow2x[0], |
775 | minCtlPower); | 792 | minCtlPower); |
776 | break; | 793 | break; |
777 | case CTL_5GHT40: | 794 | case CTL_5GHT40: |
778 | case CTL_2GHT40: | 795 | case CTL_2GHT40: |
779 | for (i = 0; | 796 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { |
780 | i < ARRAY_SIZE(targetPowerHt40.tPow2x); | 797 | targetPowerHt40.tPow2x[i] = |
781 | i++) { | 798 | (u8)min((u16)targetPowerHt40.tPow2x[i], |
782 | targetPowerHt40.tPow2x[i] = (u8)min( | 799 | minCtlPower); |
783 | (u16)targetPowerHt40.tPow2x[i], | ||
784 | minCtlPower); | ||
785 | } | 800 | } |
786 | break; | 801 | break; |
787 | default: | 802 | default: |
@@ -789,12 +804,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
789 | } | 804 | } |
790 | } | 805 | } |
791 | 806 | ||
807 | /* Now set the rates array */ | ||
808 | |||
792 | ratesArray[rate6mb] = | 809 | ratesArray[rate6mb] = |
793 | ratesArray[rate9mb] = | 810 | ratesArray[rate9mb] = |
794 | ratesArray[rate12mb] = | 811 | ratesArray[rate12mb] = |
795 | ratesArray[rate18mb] = | 812 | ratesArray[rate18mb] = |
796 | ratesArray[rate24mb] = | 813 | ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; |
797 | targetPowerOfdm.tPow2x[0]; | ||
798 | 814 | ||
799 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | 815 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; |
800 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | 816 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; |
@@ -806,12 +822,12 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
806 | 822 | ||
807 | if (IS_CHAN_2GHZ(chan)) { | 823 | if (IS_CHAN_2GHZ(chan)) { |
808 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | 824 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; |
809 | ratesArray[rate2s] = ratesArray[rate2l] = | 825 | ratesArray[rate2s] = |
810 | targetPowerCck.tPow2x[1]; | 826 | ratesArray[rate2l] = targetPowerCck.tPow2x[1]; |
811 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | 827 | ratesArray[rate5_5s] = |
812 | targetPowerCck.tPow2x[2]; | 828 | ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; |
813 | ratesArray[rate11s] = ratesArray[rate11l] = | 829 | ratesArray[rate11s] = |
814 | targetPowerCck.tPow2x[3]; | 830 | ratesArray[rate11l] = targetPowerCck.tPow2x[3]; |
815 | } | 831 | } |
816 | if (IS_CHAN_HT40(chan)) { | 832 | if (IS_CHAN_HT40(chan)) { |
817 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) | 833 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) |
@@ -820,10 +836,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
820 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | 836 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; |
821 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | 837 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; |
822 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | 838 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; |
839 | |||
823 | if (IS_CHAN_2GHZ(chan)) | 840 | if (IS_CHAN_2GHZ(chan)) |
824 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | 841 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; |
825 | } | 842 | } |
826 | 843 | ||
844 | #undef CMP_CTL | ||
845 | #undef CMP_NO_CTL | ||
827 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | 846 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN |
828 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | 847 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN |
829 | } | 848 | } |
@@ -834,10 +853,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
834 | u8 twiceMaxRegulatoryPower, | 853 | u8 twiceMaxRegulatoryPower, |
835 | u8 powerLimit) | 854 | u8 powerLimit) |
836 | { | 855 | { |
837 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | ||
838 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | ||
839 | |||
840 | struct ath_common *common = ath9k_hw_common(ah); | ||
841 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 856 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
842 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 857 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
843 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | 858 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; |
@@ -871,6 +886,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
871 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | 886 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; |
872 | } | 887 | } |
873 | 888 | ||
889 | /* OFDM power per rate */ | ||
874 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 890 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
875 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | 891 | ATH9K_POW_SM(ratesArray[rate18mb], 24) |
876 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | 892 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) |
@@ -883,6 +899,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
883 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | 899 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) |
884 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | 900 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); |
885 | 901 | ||
902 | /* CCK power per rate */ | ||
886 | if (IS_CHAN_2GHZ(chan)) { | 903 | if (IS_CHAN_2GHZ(chan)) { |
887 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | 904 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, |
888 | ATH9K_POW_SM(ratesArray[rate2s], 24) | 905 | ATH9K_POW_SM(ratesArray[rate2s], 24) |
@@ -896,6 +913,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
896 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | 913 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); |
897 | } | 914 | } |
898 | 915 | ||
916 | /* HT20 power per rate */ | ||
899 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | 917 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, |
900 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | 918 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
901 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | 919 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
@@ -908,6 +926,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
908 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | 926 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
909 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | 927 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); |
910 | 928 | ||
929 | /* HT40 power per rate */ | ||
911 | if (IS_CHAN_HT40(chan)) { | 930 | if (IS_CHAN_HT40(chan)) { |
912 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 931 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
913 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | 932 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, |
@@ -943,6 +962,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
943 | ht40PowerIncForPdadc, 0)); | 962 | ht40PowerIncForPdadc, 0)); |
944 | } | 963 | } |
945 | 964 | ||
965 | /* Dup/Ext power per rate */ | ||
946 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | 966 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, |
947 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | 967 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
948 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | 968 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
@@ -960,21 +980,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
960 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | 980 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; |
961 | else | 981 | else |
962 | regulatory->max_power_level = ratesArray[i]; | 982 | regulatory->max_power_level = ratesArray[i]; |
963 | |||
964 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
965 | case 1: | ||
966 | break; | ||
967 | case 2: | ||
968 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
969 | break; | ||
970 | case 3: | ||
971 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
972 | break; | ||
973 | default: | ||
974 | ath_print(common, ATH_DBG_EEPROM, | ||
975 | "Invalid chainmask configuration\n"); | ||
976 | break; | ||
977 | } | ||
978 | } | 983 | } |
979 | 984 | ||
980 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, | 985 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, |