aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-06-01 05:44:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-03 14:10:46 -0400
commita55f858852e4345d0a31af593c46738ca8614bff (patch)
tree0859e47e0d7414658937139c85a8bc0307ad3351 /drivers/net/wireless/ath
parent79d7f4bcf8519abbea46d909ff01a1358b431e1d (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.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c287
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
261void 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
261int ath9k_hw_eeprom_init(struct ath_hw *ah) 282int 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);
706u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, 706u16 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);
708void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
708int ath9k_hw_eeprom_init(struct ath_hw *ah); 709int 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, &centers); 640 ath9k_hw_get_channel_centers(ah, chan, &centers);
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
980static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, 985static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,