]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ath9k_hw: Fix instable target power control b/w CCK/OFDM
authorRajkumar Manoharan <rmanoharan@atheros.com>
Wed, 6 Apr 2011 16:12:52 +0000 (21:42 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 12 Apr 2011 20:57:35 +0000 (16:57 -0400)
The problem is that when the attenuation is increased,
the rate will start to drop from MCS7 -> MCS6, and finally
will see MCS1 -> CCK_11Mbps. When the rate is changed b/w
CCK and OFDM, it will use register desired_scale to calculate
how much tx gain need to change.

The output power with the same tx gain for CCK and OFDM modulated
signals are different. This difference is constant for AR9280
but not AR9285/AR9271. It has different PA architecture
a constant. So it should be calibrated against this PA
characteristic.

The driver has to read the calibrated values from EEPROM and set
the tx power registers accordingly.

Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
Acked-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ar9002_phy.h
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c

index 37663dbbcf57959f9b9afb15fe5b15e0efd613cd..47780ef1c892e56317d48e4fdc500bf34fc7c17f 100644 (file)
 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000
 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19
 
+#define AR_PHY_TX_PWRCTRL8       0xa278
+
 #define AR_PHY_TX_PWRCTRL9       0xa27C
+
+#define AR_PHY_TX_PWRCTRL10       0xa394
 #define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00
 #define AR_PHY_TX_DESIRED_SCALE_CCK_S      10
 #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000
 
 #define AR_PHY_CH0_TX_PWRCTRL11  0xa398
 #define AR_PHY_CH1_TX_PWRCTRL11  0xb398
+#define AR_PHY_CH0_TX_PWRCTRL12  0xa3dc
+#define AR_PHY_CH0_TX_PWRCTRL13  0xa3e0
 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00
 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
 
index bd82447f5b780b26df88c138191610c34e2a582b..3e316133f114c9b6765b9002d168e157fbccdaba 100644 (file)
@@ -436,7 +436,11 @@ struct modal_eep_4k_header {
        u8 db2_2:4, db2_3:4;
        u8 db2_4:4, reserved:4;
 #endif
-       u8 futureModal[4];
+       u8 tx_diversity;
+       u8 flc_pwr_thresh;
+       u8 bb_scale_smrt_antenna;
+#define EEP_4K_BB_DESIRED_SCALE_MASK   0x1f
+       u8 futureModal[1];
        struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
 } __packed;
 
index bc77a308c901eaf8ccd4c111f2600a754d0774b9..6f714dd723653032c0622b8821852749b4254f38 100644 (file)
@@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 {
        struct modal_eep_4k_header *pModal;
        struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+       struct base_eep_header_4k *pBase = &eep->baseEepHeader;
        u8 txRxAttenLocal;
        u8 ob[5], db1[5], db2[5];
        u8 ant_div_control1, ant_div_control2;
@@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
                                      AR_PHY_SETTLING_SWITCH,
                                      pModal->swSettleHt40);
        }
+       if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
+               u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+                               EEP_4K_BB_DESIRED_SCALE_MASK);
+               if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+                       u32 pwrctrl, mask, clr;
+
+                       mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+                       mask = BIT(0)|BIT(5)|BIT(15);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+                       mask = BIT(0)|BIT(5);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+               }
+       }
 }
 
 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)