summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcm43xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcm43xx')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h21
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c30
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c131
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.h5
5 files changed, 158 insertions, 38 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 8820012b4b3a..1fca1f9c48fe 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -507,14 +507,23 @@ struct bcm43xx_radioinfo {
u16 version;
u8 revision;
- /* 0: baseband attenuation,
- * 1: radio attenuation,
- * 2: tx_CTL1
- * 3: tx_CTL2
- */
- u16 txpower[4];
/* Desired TX power in dBm Q5.2 */
u16 txpower_desired;
+ /* TX Power control values. */
+ union {
+ /* B/G PHY */
+ struct {
+ u16 baseband_atten;
+ u16 radio_atten;
+ u16 txctl1;
+ u16 txctl2;
+ };
+ /* A PHY */
+ struct {
+ u16 txpwr_offset;
+ };
+ };
+
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 12c93d274ae5..e680d2acc44b 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -560,12 +560,9 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
radio->revision = revision;
/* Set default attenuation values. */
- radio->txpower[0] = 2;
- radio->txpower[1] = 2;
- if (revision == 1)
- radio->txpower[2] = 3;
- else
- radio->txpower[2] = 0;
+ radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+ radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+ radio->txctl1 = bcm43xx_default_txctl1(bcm);
if (phy->type == BCM43xx_PHYTYPE_A)
radio->txpower_desired = bcm->sprom.maxpower_aphy;
else
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 1ce9a4599903..054c64e462fb 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -220,9 +220,9 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
bcm43xx_radio_write16(bcm, 0x0076,
bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
} else {
- saved_batt = radio->txpower[0];
- saved_ratt = radio->txpower[1];
- saved_txctl1 = radio->txpower[2];
+ saved_batt = radio->baseband_atten;
+ saved_ratt = radio->radio_atten;
+ saved_txctl1 = radio->txctl1;
if ((radio->revision >= 6) && (radio->revision <= 8)
&& /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
@@ -1039,7 +1039,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
bcm43xx_radio_write16(bcm, 0x0052,
(bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0)
- | radio->txpower[3]);
+ | radio->txctl2);
}
if (phy->connected) {
@@ -1259,7 +1259,6 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
if (baseband_attenuation > 6)
baseband_attenuation = 6;
assert(radio_attenuation < 10);
- assert(tx == 0 || tx == 3);
if (tx == 3) {
return bcm43xx_get_lopair(phy,
@@ -1275,9 +1274,9 @@ struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
return bcm43xx_find_lopair(bcm,
- radio->txpower[0],
- radio->txpower[1],
- radio->txpower[2]);
+ radio->baseband_atten,
+ radio->radio_atten,
+ radio->txctl1);
}
/* Adjust B/G LO */
@@ -1311,7 +1310,7 @@ static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
txctl2 = i;
}
}
- radio->txpower[3] = txctl2;
+ radio->txctl2 = txctl2;
}
static
@@ -1530,8 +1529,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
r31 = 0;
}
bcm43xx_radio_write16(bcm, 0x43, i);
- bcm43xx_radio_write16(bcm, 0x52,
- radio->txpower[3]);
+ bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
udelay(10);
bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
@@ -1573,7 +1571,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
}
bcm43xx_radio_write16(bcm, 0x43, i - 9);
bcm43xx_radio_write16(bcm, 0x52,
- radio->txpower[3]
+ radio->txctl2
| (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
udelay(10);
@@ -1780,9 +1778,9 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
}
/* Calculate the new attenuation values. */
- baseband_attenuation = radio->txpower[0];
+ baseband_attenuation = radio->baseband_atten;
baseband_attenuation += baseband_att_delta;
- radio_attenuation = radio->txpower[1];
+ radio_attenuation = radio->radio_atten;
radio_attenuation += radio_att_delta;
/* Get baseband and radio attenuation values into their permitted ranges.
@@ -1807,7 +1805,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
}
baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
- txpower = radio->txpower[2];
+ txpower = radio->txctl1;
if ((radio->version == 0x2050) && (radio->revision == 2)) {
if (radio_attenuation <= 1) {
if (txpower == 0) {
@@ -1829,7 +1827,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
}
}
}
- radio->txpower[2] = txpower;
+ radio->txctl1 = txpower;
baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
radio_attenuation = limit_value(radio_attenuation, 0, 9);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index cac604bc0955..4e8d8c936ab4 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -1652,7 +1652,7 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
bcm43xx_ilt_write(bcm, 0x3001, dac);
- radio->txpower[0] = txpower;
+ radio->txpwr_offset = txpower;
TODO();
//TODO: FuncPlaceholder (Adjust BB loft cancel)
@@ -1666,17 +1666,14 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
if (baseband_attenuation == 0xFFFF)
- baseband_attenuation = radio->txpower[0];
- else
- radio->txpower[0] = baseband_attenuation;
+ baseband_attenuation = radio->baseband_atten;
if (radio_attenuation == 0xFFFF)
- radio_attenuation = radio->txpower[1];
- else
- radio->txpower[1] = radio_attenuation;
+ radio_attenuation = radio->radio_atten;
if (txpower == 0xFFFF)
- txpower = radio->txpower[2];
- else
- radio->txpower[2] = txpower;
+ txpower = radio->txctl1;
+ radio->baseband_atten = baseband_attenuation;
+ radio->radio_atten = radio_attenuation;
+ radio->txctl1 = txpower;
assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
if (radio->revision < 6)
@@ -1693,10 +1690,124 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
(bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
| ((txpower << 4) & 0x0070));
}
+ //FIXME: The spec is very weird and unclear here.
if (phy->type == BCM43xx_PHYTYPE_G)
bcm43xx_phy_lo_adjust(bcm, 0);
}
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (radio->version == 0x2050 && radio->revision < 6)
+ return 0;
+ return 2;
+}
+
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 att = 0xFFFF;
+
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ return 0x60;
+
+ switch (radio->version) {
+ case 0x2053:
+ switch (radio->revision) {
+ case 1:
+ att = 6;
+ break;
+ }
+ break;
+ case 0x2050:
+ switch (radio->revision) {
+ case 0:
+ att = 5;
+ break;
+ case 1:
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 3;
+ else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x416)
+ att = 3;
+ else
+ att = 1;
+ } else {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 7;
+ else
+ att = 6;
+ }
+ break;
+ case 2:
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 3;
+ else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x416)
+ att = 5;
+ else if (bcm->chip_id == 0x4320)
+ att = 4;
+ else
+ att = 3;
+ } else
+ att = 6;
+ break;
+ case 3:
+ att = 5;
+ break;
+ case 4:
+ case 5:
+ att = 1;
+ break;
+ case 6:
+ case 7:
+ att = 5;
+ break;
+ case 8:
+ att = 0x1A;
+ break;
+ case 9:
+ default:
+ att = 5;
+ }
+ }
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421) {
+ if (bcm->board_revision < 0x43)
+ att = 2;
+ else if (bcm->board_revision < 0x51)
+ att = 3;
+ }
+ if (att == 0xFFFF)
+ att = 5;
+
+ return att;
+}
+
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (radio->version != 0x2050)
+ return 0;
+ if (radio->revision == 1)
+ return 3;
+ if (radio->revision < 6)
+ return 2;
+ if (radio->revision == 8)
+ return 1;
+ return 0;
+}
void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
{
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
index a5d2e10d5d98..9ed18039fa3e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
@@ -72,6 +72,11 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
u16 baseband_attenuation, u16 attenuation,
u16 txpower);
+
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
+
void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);