Three functions about tx power control b43_nphy_tx_power_fix() b43_nphy_tx_power_coeff_set() b43_nphy_tx_power_type_set() but remain lots of TODO cause not very clearly understand the SPECS
Signed-off-by: Li YanBo <[email protected]> --- drivers/net/wireless/b43/phy_n.c | 195 +++++++++++++++++++++++++++++++++++++- 1 files changed, 194 insertions(+), 1 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 586e774..1330309 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -82,9 +82,183 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); } +enum b43_nphy_txpid { + B43_N_5G_MEDIUM_FREQ = 0, + B43_N_5G_LOW_FREQ, + B43_N_5G_HIGH_FREQ, + B43_N_2G_FREQ, + /* Attent: currently we just using 2 txpid */ + B43_N_TXPID_MAX = 2, +}; + +enum b43_nphy_txgain_type { + REV_LE2 = 0, /* rev <= 2 */ + REV_GE3_2G, /* rev >= 3 (2.4 GHz) */ + REV_E3_5G, /* rev 3 (5 GHz) */ + REV_GE4_5G, /* rev >= 4 (5 GHz) */ +}; + static void b43_nphy_tx_power_fix(struct b43_wldev *dev) { - //TODO + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = dev->phy.n; + struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + u32 txpid[B43_N_TXPID_MAX]; + int i; + + if (nphy->havoid) + b43_nphy_stay_carrier_search_enable(dev); + + if (sprom->revision < 4) + txpid[0] = txpid[1] = txpid[2] = txpid[3] = 0x48; + else { + /* TODO */ +/* if (medium freq range, 5100..5499 mhz) */ +/* txpid[B43_N_5G_MEDIUM_FREQ] = ; */ +/* Use the txpid5ga values from the SPROM in the loop below; */ +/* if (low freq range, 4900..5099 mhz) */ +/* txpid[B43_N_5G_LOW_FREQ] = ; */ +/* Use the txpid5gal values from the SPROM in the loop below; */ +/* if (high freq range, 5500.. mhz) */ +/* txpid[B43_N_5G_HIGH_FREQ] = ; */ +/* Use the txpid5gah values from the SPROM in the loop below; */ +/* if (2.4 GHz) */ +/* txpid[B43_N_2G_FREQ] = ; */ +/* Use the txpid2g values from the SPROM in the loop below; */ + } + if (phy->rev >= 3) + txpid[0] = txpid[1] = txpid[2] = txpid[3] = 0x28; + + for (i = 0; i < B43_N_TXPID_MAX; i++) { + u32 tx_gain; + u16 reg; + + if (phy->rev <= 2) + tx_gain = b43_ntab_txgain[REV_LE2][txpid[i]]; + else if ((i == B43_N_2G_FREQ) && (phy->rev > 2)) + tx_gain = b43_ntab_txgain[REV_GE3_2G][txpid[i]]; + else if (phy->rev == 3) + tx_gain = b43_ntab_txgain[REV_E3_5G][txpid[i]]; + else if (phy->rev > 3) + tx_gain = b43_ntab_txgain[REV_GE4_5G][txpid[i]]; + + /* Fixme depending on loop idx? */ + if (phy->rev < 3) + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x100); + else if (i == 0) + b43_phy_set(dev, B43_PHY_N(0x8F), 0x100); + else + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x100); + + if (i == 0) /* for core 1 */ + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, + (tx_gain >> 8) & 0x3f); + else /* for core 2 */ + b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, + (tx_gain >> 8) & 0x3f); + + /* set the radio gain */ + if (phy->rev < 3) + reg = (tx_gain >> 16) & 0x1fff; + else + reg = (tx_gain >> 16) & 0x1ffff; + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, txpid[i] + 0x1d10); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, reg); + + /* set the BB multiplier to table */ + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3c57); + reg = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + if (i == 1) + reg |= ((tx_gain & 0xff) << 8); + else if (i == 2) + reg |= (tx_gain & 0xff); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3c57); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, reg); + } + b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); + if (nphy->havoid) + b43_nphy_stay_carrier_search_disable(dev); +} + +static void b43_nphy_tx_power_coeff_set(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + if (nphy->havoid) + b43_nphy_stay_carrier_search_enable(dev); + +/* # read 7 16-bit values from the table 15 from offset 80; */ +/* # for the table IDs 26 and 27; */ +/* 1. for table 26: calculate the I/Q compensation as the first read value & 0x3ff shifted up by 10, and the second read value & 0x3ff; */ +/* 2. for table 27: do a similar calculation with the third and fourth read values; */ +/* 3. write the table ID << 10 ored with 128 to PHY reg 0x72; */ +/* 4. 128 times: write the higher 16 bits of the I/Q compensation to PHY reg 0x74 and the lower 16 bits to 0x73 */ + +/* # for the table IDs 26 and 27: */ +/* 1. the LO compensation I/Q is the upper/lower 8 bits of the fifth (table id 26) or sixth (27) read value */ +/* 2. write the table ID << 10 ored with 448 to PHY reg 0x72 */ +/* 3. 128 times: */ +/* 1.for PHY rev < 3: calculate the new LO compensation I/Q values according to the table by multiplying with the table value, adding 128 and then shifting down by 8 (other PHY revs require no calculation); */ +/* 2. calculate I << 8 | Q and write zero to 0x74, that value to 0x73 */ + +/* if (phy->rev < 2) */ +/* ;#if the PHY rev is < 2, write 0xffff to SHM 0x708 and 0x70e; */ +/* if (nphy->havoid) */ +/* b43_nphy_stay_carrier_search_disable(dev); */ + if (nphy->havoid) + b43_nphy_stay_carrier_search_disable(dev); +} + +static void b43_nphy_tx_power_type_set(struct b43_wldev *dev, u16 pwr_ctl) + +{ + struct b43_phy *phy = &dev->phy; + + dev->phy.n->tx_pwr = pwr_ctl; + + if (pwr_ctl != 0) { + /* TODO write the 84-entry adjusted power table (calculated during setup) + to both 8-bit hardware tables 26 and 27 at offset 64 */ + if (pwr_ctl == 1) + b43_phy_set(dev, B43_NPHY_TXPCTL_CMD, + B43_NPHY_TXPCTL_CMD_COEFF | + B43_NPHY_TXPCTL_CMD_HWPCTLEN); + else + b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, + ~(B43_NPHY_TXPCTL_CMD_COEFF | + B43_NPHY_TXPCTL_CMD_HWPCTLEN)); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000); + if (phy->rev < 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x40); + else + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x3b); + /* TODO 6.if the PHY rev two or higher and the bandwidth is + 40 MHz, clear the 20 in 40 MHz I/Q workaround host flag; */ + } else { + int i; + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6c40); + for (i = 0; i < 84; i++) + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); + b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, + ~(B43_NPHY_TXPCTL_CMD_COEFF | + B43_NPHY_TXPCTL_CMD_HWPCTLEN)); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); + if (phy->rev < 2) + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x5a); + else + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, 0x53); + + /* TODO if the PHY rev two or higher and the bandwidth is 40 MHz, + set the 20 in 40 MHz I/Q workaround host flag ; */ + } } /* Tune the hardware to a new channel. */ @@ -451,6 +625,25 @@ static void b43_nphy_periodic_calibration_init(struct b43_wldev *dev, /* TODO */ } + +static void b43_nphy_tx_gain_get(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + if (nphy->tx_pwr == 0) { + if (nphy->havoid) + b43_nphy_stay_carrier_search_enable(dev); + /* TODO read two 16-bit values from table 7 at offset 0x110, the first is for core 0, the second for core 1; */ + if (nphy->havoid) + b43_nphy_stay_carrier_search_disable(dev); + } else { + /* TODO read the base index from register 0x1ed (core 0) or 0x1ee (core 1); */ + /* TODO if the PHY rev is >= 3, use the lower 16 bits of the Init tables at the base index offset, and treat it as above; */ + /* TODO if the PHY rev is < 2, use the uppwer 16 bits of the Init tables at the base index offset, and treat it as above ; */ + } +} + + int b43_phy_initn(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; -- 1.5.6.3 _______________________________________________ Bcm43xx-dev mailing list [email protected] https://lists.berlios.de/mailman/listinfo/bcm43xx-dev
