static void b43_phy_ww(struct b43_wldev *dev) { u16 b, curr_s, best_s = 0xFFFF; int i; b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN); b43_phy_write(dev, B43_PHY_OFDM(0x1B), b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000); b43_phy_write(dev, B43_PHY_OFDM(0x82), (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300); b43_radio_write16(dev, 0x0009, b43_radio_read16(dev, 0x0009) | 0x0080); b43_radio_write16(dev, 0x0012, (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002); b43_wa_initgains(dev); b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5); b = b43_phy_read(dev, B43_PHY_PWRDOWN); b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005); b43_radio_write16(dev, 0x0004, b43_radio_read16(dev, 0x0004) | 0x0004); for (i = 0x10; i <= 0x20; i++) { b43_radio_write16(dev, 0x0013, i); curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF; if (!curr_s) { best_s = 0x0000; break; } else if (curr_s >= 0x0080) curr_s = 0x0100 - curr_s; if (curr_s < best_s) best_s = curr_s; } b43_phy_write(dev, B43_PHY_PWRDOWN, b); b43_radio_write16(dev, 0x0004, b43_radio_read16(dev, 0x0004) & 0xFFFB); b43_radio_write16(dev, 0x0013, best_s); b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC); b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80); b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00); b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0); b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0); b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF); b43_phy_write(dev, B43_PHY_OFDM(0xBB), (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053); b43_phy_write(dev, B43_PHY_OFDM61, (b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120); b43_phy_write(dev, B43_PHY_OFDM(0x13), (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000); b43_phy_write(dev, B43_PHY_OFDM(0x14), (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000); b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017); for (i = 0; i < 6; i++) b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F); b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E); b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011); b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013); b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030); b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); }
static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel) { u16 freq, r8, tmp; freq = channel2freq_a(channel); r8 = b43_radio_read16(dev, 0x0008); b43_write16(dev, 0x03F0, freq); b43_radio_write16(dev, 0x0008, r8); //TODO: write max channel TX power? to Radio 0x2D tmp = b43_radio_read16(dev, 0x002E); tmp &= 0x0080; //TODO: OR tmp with the Power out estimation for this channel? b43_radio_write16(dev, 0x002E, tmp); if (freq >= 4920 && freq <= 5500) { /* * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; * = (freq * 0.025862069 */ r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ } b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022) & 0x000F) | (r8 << 4)); b43_radio_write16(dev, 0x002A, (r8 << 4)); b43_radio_write16(dev, 0x002B, (r8 << 4)); b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008) & 0x00F0) | (r8 << 4)); b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029) & 0xFF0F) | 0x00B0); b43_radio_write16(dev, 0x0035, 0x00AA); b43_radio_write16(dev, 0x0036, 0x0085); b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A) & 0xFF20) | freq_r3A_value(freq)); b43_radio_write16(dev, 0x003D, b43_radio_read16(dev, 0x003D) & 0x00FF); b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081) & 0xFF7F) | 0x0080); b43_radio_write16(dev, 0x0035, b43_radio_read16(dev, 0x0035) & 0xFFEF); b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035) & 0xFFEF) | 0x0010); b43_radio_set_tx_iq(dev); //TODO: TSSI2dbm workaround //FIXME b43_phy_xmitpower(dev); }
/* 802.11/LO/GPHY/MeasuringGains */ static void lo_measure_gain_values(struct b43_wldev *dev, s16 max_rx_gain, int use_trsw_rx) { struct b43_phy *phy = &dev->phy; u16 tmp; if (max_rx_gain < 0) max_rx_gain = 0; if (has_loopback_gain(phy)) { int trsw_rx = 0; int trsw_rx_gain; if (use_trsw_rx) { trsw_rx_gain = phy->trsw_rx_gain / 2; if (max_rx_gain >= trsw_rx_gain) { trsw_rx_gain = max_rx_gain - trsw_rx_gain; trsw_rx = 0x20; } } else trsw_rx_gain = max_rx_gain; if (trsw_rx_gain < 9) { phy->lna_lod_gain = 0; } else { phy->lna_lod_gain = 1; trsw_rx_gain -= 8; } trsw_rx_gain = limit_value(trsw_rx_gain, 0, 0x2D); phy->pga_gain = trsw_rx_gain / 3; if (phy->pga_gain >= 5) { phy->pga_gain -= 5; phy->lna_gain = 2; } else phy->lna_gain = 0; } else { phy->lna_gain = 0; phy->trsw_rx_gain = 0x20; if (max_rx_gain >= 0x14) { phy->lna_lod_gain = 1; phy->pga_gain = 2; } else if (max_rx_gain >= 0x12) { phy->lna_lod_gain = 1; phy->pga_gain = 1; } else if (max_rx_gain >= 0xF) { phy->lna_lod_gain = 1; phy->pga_gain = 0; } else { phy->lna_lod_gain = 0; phy->pga_gain = 0; } } tmp = b43_radio_read16(dev, 0x7A); if (phy->lna_lod_gain == 0) tmp &= ~0x0008; else tmp |= 0x0008; b43_radio_write16(dev, 0x7A, tmp); }
static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel) { u16 freq, r8, tmp; freq = channel2freq_a(channel); r8 = b43_radio_read16(dev, 0x0008); b43_write16(dev, 0x03F0, freq); b43_radio_write16(dev, 0x0008, r8); tmp = b43_radio_read16(dev, 0x002E); tmp &= 0x0080; b43_radio_write16(dev, 0x002E, tmp); if (freq >= 4920 && freq <= 5500) { r8 = 3 * freq / 116; } b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); b43_radio_maskset(dev, 0x0022, 0x000F, (r8 << 4)); b43_radio_write16(dev, 0x002A, (r8 << 4)); b43_radio_write16(dev, 0x002B, (r8 << 4)); b43_radio_maskset(dev, 0x0008, 0x00F0, (r8 << 4)); b43_radio_maskset(dev, 0x0029, 0xFF0F, 0x00B0); b43_radio_write16(dev, 0x0035, 0x00AA); b43_radio_write16(dev, 0x0036, 0x0085); b43_radio_maskset(dev, 0x003A, 0xFF20, freq_r3A_value(freq)); b43_radio_mask(dev, 0x003D, 0x00FF); b43_radio_maskset(dev, 0x0081, 0xFF7F, 0x0080); b43_radio_mask(dev, 0x0035, 0xFFEF); b43_radio_maskset(dev, 0x0035, 0xFFEF, 0x0010); b43_radio_set_tx_iq(dev); }
static void b43_radio_set_tx_iq(struct b43_wldev *dev) { static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; u16 tmp = b43_radio_read16(dev, 0x001E); int i, j; for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (tmp == (data_high[i] << 4 | data_low[j])) { b43_phy_write(dev, 0x0069, (i - j) << 8 | 0x00C0); return; } } } }
static void b43_radio_init2055_post(struct b43_wldev *dev) { struct ssb_sprom *sprom = &(dev->dev->bus->sprom); struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); int i; u16 val; b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); msleep(1); if ((sprom->revision != 4) || !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || (binfo->type != 0x46D) || (binfo->rev < 0x41)) { b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); msleep(1); } } b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); msleep(1); b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); msleep(1); b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); msleep(1); b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); msleep(1); b43_radio_set(dev, B2055_CAL_MISC, 0x1); msleep(1); b43_radio_set(dev, B2055_CAL_MISC, 0x40); msleep(1); for (i = 0; i < 100; i++) { val = b43_radio_read16(dev, B2055_CAL_COUT2); if (val & 0x80) break; udelay(10); } msleep(1); b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); msleep(1); nphy_channel_switch(dev, dev->phy.channel); b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); }
static void b43_radio_init2060(struct b43_wldev *dev) { b43_radio_write16(dev, 0x0004, 0x00C0); b43_radio_write16(dev, 0x0005, 0x0008); b43_radio_write16(dev, 0x0009, 0x0040); b43_radio_write16(dev, 0x0005, 0x00AA); b43_radio_write16(dev, 0x0032, 0x008F); b43_radio_write16(dev, 0x0006, 0x008F); b43_radio_write16(dev, 0x0034, 0x008F); b43_radio_write16(dev, 0x002C, 0x0007); b43_radio_write16(dev, 0x0082, 0x0080); b43_radio_write16(dev, 0x0080, 0x0000); b43_radio_write16(dev, 0x003F, 0x00DA); b43_radio_mask(dev, 0x0005, ~0x0008); b43_radio_mask(dev, 0x0081, ~0x0010); b43_radio_mask(dev, 0x0081, ~0x0020); b43_radio_mask(dev, 0x0081, ~0x0020); msleep(1); /* delay 400usec */ b43_radio_maskset(dev, 0x0081, ~0x0020, 0x0010); msleep(1); /* delay 400usec */ b43_radio_maskset(dev, 0x0005, ~0x0008, 0x0008); b43_radio_mask(dev, 0x0085, ~0x0010); b43_radio_mask(dev, 0x0005, ~0x0008); b43_radio_mask(dev, 0x0081, ~0x0040); b43_radio_maskset(dev, 0x0081, ~0x0040, 0x0040); b43_radio_write16(dev, 0x0005, (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008); b43_phy_write(dev, 0x0063, 0xDDC6); b43_phy_write(dev, 0x0069, 0x07BE); b43_phy_write(dev, 0x006A, 0x0000); aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev)); msleep(1); }
static void lo_measure_restore(struct b43_wldev *dev, struct lo_g_saved_values *sav) { struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; u16 tmp; if (phy->rev >= 2) { b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); tmp = (phy->pga_gain << 8); b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); udelay(5); b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); udelay(2); b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); } else { tmp = (phy->pga_gain | 0xEFA0); b43_phy_write(dev, B43_PHY_PGACTL, tmp); } if (b43_has_hardware_pctl(phy)) { b43_gphy_dc_lt_init(dev); } else { if (lo->rebuild) b43_lo_g_adjust_to(dev, 3, 2, 0); else b43_lo_g_adjust(dev); } if (phy->type == B43_PHYTYPE_G) { if (phy->rev >= 3) b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); else b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); if (phy->rev >= 2) b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0202); else b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0101); } b43_write16(dev, 0x3F4, sav->reg_3F4); b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl); b43_phy_write(dev, B43_PHY_CCK(0x2A), sav->phy_cck_2A); b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl); b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl); b43_radio_write16(dev, 0x43, sav->radio_43); b43_radio_write16(dev, 0x7A, sav->radio_7A); if (!has_tx_magnification(phy)) { tmp = sav->radio_52; b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFF0F) | tmp); } b43_write16(dev, 0x3E2, sav->reg_3E2); if (phy->type == B43_PHYTYPE_B && phy->radio_ver == 0x2050 && phy->radio_rev <= 5) { b43_phy_write(dev, B43_PHY_CCK(0x30), sav->phy_cck_30); b43_phy_write(dev, B43_PHY_CCK(0x06), sav->phy_cck_06); } if (phy->rev >= 2) { b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover); b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, sav->phy_analogoverval); b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl); b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover); b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval); b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); } if (b43_has_hardware_pctl(phy)) { tmp = (sav->phy_lo_mask & 0xBFFF); b43_phy_write(dev, B43_PHY_LO_MASK, tmp); b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl); b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); } b43_radio_selectchannel(dev, sav->old_channel, 1); }
static void lo_measure_setup(struct b43_wldev *dev, struct lo_g_saved_values *sav) { struct ssb_sprom *sprom = &dev->dev->bus->sprom; struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; u16 tmp; if (b43_has_hardware_pctl(phy)) { sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14)); sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL); b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, b43_phy_read(dev, B43_PHY_HPWR_TSSICTL) | 0x100); b43_phy_write(dev, B43_PHY_EXTG(0x01), b43_phy_read(dev, B43_PHY_EXTG(0x01)) | 0x40); b43_phy_write(dev, B43_PHY_DACCTL, b43_phy_read(dev, B43_PHY_DACCTL) | 0x40); b43_phy_write(dev, B43_PHY_CCK(0x14), b43_phy_read(dev, B43_PHY_CCK(0x14)) | 0x200); } if (phy->type == B43_PHYTYPE_B && phy->radio_ver == 0x2050 && phy->radio_rev < 6) { b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); } if (!lo->rebuild && b43_has_hardware_pctl(phy)) lo_read_power_vector(dev); if (phy->rev >= 2) { sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); sav->phy_analogoverval = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E)); sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); b43_phy_write(dev, B43_PHY_CLASSCTL, b43_phy_read(dev, B43_PHY_CLASSCTL) & 0xFFFC); b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) & 0x7FFF); b43_phy_write(dev, B43_PHY_ANALOGOVER, b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0003); b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, b43_phy_read(dev, B43_PHY_ANALOGOVERVAL) & 0xFFFC); if (phy->type == B43_PHYTYPE_G) { if ((phy->rev >= 7) && (sprom->boardflags_lo & B43_BFL_EXTLNA)) { b43_phy_write(dev, B43_PHY_RFOVER, 0x933); } else { b43_phy_write(dev, B43_PHY_RFOVER, 0x133); } } else { b43_phy_write(dev, B43_PHY_RFOVER, 0); } b43_phy_write(dev, B43_PHY_CCK(0x3E), 0); } sav->reg_3F4 = b43_read16(dev, 0x3F4); sav->reg_3E2 = b43_read16(dev, 0x3E2); sav->radio_43 = b43_radio_read16(dev, 0x43); sav->radio_7A = b43_radio_read16(dev, 0x7A); sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); sav->phy_cck_2A = b43_phy_read(dev, B43_PHY_CCK(0x2A)); sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL); if (!has_tx_magnification(phy)) { sav->radio_52 = b43_radio_read16(dev, 0x52); sav->radio_52 &= 0x00F0; } if (phy->type == B43_PHYTYPE_B) { sav->phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); sav->phy_cck_06 = b43_phy_read(dev, B43_PHY_CCK(0x06)); b43_phy_write(dev, B43_PHY_CCK(0x30), 0x00FF); b43_phy_write(dev, B43_PHY_CCK(0x06), 0x3F3F); } else { b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000); } b43_write16(dev, 0x3F4, b43_read16(dev, 0x3F4) & 0xF000); tmp = (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_CCK(0x2E); b43_phy_write(dev, tmp, 0x007F); tmp = sav->phy_syncctl; b43_phy_write(dev, B43_PHY_SYNCCTL, tmp & 0xFF7F); tmp = sav->radio_7A; b43_radio_write16(dev, 0x007A, tmp & 0xFFF0); b43_phy_write(dev, B43_PHY_CCK(0x2A), 0x8A3); if (phy->type == B43_PHYTYPE_G || (phy->type == B43_PHYTYPE_B && phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) { b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1003); } else b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); if (phy->rev >= 2) b43_dummy_transmission(dev); b43_radio_selectchannel(dev, 6, 0); b43_radio_read16(dev, 0x51); /* dummy read */ if (phy->type == B43_PHYTYPE_G) b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); if (lo->rebuild) lo_measure_txctl_values(dev); if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); } else { if (phy->type == B43_PHYTYPE_B) b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); else b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); } }
static void lo_measure_txctl_values(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; u16 reg, mask; u16 trsw_rx, pga; u16 radio_pctl_reg; static const u8 tx_bias_values[] = { 0x09, 0x08, 0x0A, 0x01, 0x00, 0x02, 0x05, 0x04, 0x06, }; static const u8 tx_magn_values[] = { 0x70, 0x40, }; if (!has_loopback_gain(phy)) { radio_pctl_reg = 6; trsw_rx = 2; pga = 0; } else { int lb_gain; /* Loopback gain (in dB) */ trsw_rx = 0; lb_gain = phy->max_lb_gain / 2; if (lb_gain > 10) { radio_pctl_reg = 0; pga = abs(10 - lb_gain) / 6; pga = limit_value(pga, 0, 15); } else { int cmp_val; int tmp; pga = 0; cmp_val = 0x24; if ((phy->rev >= 2) && (phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) cmp_val = 0x3C; tmp = lb_gain; if ((10 - lb_gain) < cmp_val) tmp = (10 - lb_gain); if (tmp < 0) tmp += 6; else tmp += 3; cmp_val /= 4; tmp /= 4; if (tmp >= cmp_val) radio_pctl_reg = cmp_val; else radio_pctl_reg = tmp; } } b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) & 0xFFF0) | radio_pctl_reg); b43_phy_set_baseband_attenuation(dev, 2); reg = lo_txctl_register_table(dev, &mask, NULL); mask = ~mask; b43_radio_write16(dev, reg, b43_radio_read16(dev, reg) & mask); if (has_tx_magnification(phy)) { int i, j; int feedthrough; int min_feedth = 0xFFFF; u8 tx_magn, tx_bias; for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) { tx_magn = tx_magn_values[i]; b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFF0F) | tx_magn); for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) { tx_bias = tx_bias_values[j]; b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFFF0) | tx_bias); feedthrough = lo_measure_feedthrough(dev, 0, pga, trsw_rx); if (feedthrough < min_feedth) { lo->tx_bias = tx_bias; lo->tx_magn = tx_magn; min_feedth = feedthrough; } if (lo->tx_bias == 0) break; } b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFF00) | lo->tx_bias | lo-> tx_magn); } } else { lo->tx_magn = 0; lo->tx_bias = 0; b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) & 0xFFF0); /* TX bias == 0 */ } }
void b43_lo_b_measure(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; u16 regstack[12] = { 0 }; u16 mls; u16 fval; int i, j; regstack[0] = b43_phy_read(dev, 0x0015); regstack[1] = b43_radio_read16(dev, 0x0052) & 0xFFF0; if (phy->radio_ver == 0x2053) { regstack[2] = b43_phy_read(dev, 0x000A); regstack[3] = b43_phy_read(dev, 0x002A); regstack[4] = b43_phy_read(dev, 0x0035); regstack[5] = b43_phy_read(dev, 0x0003); regstack[6] = b43_phy_read(dev, 0x0001); regstack[7] = b43_phy_read(dev, 0x0030); regstack[8] = b43_radio_read16(dev, 0x0043); regstack[9] = b43_radio_read16(dev, 0x007A); regstack[10] = b43_read16(dev, 0x03EC); regstack[11] = b43_radio_read16(dev, 0x0052) & 0x00F0; b43_phy_write(dev, 0x0030, 0x00FF); b43_write16(dev, 0x03EC, 0x3F3F); b43_phy_write(dev, 0x0035, regstack[4] & 0xFF7F); b43_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0); } b43_phy_write(dev, 0x0015, 0xB000); b43_phy_write(dev, 0x002B, 0x0004); if (phy->radio_ver == 0x2053) { b43_phy_write(dev, 0x002B, 0x0203); b43_phy_write(dev, 0x002A, 0x08A3); } phy->minlowsig[0] = 0xFFFF; for (i = 0; i < 4; i++) { b43_radio_write16(dev, 0x0052, regstack[1] | i); lo_b_r15_loop(dev); } for (i = 0; i < 10; i++) { b43_radio_write16(dev, 0x0052, regstack[1] | i); mls = lo_b_r15_loop(dev) / 10; if (mls < phy->minlowsig[0]) { phy->minlowsig[0] = mls; phy->minlowsigpos[0] = i; } } b43_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]); phy->minlowsig[1] = 0xFFFF; for (i = -4; i < 5; i += 2) { for (j = -4; j < 5; j += 2) { if (j < 0) fval = (0x0100 * i) + j + 0x0100; else fval = (0x0100 * i) + j; b43_phy_write(dev, 0x002F, fval); mls = lo_b_r15_loop(dev) / 10; if (mls < phy->minlowsig[1]) { phy->minlowsig[1] = mls; phy->minlowsigpos[1] = fval; } } } phy->minlowsigpos[1] += 0x0101; b43_phy_write(dev, 0x002F, phy->minlowsigpos[1]); if (phy->radio_ver == 0x2053) { b43_phy_write(dev, 0x000A, regstack[2]); b43_phy_write(dev, 0x002A, regstack[3]); b43_phy_write(dev, 0x0035, regstack[4]); b43_phy_write(dev, 0x0003, regstack[5]); b43_phy_write(dev, 0x0001, regstack[6]); b43_phy_write(dev, 0x0030, regstack[7]); b43_radio_write16(dev, 0x0043, regstack[8]); b43_radio_write16(dev, 0x007A, regstack[9]); b43_radio_write16(dev, 0x0052, (b43_radio_read16(dev, 0x0052) & 0x000F) | regstack[11]); b43_write16(dev, 0x03EC, regstack[10]); } b43_phy_write(dev, 0x0015, regstack[0]); }
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) { b43_radio_write16(dev, offset, (b43_radio_read16(dev, offset) & mask) | set); }
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) { b43_radio_write16(dev, offset, b43_radio_read16(dev, offset) | set); }
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) { b43_radio_write16(dev, offset, b43_radio_read16(dev, offset) & mask); }