diff options
author | Vivek Natarajan <vnatarajan@atheros.com> | 2009-09-18 05:33:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-07 16:39:38 -0400 |
commit | 0b98eaaa02965fb06dee4ad8c605bb3c93df2c98 (patch) | |
tree | 564b56fb04c8e4a199f5bb0470570f870a5e9c74 | |
parent | 181af387033e20065e94363d07ecbace7738278c (diff) |
ath9k: Add Calibration checks
* Prevent divide-by-zero errors in IQ Calibration.
* Do not run temperature compensation if initPDADC or currPDADC is zero.
* Also, introduce a separate function for handling OLC for AR9287.
Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 78 |
1 files changed, 50 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 36c5f89e2fc7..9c46b54d2a98 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -403,7 +403,8 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
403 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | 403 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; |
404 | qCoffDenom = powerMeasQ / 64; | 404 | qCoffDenom = powerMeasQ / 64; |
405 | 405 | ||
406 | if (powerMeasQ != 0) { | 406 | if ((powerMeasQ != 0) && (iCoffDenom != 0) && |
407 | (qCoffDenom != 0)) { | ||
407 | iCoff = iqCorrMeas / iCoffDenom; | 408 | iCoff = iqCorrMeas / iCoffDenom; |
408 | qCoff = powerMeasI / qCoffDenom - 64; | 409 | qCoff = powerMeasI / qCoffDenom - 64; |
409 | ath_print(common, ATH_DBG_CALIBRATE, | 410 | ath_print(common, ATH_DBG_CALIBRATE, |
@@ -746,44 +747,65 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
746 | return nf; | 747 | return nf; |
747 | } | 748 | } |
748 | 749 | ||
749 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | 750 | static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah) |
750 | { | 751 | { |
751 | u32 rddata, i; | 752 | u32 rddata; |
752 | int delta, currPDADC, regval, slope; | 753 | int32_t delta, currPDADC, slope; |
753 | 754 | ||
754 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | 755 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); |
755 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | 756 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); |
756 | 757 | ||
758 | if (ah->initPDADC == 0 || currPDADC == 0) { | ||
759 | /* | ||
760 | * Zero value indicates that no frames have been transmitted yet, | ||
761 | * can't do temperature compensation until frames are transmitted. | ||
762 | */ | ||
763 | return; | ||
764 | } else { | ||
765 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | ||
766 | |||
767 | if (slope == 0) { /* to avoid divide by zero case */ | ||
768 | delta = 0; | ||
769 | } else { | ||
770 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | ||
771 | } | ||
772 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | ||
773 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
774 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | ||
775 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | ||
780 | { | ||
781 | u32 rddata, i; | ||
782 | int delta, currPDADC, regval; | ||
757 | 783 | ||
758 | if (OLC_FOR_AR9287_10_LATER) { | 784 | if (OLC_FOR_AR9287_10_LATER) { |
785 | ath9k_olc_temp_compensation_9287(ah); | ||
786 | } else { | ||
787 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | ||
788 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | ||
789 | |||
759 | if (ah->initPDADC == 0 || currPDADC == 0) { | 790 | if (ah->initPDADC == 0 || currPDADC == 0) { |
760 | return; | 791 | return; |
761 | } else { | 792 | } else { |
762 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | 793 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) |
763 | if (slope == 0) | 794 | delta = (currPDADC - ah->initPDADC + 4) / 8; |
764 | delta = 0; | ||
765 | else | 795 | else |
766 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | 796 | delta = (currPDADC - ah->initPDADC + 5) / 10; |
767 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | 797 | |
768 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | 798 | if (delta != ah->PDADCdelta) { |
769 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | 799 | ah->PDADCdelta = delta; |
770 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | 800 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { |
771 | } | 801 | regval = ah->originalGain[i] - delta; |
772 | } else { | 802 | if (regval < 0) |
773 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) | 803 | regval = 0; |
774 | delta = (currPDADC - ah->initPDADC + 4) / 8; | 804 | |
775 | else | 805 | REG_RMW_FIELD(ah, |
776 | delta = (currPDADC - ah->initPDADC + 5) / 10; | 806 | AR_PHY_TX_GAIN_TBL1 + i * 4, |
777 | 807 | AR_PHY_TX_GAIN, regval); | |
778 | if (delta != ah->PDADCdelta) { | 808 | } |
779 | ah->PDADCdelta = delta; | ||
780 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | ||
781 | regval = ah->originalGain[i] - delta; | ||
782 | if (regval < 0) | ||
783 | regval = 0; | ||
784 | |||
785 | REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, | ||
786 | AR_PHY_TX_GAIN, regval); | ||
787 | } | 809 | } |
788 | } | 810 | } |
789 | } | 811 | } |