diff options
Diffstat (limited to 'drivers/net/wireless/bcm43xx')
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 131 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 5 |
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); |