]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - drivers/net/wireless/ath/ath5k/phy.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[mirror_ubuntu-kernels.git] / drivers / net / wireless / ath / ath5k / phy.c
index 492cbb15720d2076667681a8860a7ed866a2df5f..61da913e7c8fb05a7492ffefc7be9b06b4fc0662 100644 (file)
@@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
 \**********************/
 
 /*
- * This code is used to optimize rf gain on different environments
+ * This code is used to optimize RF gain on different environments
  * (temperature mostly) based on feedback from a power detector.
  *
  * It's only used on RF5111 and RF5112, later RF chips seem to have
@@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
 }
 
 /* Perform gain_F adjustment by choosing the right set
- * of parameters from rf gain optimization ladder */
+ * of parameters from RF gain optimization ladder */
 static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
 {
        const struct ath5k_gain_opt *go;
@@ -367,7 +367,7 @@ done:
        return ret;
 }
 
-/* Main callback for thermal rf gain calibration engine
+/* Main callback for thermal RF gain calibration engine
  * Check for a new gain reading and schedule an adjustment
  * if needed.
  *
@@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
        u32 data, type;
        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 
-       ATH5K_TRACE(ah->ah_sc);
-
        if (ah->ah_rf_banks == NULL ||
        ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
                return AR5K_RFGAIN_INACTIVE;
@@ -435,7 +433,7 @@ done:
        return ah->ah_gain.g_state;
 }
 
-/* Write initial rf gain table to set the RF sensitivity
+/* Write initial RF gain table to set the RF sensitivity
  * this one works on all RF chips and has nothing to do
  * with gain_F calibration */
 int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
@@ -498,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
 
 
 /*
- * Setup RF registers by writing rf buffer on hw
+ * Setup RF registers by writing RF buffer on hw
  */
 int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
                unsigned int mode)
@@ -573,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
                return -EINVAL;
        }
 
-       /* If it's the first time we set rf buffer, allocate
+       /* If it's the first time we set RF buffer, allocate
         * ah->ah_rf_banks based on ah->ah_rf_banks_size
         * we set above */
        if (ah->ah_rf_banks == NULL) {
@@ -1167,7 +1165,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
  * The median of the values in the history is then loaded into the
  * hardware for its own use for RSSI and CCA measurements.
  */
-static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
+void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 {
        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
        u32 val;
@@ -1248,7 +1246,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 /*
  * Perform a PHY calibration on RF5110
  * -Fix BPSK/QAM Constellation (I/Q correction)
- * -Calculate Noise Floor
  */
 static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
                struct ieee80211_channel *channel)
@@ -1260,7 +1257,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
         * Disable beacons and RX/TX queues, wait
         */
        AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
-               AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+               AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
        beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
        ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
 
@@ -1335,35 +1332,31 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
                return ret;
        }
 
-       ath5k_hw_update_noise_floor(ah);
-
        /*
         * Re-enable RX/TX and beacons
         */
        AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
-               AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+               AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
        ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
 
        return 0;
 }
 
 /*
- * Perform a PHY calibration on RF5111/5112 and newer chips
+ * Perform I/Q calibration on RF5111/5112 and newer chips
  */
-static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
-               struct ieee80211_channel *channel)
+static int
+ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
 {
        u32 i_pwr, q_pwr;
        s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
        int i;
-       ATH5K_TRACE(ah->ah_sc);
 
        if (!ah->ah_calibration ||
                ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
-               goto done;
+               return 0;
 
        /* Calibration has finished, get the results and re-run */
-
        /* work around empty results which can apparently happen on 5212 */
        for (i = 0; i <= 10; i++) {
                iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
@@ -1384,7 +1377,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
 
        /* protect against divide by 0 and loss of sign bits */
        if (i_coffd == 0 || q_coffd < 2)
-               goto done;
+               return 0;
 
        i_coff = (-iq_corr) / i_coffd;
        i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
@@ -1410,17 +1403,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
                        AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
        AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
 
-done:
-
-       /* TODO: Separate noise floor calibration from I/Q calibration
-        * since noise floor calibration interrupts rx path while I/Q
-        * calibration doesn't. We don't need to run noise floor calibration
-        * as often as I/Q calibration.*/
-       ath5k_hw_update_noise_floor(ah);
-
-       /* Initiate a gain_F calibration */
-       ath5k_hw_request_rfgain_probe(ah);
-
        return 0;
 }
 
@@ -1434,8 +1416,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
 
        if (ah->ah_radio == AR5K_RF5110)
                ret = ath5k_hw_rf5110_calibrate(ah, channel);
-       else
-               ret = ath5k_hw_rf511x_calibrate(ah, channel);
+       else {
+               ret = ath5k_hw_rf511x_iq_calibrate(ah);
+               ath5k_hw_request_rfgain_probe(ah);
+       }
 
        return ret;
 }
@@ -1598,7 +1582,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
                        else if (curr_sym_off >= 31 && curr_sym_off <= 46)
                                mag_mask[2] |=
                                        plt_mag_map << (curr_sym_off - 31) * 2;
-                       else if (curr_sym_off >= 46 && curr_sym_off <= 53)
+                       else if (curr_sym_off >= 47 && curr_sym_off <= 53)
                                mag_mask[3] |=
                                        plt_mag_map << (curr_sym_off - 47) * 2;
 
@@ -1693,7 +1677,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
 
 int ath5k_hw_phy_disable(struct ath5k_hw *ah)
 {
-       ATH5K_TRACE(ah->ah_sc);
        /*Just a try M.F.*/
        ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
 
@@ -1709,8 +1692,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
        u32 srev;
        u16 ret;
 
-       ATH5K_TRACE(ah->ah_sc);
-
        /*
         * Set the radio chip access register
         */
@@ -1755,8 +1736,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
 static void /*TODO:Boundary check*/
 ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
 {
-       ATH5K_TRACE(ah->ah_sc);
-
        if (ah->ah_version != AR5K_AR5210)
                ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
 }
@@ -1789,19 +1768,50 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
 
        if (enable) {
                AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
-                               AR5K_PHY_RESTART_DIV_GC, 0xc);
+                               AR5K_PHY_RESTART_DIV_GC, 4);
 
                AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
                                        AR5K_PHY_FAST_ANT_DIV_EN);
        } else {
                AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
-                               AR5K_PHY_RESTART_DIV_GC, 0x8);
+                               AR5K_PHY_RESTART_DIV_GC, 0);
 
                AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
                                        AR5K_PHY_FAST_ANT_DIV_EN);
        }
 }
 
+void
+ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode)
+{
+       u8 ant0, ant1;
+
+       /*
+        * In case a fixed antenna was set as default
+        * use the same switch table twice.
+        */
+       if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A)
+               ant0 = ant1 = AR5K_ANT_SWTABLE_A;
+       else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B)
+               ant0 = ant1 = AR5K_ANT_SWTABLE_B;
+       else {
+               ant0 = AR5K_ANT_SWTABLE_A;
+               ant1 = AR5K_ANT_SWTABLE_B;
+       }
+
+       /* Set antenna idle switch table */
+       AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+                       AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+                       (ah->ah_ant_ctl[ee_mode][AR5K_ANT_CTL] |
+                       AR5K_PHY_ANT_CTL_TXRX_EN));
+
+       /* Set antenna switch tables */
+       ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant0],
+               AR5K_PHY_ANT_SWITCH_TABLE_0);
+       ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant1],
+               AR5K_PHY_ANT_SWITCH_TABLE_1);
+}
+
 /*
  * Set antenna operating mode
  */
@@ -1823,8 +1833,6 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
 
        def_ant = ah->ah_def_ant;
 
-       ATH5K_TRACE(ah->ah_sc);
-
        switch (channel->hw_value & CHANNEL_MODES) {
        case CHANNEL_A:
        case CHANNEL_T:
@@ -1923,6 +1931,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
        if (sta_id1)
                AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1);
 
+       ath5k_hw_set_antenna_switch(ah, ee_mode);
        /* Note: set diversity before default antenna
         * because it won't work correctly */
        ath5k_hw_set_fast_div(ah, ee_mode, fast_div);
@@ -2978,7 +2987,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
 
 
 /*
- * Set transmition power
+ * Set transmission power
  */
 int
 ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
@@ -2988,7 +2997,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
        u8 type;
        int ret;
 
-       ATH5K_TRACE(ah->ah_sc);
        if (txpower > AR5K_TUNE_MAX_TXPOWER) {
                ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
                return -EINVAL;
@@ -3027,9 +3035,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
        /* Limit max power if we have a CTL available */
        ath5k_get_max_ctl_power(ah, channel);
 
-       /* FIXME: Tx power limit for this regdomain
-        * XXX: Mac80211/CRDA will do that anyway ? */
-
        /* FIXME: Antenna reduction stuff */
 
        /* FIXME: Limit power on turbo modes */
@@ -3084,8 +3089,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
        struct ieee80211_channel *channel = ah->ah_current_channel;
        u8 ee_mode;
 
-       ATH5K_TRACE(ah->ah_sc);
-
        switch (channel->hw_value & CHANNEL_MODES) {
        case CHANNEL_A:
        case CHANNEL_T: