diff options
author | Senthil Balasubramanian <senthilkumar@atheros.com> | 2009-09-18 05:38:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-07 16:39:40 -0400 |
commit | e41f0bfcb130d9f17cf5ee8e46d739c1bebda963 (patch) | |
tree | d8a81b3e0cb3bb0b48ce711ae7684312ae69991a /drivers/net/wireless/ath/ath9k/eeprom_def.c | |
parent | ebb90cfc32f0d7ee55be7787ce7d88e521e9ed01 (diff) |
ath9k: Fix bugs in handling TX power
* Get power table offset from the EEPROM instead of using
a hardcoded value of -5 if the EEPROM rev is >= 21.
* Add support in the 4k eeprom code for tx power offset
in case we have a 4k AR9280 implementation.
* Fix tx power accuracy at high powers.
Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/eeprom_def.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_def.c | 102 |
1 files changed, 98 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 8f04b644e2e6..404a0341242c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -291,6 +291,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | |||
291 | return pBase->frac_n_5g; | 291 | return pBase->frac_n_5g; |
292 | else | 292 | else |
293 | return 0; | 293 | return 0; |
294 | case EEP_PWR_TABLE_OFFSET: | ||
295 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21) | ||
296 | return pBase->pwr_table_offset; | ||
297 | else | ||
298 | return AR5416_PWR_TABLE_OFFSET_DB; | ||
294 | default: | 299 | default: |
295 | return 0; | 300 | return 0; |
296 | } | 301 | } |
@@ -741,6 +746,76 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
741 | return; | 746 | return; |
742 | } | 747 | } |
743 | 748 | ||
749 | static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, | ||
750 | u16 *gb, | ||
751 | u16 numXpdGain, | ||
752 | u16 pdGainOverlap_t2, | ||
753 | int8_t pwr_table_offset, | ||
754 | int16_t *diff) | ||
755 | |||
756 | { | ||
757 | u16 k; | ||
758 | |||
759 | /* Prior to writing the boundaries or the pdadc vs. power table | ||
760 | * into the chip registers the default starting point on the pdadc | ||
761 | * vs. power table needs to be checked and the curve boundaries | ||
762 | * adjusted accordingly | ||
763 | */ | ||
764 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
765 | u16 gb_limit; | ||
766 | |||
767 | if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { | ||
768 | /* get the difference in dB */ | ||
769 | *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); | ||
770 | /* get the number of half dB steps */ | ||
771 | *diff *= 2; | ||
772 | /* change the original gain boundary settings | ||
773 | * by the number of half dB steps | ||
774 | */ | ||
775 | for (k = 0; k < numXpdGain; k++) | ||
776 | gb[k] = (u16)(gb[k] - *diff); | ||
777 | } | ||
778 | /* Because of a hardware limitation, ensure the gain boundary | ||
779 | * is not larger than (63 - overlap) | ||
780 | */ | ||
781 | gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); | ||
782 | |||
783 | for (k = 0; k < numXpdGain; k++) | ||
784 | gb[k] = (u16)min(gb_limit, gb[k]); | ||
785 | } | ||
786 | |||
787 | return *diff; | ||
788 | } | ||
789 | |||
790 | static void ath9k_adjust_pdadc_values(struct ath_hw *ah, | ||
791 | int8_t pwr_table_offset, | ||
792 | int16_t diff, | ||
793 | u8 *pdadcValues) | ||
794 | { | ||
795 | #define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) | ||
796 | u16 k; | ||
797 | |||
798 | /* If this is a board that has a pwrTableOffset that differs from | ||
799 | * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the | ||
800 | * pdadc vs pwr table needs to be adjusted prior to writing to the | ||
801 | * chip. | ||
802 | */ | ||
803 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
804 | if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { | ||
805 | /* shift the table to start at the new offset */ | ||
806 | for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) { | ||
807 | pdadcValues[k] = pdadcValues[k + diff]; | ||
808 | } | ||
809 | |||
810 | /* fill the back of the table */ | ||
811 | for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { | ||
812 | pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | #undef NUM_PDADC | ||
817 | } | ||
818 | |||
744 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | 819 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, |
745 | struct ath9k_channel *chan, | 820 | struct ath9k_channel *chan, |
746 | int16_t *pTxPowerIndexOffset) | 821 | int16_t *pTxPowerIndexOffset) |
@@ -756,15 +831,18 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
756 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | 831 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; |
757 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | 832 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; |
758 | u16 numPiers, i, j; | 833 | u16 numPiers, i, j; |
759 | int16_t tMinCalPower; | 834 | int16_t tMinCalPower, diff = 0; |
760 | u16 numXpdGain, xpdMask; | 835 | u16 numXpdGain, xpdMask; |
761 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | 836 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; |
762 | u32 reg32, regOffset, regChainOffset; | 837 | u32 reg32, regOffset, regChainOffset; |
763 | int16_t modalIdx; | 838 | int16_t modalIdx; |
839 | int8_t pwr_table_offset; | ||
764 | 840 | ||
765 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | 841 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; |
766 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | 842 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; |
767 | 843 | ||
844 | pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET); | ||
845 | |||
768 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | 846 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= |
769 | AR5416_EEP_MINOR_VER_2) { | 847 | AR5416_EEP_MINOR_VER_2) { |
770 | pdGainOverlap_t2 = | 848 | pdGainOverlap_t2 = |
@@ -844,6 +922,13 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
844 | numXpdGain); | 922 | numXpdGain); |
845 | } | 923 | } |
846 | 924 | ||
925 | diff = ath9k_change_gain_boundary_setting(ah, | ||
926 | gainBoundaries, | ||
927 | numXpdGain, | ||
928 | pdGainOverlap_t2, | ||
929 | pwr_table_offset, | ||
930 | &diff); | ||
931 | |||
847 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 932 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
848 | if (OLC_FOR_AR9280_20_LATER) { | 933 | if (OLC_FOR_AR9280_20_LATER) { |
849 | REG_WRITE(ah, | 934 | REG_WRITE(ah, |
@@ -864,6 +949,10 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
864 | } | 949 | } |
865 | } | 950 | } |
866 | 951 | ||
952 | |||
953 | ath9k_adjust_pdadc_values(ah, pwr_table_offset, | ||
954 | diff, pdadcValues); | ||
955 | |||
867 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | 956 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; |
868 | for (j = 0; j < 32; j++) { | 957 | for (j = 0; j < 32; j++) { |
869 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | 958 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | |
@@ -1199,8 +1288,13 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1199 | } | 1288 | } |
1200 | 1289 | ||
1201 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1290 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1202 | for (i = 0; i < Ar5416RateSize; i++) | 1291 | for (i = 0; i < Ar5416RateSize; i++) { |
1203 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | 1292 | int8_t pwr_table_offset; |
1293 | |||
1294 | pwr_table_offset = ah->eep_ops->get_eeprom(ah, | ||
1295 | EEP_PWR_TABLE_OFFSET); | ||
1296 | ratesArray[i] -= pwr_table_offset * 2; | ||
1297 | } | ||
1204 | } | 1298 | } |
1205 | 1299 | ||
1206 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 1300 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
@@ -1299,7 +1393,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1299 | 1393 | ||
1300 | if (AR_SREV_9280_10_OR_LATER(ah)) | 1394 | if (AR_SREV_9280_10_OR_LATER(ah)) |
1301 | regulatory->max_power_level = | 1395 | regulatory->max_power_level = |
1302 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | 1396 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; |
1303 | else | 1397 | else |
1304 | regulatory->max_power_level = ratesArray[i]; | 1398 | regulatory->max_power_level = ratesArray[i]; |
1305 | 1399 | ||