b43: rewrite A PHY initialization

Rewrite and sync A PHY initialization with specs, thus allowing for further
work to be done on 802.11a support. Note that A PHY initialization involves
G PHYs as well.

Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Acked-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 15a8718..0ac8653 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -229,7 +229,7 @@
 };
 
 const u16 b43_tab_noisea3[] = {
-	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+	0x5E5E, 0x5E5E, 0x5E5E, 0x3F48,
 	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
 };
 
@@ -243,6 +243,26 @@
 	0x0000, 0x0000, 0x0000, 0x0000,
 };
 
+const u16 b43_tab_noisescalea2[] = {
+	0x6767, 0x6767, 0x6767, 0x6767, /* 0 */
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6700, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x6767, 0x6767, /* 16 */
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x0067,
+};
+
+const u16 b43_tab_noisescalea3[] = {
+	0x2323, 0x2323, 0x2323, 0x2323, /* 0 */
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2300, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x2323, 0x2323, /* 16 */
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x0023,
+};
+
 const u16 b43_tab_noisescaleg1[] = {
 	0x6C77, 0x5162, 0x3B40, 0x3335,	/* 0 */
 	0x2F2D, 0x2A2A, 0x2527, 0x1F21,
@@ -254,7 +274,7 @@
 };
 
 const u16 b43_tab_noisescaleg2[] = {
-	0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7,	/* 0 */
+	0xD8DD, 0xCBD4, 0xBCC0, 0xB6B7,	/* 0 */
 	0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
 	0x969B, 0x9195, 0x8F8F, 0x8A8A,
 	0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
@@ -307,6 +327,28 @@
 	0x00DE,
 };
 
+const u16 b43_tab_rssiagc1[] = {
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, /* 0 */
+	0xFFF8, 0xFFF9, 0xFFFC, 0xFFFE,
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+};
+
+const u16 b43_tab_rssiagc2[] = {
+	0x0820, 0x0820, 0x0920, 0x0C38, /* 0 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38, /* 16 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38, /* 32 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+};
+
 static inline void assert_sizes(void)
 {
 	BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor));
@@ -317,36 +359,65 @@
 	BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3));
 	BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1));
 	BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2));
-	BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescalea2));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescalea3));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
 		     ARRAY_SIZE(b43_tab_noisescaleg1));
-	BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
 		     ARRAY_SIZE(b43_tab_noisescaleg2));
-	BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
 		     ARRAY_SIZE(b43_tab_noisescaleg3));
 	BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1));
 	BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2));
+	BUILD_BUG_ON(B43_TAB_RSSIAGC1_SIZE != ARRAY_SIZE(b43_tab_rssiagc1));
+	BUILD_BUG_ON(B43_TAB_RSSIAGC2_SIZE != ARRAY_SIZE(b43_tab_rssiagc2));
 }
 
 u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
 {
-	assert_sizes();
+	struct b43_phy *phy = &dev->phy;
+	u16 addr;
 
-	b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+	addr = table + offset;
+	if (addr - 1 != phy->ofdm_addr || phy->ofdm_valid != 1) {
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		phy->ofdm_valid = 1;
+	}
+	phy->ofdm_addr = addr;
+
 	return b43_phy_read(dev, B43_PHY_OTABLEI);
+	assert_sizes();
 }
 
 void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
 			 u16 offset, u16 value)
 {
-	b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+	struct b43_phy *phy = &dev->phy;
+	u16 addr;
+
+	addr = table + offset;
+	if (addr - 1 != phy->ofdm_addr || phy->ofdm_valid != 2) {
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		phy->ofdm_valid = 2;
+	}
+	phy->ofdm_addr = addr;
 	b43_phy_write(dev, B43_PHY_OTABLEI, value);
 }
 
 u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
 {
+	struct b43_phy *phy = &dev->phy;
 	u32 ret;
+	u16 addr;
 
-	b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+	addr = table + offset;
+	if (addr - 1 != phy->ofdm_addr || phy->ofdm_valid != 1) {
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		phy->ofdm_valid = 1;
+	}
+	phy->ofdm_addr = addr;
 	ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
 	ret <<= 16;
 	ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
@@ -357,9 +428,17 @@
 void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
 			 u16 offset, u32 value)
 {
-	b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+	struct b43_phy *phy = &dev->phy;
+	u16 addr;
+
+	addr = table + offset;
+	if (addr - 1 != phy->ofdm_addr || phy->ofdm_valid != 2) {
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		phy->ofdm_valid = 2;
+	}
+	phy->ofdm_addr = addr;
+
 	b43_phy_write(dev, B43_PHY_OTABLEI, value);
-	b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
 }
 
 u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset)