aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
authorSenthil Balasubramanian <senthilkumar@atheros.com>2009-09-18 05:38:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:40 -0400
commite41f0bfcb130d9f17cf5ee8e46d739c1bebda963 (patch)
treed8a81b3e0cb3bb0b48ce711ae7684312ae69991a /drivers/net/wireless/ath/ath9k
parentebb90cfc32f0d7ee55be7787ce7d88e521e9ed01 (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')
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c102
3 files changed, 104 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 33492741735d..2f2993b50e2f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -134,6 +134,7 @@
134#define AR5416_EEP_MINOR_VER_17 0x11 134#define AR5416_EEP_MINOR_VER_17 0x11
135#define AR5416_EEP_MINOR_VER_19 0x13 135#define AR5416_EEP_MINOR_VER_19 0x13
136#define AR5416_EEP_MINOR_VER_20 0x14 136#define AR5416_EEP_MINOR_VER_20 0x14
137#define AR5416_EEP_MINOR_VER_21 0x15
137#define AR5416_EEP_MINOR_VER_22 0x16 138#define AR5416_EEP_MINOR_VER_22 0x16
138 139
139#define AR5416_NUM_5G_CAL_PIERS 8 140#define AR5416_NUM_5G_CAL_PIERS 8
@@ -154,7 +155,7 @@
154#define AR5416_BCHAN_UNUSED 0xFF 155#define AR5416_BCHAN_UNUSED 0xFF
155#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 156#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
156#define AR5416_MAX_CHAINS 3 157#define AR5416_MAX_CHAINS 3
157#define AR5416_PWR_TABLE_OFFSET -5 158#define AR5416_PWR_TABLE_OFFSET_DB -5
158 159
159/* Rx gain type values */ 160/* Rx gain type values */
160#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 161#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
@@ -302,7 +303,7 @@ struct base_eep_header {
302 u8 txGainType; 303 u8 txGainType;
303 u8 rcChainMask; 304 u8 rcChainMask;
304 u8 desiredScaleCCK; 305 u8 desiredScaleCCK;
305 u8 power_table_offset; 306 u8 pwr_table_offset;
306 u8 frac_n_5g; 307 u8 frac_n_5g;
307 u8 futureBase_3[21]; 308 u8 futureBase_3[21];
308} __packed; 309} __packed;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 2a27b1d51a1b..58167d861dc6 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -210,6 +210,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
210 return pBase->rxMask; 210 return pBase->rxMask;
211 case EEP_FRAC_N_5G: 211 case EEP_FRAC_N_5G:
212 return 0; 212 return 0;
213 case EEP_PWR_TABLE_OFFSET:
214 return AR5416_PWR_TABLE_OFFSET_DB;
213 default: 215 default:
214 return 0; 216 return 0;
215 } 217 }
@@ -753,7 +755,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
753 755
754 if (AR_SREV_9280_10_OR_LATER(ah)) { 756 if (AR_SREV_9280_10_OR_LATER(ah)) {
755 for (i = 0; i < Ar5416RateSize; i++) 757 for (i = 0; i < Ar5416RateSize; i++)
756 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; 758 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
757 } 759 }
758 760
759 /* OFDM power per rate */ 761 /* OFDM power per rate */
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
749static 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
790static 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
744static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, 819static 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