From 1cdd762f908a29c1f577ccdb5c1620a62e452a30 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Thu, 10 Nov 2011 23:07:42 +0000
Subject: mac80211: add antenna control api for b43

SVN-Revision: 28940
---
 .../patches/820-b43-add-antenna-control.patch      | 131 +++++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 package/mac80211/patches/820-b43-add-antenna-control.patch

diff --git a/package/mac80211/patches/820-b43-add-antenna-control.patch b/package/mac80211/patches/820-b43-add-antenna-control.patch
new file mode 100644
index 0000000000..fd80824857
--- /dev/null
+++ b/package/mac80211/patches/820-b43-add-antenna-control.patch
@@ -0,0 +1,131 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -1535,7 +1535,7 @@ static void b43_write_beacon_template(st
+ 				  len, ram_offset, shm_size_offset, rate);
+ 
+ 	/* Write the PHY TX control parameters. */
+-	antenna = B43_ANTENNA_DEFAULT;
++	antenna = dev->tx_antenna;
+ 	antenna = b43_antenna_to_phyctl(antenna);
+ 	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+ 	/* We can't send beacons with short preamble. Would get PHY errors. */
+@@ -3052,8 +3052,8 @@ static int b43_chip_init(struct b43_wlde
+ 
+ 	/* Select the antennae */
+ 	if (phy->ops->set_rx_antenna)
+-		phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+-	b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++		phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++	b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ 
+ 	if (phy->type == B43_PHYTYPE_B) {
+ 		value16 = b43_read16(dev, 0x005E);
+@@ -3782,7 +3782,6 @@ static int b43_op_config(struct ieee8021
+ 	struct b43_wldev *dev;
+ 	struct b43_phy *phy;
+ 	struct ieee80211_conf *conf = &hw->conf;
+-	int antenna;
+ 	int err = 0;
+ 	bool reload_bss = false;
+ 
+@@ -3836,11 +3835,9 @@ static int b43_op_config(struct ieee8021
+ 	}
+ 
+ 	/* Antennas for RX and management frame TX. */
+-	antenna = B43_ANTENNA_DEFAULT;
+-	b43_mgmtframe_txantenna(dev, antenna);
+-	antenna = B43_ANTENNA_DEFAULT;
++	b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ 	if (phy->ops->set_rx_antenna)
+-		phy->ops->set_rx_antenna(dev, antenna);
++		phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+ 
+ 	if (wl->radio_enabled != phy->radio_on) {
+ 		if (wl->radio_enabled) {
+@@ -4910,6 +4907,47 @@ static int b43_op_get_survey(struct ieee
+ 	return 0;
+ }
+ 
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++	struct b43_wldev *dev = wl->current_dev;
++
++	if (tx_ant == 1 && rx_ant == 1) {
++		dev->tx_antenna = B43_ANTENNA0;
++		dev->rx_antenna = B43_ANTENNA0;
++	}
++	else if (tx_ant == 2 && rx_ant == 2) {
++		dev->tx_antenna = B43_ANTENNA1;
++		dev->rx_antenna = B43_ANTENNA1;
++	}
++	else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++		dev->tx_antenna = B43_ANTENNA_DEFAULT;
++		dev->rx_antenna = B43_ANTENNA_DEFAULT;
++	}
++	else {
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++	struct b43_wldev *dev = wl->current_dev;
++
++	switch (dev->tx_antenna) {
++	case B43_ANTENNA0:
++		*tx_ant = 1; *rx_ant = 1; break;
++	case B43_ANTENNA1:
++		*tx_ant = 2; *rx_ant = 2; break;
++	case B43_ANTENNA_DEFAULT:
++		*tx_ant = 3; *rx_ant = 3; break;
++	}
++	return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ 	.tx			= b43_op_tx,
+ 	.conf_tx		= b43_op_conf_tx,
+@@ -4931,6 +4969,8 @@ static const struct ieee80211_ops b43_hw
+ 	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
+ 	.get_survey		= b43_op_get_survey,
+ 	.rfkill_poll		= b43_rfkill_poll,
++	.set_antenna		= b43_op_set_antenna,
++	.get_antenna		= b43_op_get_antenna,
+ };
+ 
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5177,6 +5217,8 @@ static int b43_one_core_attach(struct b4
+ 	if (!wldev)
+ 		goto out;
+ 
++	wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++	wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ 	wldev->use_pio = b43_modparam_pio;
+ 	wldev->dev = dev;
+ 	wldev->wl = wl;
+@@ -5264,6 +5306,9 @@ static struct b43_wl *b43_wireless_init(
+ 		BIT(NL80211_IFTYPE_WDS) |
+ 		BIT(NL80211_IFTYPE_ADHOC);
+ 
++	hw->wiphy->available_antennas_rx = 0x3;
++	hw->wiphy->available_antennas_tx = 0x3;
++
+ 	hw->queues = modparam_qos ? 4 : 1;
+ 	wl->mac80211_initially_registered_queues = hw->queues;
+ 	hw->max_rates = 2;
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -792,6 +792,8 @@ struct b43_wldev {
+ 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
+ 	bool use_pio;			/* TRUE if next init should use PIO */
+ 	int gpiomask;			/* GPIO LED mask as a module parameter */
++	int rx_antenna;			/* Used RX antenna (B43_ANTENNAxxx) */
++	int tx_antenna;			/* Used TX antenna (B43_ANTENNAxxx) */
+ 
+ 	/* PHY/Radio device. */
+ 	struct b43_phy phy;
-- 
cgit v1.2.3