From 1ef7772f766c72f9b767d32cc0b26d457a34ace2 Mon Sep 17 00:00:00 2001
From: Ivo van Doorn <IvDoorn@gmail.com>
Date: Sun, 8 Feb 2009 00:09:22 +0100
Subject: [PATCH] rt2x00: Channel HT40+/- fixes (rt2800usb)

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |  107 ++++++++++++++++--------------
 drivers/net/wireless/rt2x00/rt2800usb.h |    5 +-
 2 files changed, 61 insertions(+), 51 deletions(-)

--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -641,7 +641,7 @@ static void rt2800usb_config_ant(struct 
 		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
 		break;
 	case 2:
-		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 16);
+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
 		break;
 	case 3:
 		/* Do nothing */
@@ -691,6 +691,7 @@ static void rt2800usb_config_lna_gain(st
 }
 
 static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
+					  struct ieee80211_conf *conf,
 					  struct rf_channel *rf,
 					  struct channel_info *info)
 {
@@ -702,6 +703,7 @@ static void rt2800usb_config_channel_rt2
 	 * Determine antenna settings from EEPROM
 	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
 
@@ -742,8 +744,7 @@ static void rt2800usb_config_channel_rt2
 				   TXPOWER_G_TO_DEV(info->tx_power2));
 	}
 
-	rt2x00_set_field32(&rf->rf4, RF4_BW40,
-			   test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags));
+	rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
 
 	rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
 	rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
@@ -766,6 +767,7 @@ static void rt2800usb_config_channel_rt2
 }
 
 static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
+					  struct ieee80211_conf *conf,
 					  struct rf_channel *rf,
 					  struct channel_info *info)
 {
@@ -787,10 +789,12 @@ static void rt2800usb_config_channel_rt3
 	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
 	rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr);
 
-	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
-		rt2800usb_rfcsr_write(rt2x00dev, 24, rt2x00dev->calibration_bw40);
+	if (conf_is_ht40(conf))
+		rt2800usb_rfcsr_write(rt2x00dev, 24,
+				      rt2x00dev->calibration_bw40);
 	else
-		rt2800usb_rfcsr_write(rt2x00dev, 24, rt2x00dev->calibration_bw20);
+		rt2800usb_rfcsr_write(rt2x00dev, 24,
+				      rt2x00dev->calibration_bw20);
 
 	rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
@@ -798,46 +802,24 @@ static void rt2800usb_config_channel_rt3
 }
 
 static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_conf *conf,
 				     struct rf_channel *rf,
 				     struct channel_info *info)
 {
 	u32 reg;
 	unsigned int tx_pin;
 	u16 eeprom;
+	u8 bbp;
 
-	if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
-		rt2800usb_config_channel_rt2x(rt2x00dev, rf, info);
-	else
-		rt2800usb_config_channel_rt3x(rt2x00dev, rf, info);
-
-	tx_pin = 0;
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
-
+	/*
+	 * Determine antenna settings from EEPROM
+	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
 
-	/* Turn off unused PA or LNA when only 1T or 1R */
-	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) {
-		
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 0);
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 0);
-	}
-
-	/* Turn off unused PA or LNA when only 1T or 1R */
-	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) {
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 0);
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 0);
-	}
-
-	if (rf->channel > 14)
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);
+	if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
+		rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info);
 	else
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+		rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info);
 
 	/*
 	 * Change BBP settings
@@ -855,11 +837,6 @@ static void rt2800usb_config_channel(str
 			rt2800usb_bbp_write(rt2x00dev, 82, 0x84);
 			rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
 		}
-
-		rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, &reg);
-		rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 0);
-		rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 1);
-		rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg);
 	} else {
 		rt2800usb_bbp_write(rt2x00dev, 82, 0xf2);
 
@@ -867,15 +844,45 @@ static void rt2800usb_config_channel(str
 			rt2800usb_bbp_write(rt2x00dev, 75, 0x46);
 		else
 			rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
+	}
+
+	rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
+	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
+	rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg);
+
+	tx_pin = 0;
+
+	/* Turn on unused PA or LNA when not using 1T or 1R */
+	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) != 1) {
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+	}
 
-		rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, &reg);
-		rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 1);
-		rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 0);
-		rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg);
+	/* Turn on unused PA or LNA when not using 1T or 1R */
+	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) != 1) {
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
 	}
 
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
+
 	rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
 
+	rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
+	rt2800usb_bbp_write(rt2x00dev, 4, bbp);
+
+	rt2800usb_bbp_read(rt2x00dev, 3, &bbp);
+	rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2800usb_bbp_write(rt2x00dev, 3, bbp);
+
 	msleep(1);
 }
 
@@ -1008,8 +1015,8 @@ static void rt2800usb_config(struct rt2x
 	rt2800usb_config_lna_gain(rt2x00dev, libconf);
 
 	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-		rt2800usb_config_channel(rt2x00dev, &libconf->rf,
-					 &libconf->channel);
+		rt2800usb_config_channel(rt2x00dev, libconf->conf,
+					 &libconf->rf, &libconf->channel);
 	if (flags & IEEE80211_CONF_CHANGE_POWER)
 		rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
@@ -1643,7 +1650,7 @@ static u8 rt2800usb_init_rx_filter(struc
 
 	if (bw40) {
 		rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
-		rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0x10);
+		rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2);
 		rt2800usb_bbp_write(rt2x00dev, 4, bbp);
 	}
 
@@ -2777,14 +2784,14 @@ static const struct rt2x00lib_ops rt2800
 
 static const struct data_queue_desc rt2800usb_queue_rx = {
 	.entry_num		= RX_ENTRIES,
-	.data_size		= DATA_FRAME_SIZE,
+	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= RXD_DESC_SIZE + RXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct data_queue_desc rt2800usb_queue_tx = {
 	.entry_num		= TX_ENTRIES,
-	.data_size		= DATA_FRAME_SIZE,
+	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
--- a/drivers/net/wireless/rt2x00/rt2800usb.h
+++ b/drivers/net/wireless/rt2x00/rt2800usb.h
@@ -803,6 +803,7 @@
  * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
  */
 #define TX_BAND_CFG			0x132c
+#define TX_BAND_CFG_HT40_PLUS		FIELD32(0x00000001)
 #define TX_BAND_CFG_A			FIELD32(0x00000002)
 #define TX_BAND_CFG_BG			FIELD32(0x00000004)
 
@@ -1482,10 +1483,12 @@ struct mac_iveiv_entry {
  * BBP 3: RX Antenna
  */
 #define BBP3_RX_ANTENNA			FIELD8(0x18)
+#define BBP3_HT40_PLUS			FIELD8(0x20)
 
 /*
  * BBP 4: Bandwidth
  */
+#define BBP4_TX_BF			FIELD8(0x01)
 #define BBP4_BANDWIDTH			FIELD8(0x18)
 
 /*
@@ -1548,7 +1551,7 @@ struct mac_iveiv_entry {
 #define RF4_TXPOWER_A_7DBM_BOOST	FIELD32(0x00000040)
 #define RF4_TXPOWER_A			FIELD32(0x00000780)
 #define RF4_FREQ_OFFSET			FIELD32(0x001f8000)
-#define RF4_BW40			FIELD32(0x00200000)
+#define RF4_HT40			FIELD32(0x00200000)
 
 /*
  * EEPROM content.