rt2x00: Split rt61/rt73 antenna selection into RX and TX antenna
authorIvo van Doorn <ivdoorn@gmail.com>
Sat, 27 Oct 2007 11:39:57 +0000 (13:39 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 23:02:57 +0000 (15:02 -0800)
Based on investigation of the legacy drivers, I have made the
following assumptions of the antenna setup:
 - R77 is the TX antenna configuration
 - RF2529 fetches default antenna selection from NIC eeprom word

With these assumptions we can change the antenna configuration
to correctly read both antenna setup values and correctly
configure the antenna. And we can now also configure the antenna
for RF2529 without a double antenna.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h

index c57d39002bfb01872f56fe29499a4c37447d8fb6..7c97761034e7a47b7a70cd5251f6bddc5cdddf9a 100644 (file)
@@ -424,6 +424,29 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
                          !rt2x00_rf(&rt2x00dev->chip, RF5225));
 
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 3);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
        switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
@@ -433,11 +456,6 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
-               if (rt2x00dev->curr_hwmode == HWMODE_A)
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
                break;
        case ANTENNA_SW_DIVERSITY:
                /*
@@ -449,11 +467,6 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        case ANTENNA_B:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
-               if (rt2x00dev->curr_hwmode == HWMODE_A)
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
                break;
        }
 
@@ -478,13 +491,35 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
                          !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
 
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 3);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
        switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
                break;
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
                break;
        case ANTENNA_SW_DIVERSITY:
                /*
@@ -495,7 +530,6 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
                 */
        case ANTENNA_B:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
                break;
        }
 
@@ -530,74 +564,75 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
        u8 r3;
        u8 r4;
        u8 r77;
+       u8 rx_ant;
 
        rt61pci_bbp_read(rt2x00dev, 3, &r3);
        rt61pci_bbp_read(rt2x00dev, 4, &r4);
        rt61pci_bbp_read(rt2x00dev, 77, &r77);
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+       rx_ant = !!(rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED) & 2);
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
 
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
-           rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 1);
-               rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
-       } else if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY)) {
-               if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED) >= 2) {
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
-                       rt61pci_bbp_write(rt2x00dev, 77, r77);
-               }
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
-       } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
-                  rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 3);
+               break;
+       }
 
-               switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
-               case 0:
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
-                       break;
-               case 1:
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
-                       break;
-               case 2:
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
-                       break;
-               case 3:
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
-                       break;
-               }
-       } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
-                  !rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_A:
+               rt61pci_config_antenna_2529_rx(rt2x00dev, 0, rx_ant);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt61pci_config_antenna_2529_rx(rt2x00dev, 1, rx_ant);
+               break;
+       }
+
+       /*
+        * FIXME: We are using the default antenna setup to
+        * determine the remaining settings. This because we
+        * need to know what the EEPROM indicated.
+        * It is however unclear if this is required, and overall
+        * using the default antenna settings here is incorrect
+        * since mac80211 might have told us to use fixed settings.
+        */
+       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+       else
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
 
-               switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
-               case 0:
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
-                       rt61pci_bbp_write(rt2x00dev, 77, r77);
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
-                       break;
-               case 1:
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
-                       rt61pci_bbp_write(rt2x00dev, 77, r77);
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
-                       break;
-               case 2:
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
-                       rt61pci_bbp_write(rt2x00dev, 77, r77);
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
-                       break;
-               case 3:
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
-                       rt61pci_bbp_write(rt2x00dev, 77, r77);
-                       rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
-                       break;
-               }
-       }
+       rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+                         (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) &&
+                         (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY));
 
+       rt61pci_bbp_write(rt2x00dev, 77, r77);
        rt61pci_bbp_write(rt2x00dev, 3, r3);
        rt61pci_bbp_write(rt2x00dev, 4, r4);
 }
@@ -2030,6 +2065,12 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
                return -ENODEV;
        }
 
+       /*
+        * Determine number of antenna's.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
+               __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+
        /*
         * Identify default antenna configuration.
         */
@@ -2044,12 +2085,6 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
                __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
 
-       /*
-        * Determine number of antenna's.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
-               __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
-
        /*
         * Detect if this device has an hardware controlled radio.
         */
@@ -2077,6 +2112,38 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
                __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
 
+       /*
+        * When working with a RF2529 chip without double antenna
+        * the antenna settings should be gathered from the NIC
+        * eeprom word.
+        */
+       if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
+           !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+               switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
+               case 0:
+                       rt2x00dev->default_ant.tx = ANTENNA_B;
+                       rt2x00dev->default_ant.rx = ANTENNA_A;
+                       break;
+               case 1:
+                       rt2x00dev->default_ant.tx = ANTENNA_B;
+                       rt2x00dev->default_ant.rx = ANTENNA_B;
+                       break;
+               case 2:
+                       rt2x00dev->default_ant.tx = ANTENNA_A;
+                       rt2x00dev->default_ant.rx = ANTENNA_A;
+                       break;
+               case 3:
+                       rt2x00dev->default_ant.tx = ANTENNA_A;
+                       rt2x00dev->default_ant.rx = ANTENNA_B;
+                       break;
+               }
+
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
+                       rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY))
+                       rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY;
+       }
+
        /*
         * Store led settings, for correct led behaviour.
         * If the eeprom value is invalid,
index 6721d7dd32bc67222f2feae5730fc6f2050cc610..ba51016494031611096b423ba300d7fc9f6f24fa 100644 (file)
@@ -1083,7 +1083,7 @@ struct hw_pairwise_ta_entry {
 /*
  * R77
  */
-#define BBP_R77_PAIR                   FIELD8(0x03)
+#define BBP_R77_TX_ANTENNA             FIELD8(0x03)
 
 /*
  * RF registers
index e3d5e78661ea64c3aa670ddacb7ef28766a8964e..b9d5310c386f503a8c8dbf85d0e00f05152d57f1 100644 (file)
@@ -408,6 +408,29 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
 
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 3);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
        switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
@@ -417,11 +440,6 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
-               if (rt2x00dev->curr_hwmode == HWMODE_A)
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
                break;
        case ANTENNA_SW_DIVERSITY:
                /*
@@ -433,11 +451,6 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        case ANTENNA_B:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
-               if (rt2x00dev->curr_hwmode == HWMODE_A)
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
                break;
        }
 
@@ -461,13 +474,35 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
                          !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
 
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_SW_DIVERSITY:
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * NOTE: We should never come here because rt2x00lib is
+                * supposed to catch this and send us the correct antenna
+                * explicitely. However we are nog going to bug about this.
+                * Instead, just default to antenna B.
+                */
+       case ANTENNA_B:
+               rt2x00_set_field8(&r77, BBP_R77_TX_ANTENNA, 3);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
        switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
                break;
        case ANTENNA_A:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
                break;
        case ANTENNA_SW_DIVERSITY:
                /*
@@ -478,7 +513,6 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
                 */
        case ANTENNA_B:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
                break;
        }
 
index f0951519f74b32592077587d22dfa304d5b9e9fe..13f479c7da0d5023e619feb5dbc06601ba661689 100644 (file)
@@ -719,7 +719,7 @@ struct hw_pairwise_ta_entry {
 /*
  * R77
  */
-#define BBP_R77_PAIR                   FIELD8(0x03)
+#define BBP_R77_TX_ANTENNA             FIELD8(0x03)
 
 /*
  * RF registers