/* wlc_lcnphy_tbl_init */ void b43_phy_lcn_tables_init(struct b43_wldev *dev) { struct ssb_sprom *sprom = dev->dev->bus_sprom; b43_phy_lcn_upload_static_tables(dev); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { if (sprom->boardflags_lo & B43_BFL_FEM) b43_phy_lcn_load_tx_gain_tab(dev, b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); else b43err(dev->wl, "TX gain table unknown for this card\n"); } if (sprom->boardflags_lo & B43_BFL_FEM && !(sprom->boardflags_hi & B43_BFH_FEM_BT)) b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0), ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0), b43_lcntab_sw_ctl_4313_epa_rev0); else b43err(dev->wl, "SW ctl table is unknown for this card\n"); b43_phy_lcn_load_rfpower(dev); b43_phy_lcn_rewrite_rfpower_table(dev); b43_phy_lcn_clean_papd_comp_table(dev); }
/* wlc_lcnphy_tx_pwr_ctrl_init */ static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev) { struct lcn_tx_gains tx_gains; u8 bbmult; b43_mac_suspend(dev); if (!dev->phy.lcn->hw_pwr_ctl_capable) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { tx_gains.gm_gain = 4; tx_gains.pga_gain = 12; tx_gains.pad_gain = 12; tx_gains.dac_gain = 0; bbmult = 150; } else { tx_gains.gm_gain = 7; tx_gains.pga_gain = 15; tx_gains.pad_gain = 14; tx_gains.dac_gain = 0; bbmult = 150; } b43_phy_lcn_set_tx_gain(dev, &tx_gains); b43_phy_lcn_set_bbmult(dev, bbmult); b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP); } else { b43err(dev->wl, "TX power control not supported for this HW\n"); } b43_mac_enable(dev); }
/* wlc_radio_2064_init */ static void b43_radio_2064_init(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { b43_radio_write(dev, 0x09c, 0x0020); b43_radio_write(dev, 0x105, 0x0008); } else { /* TODO */ } b43_radio_write(dev, 0x032, 0x0062); b43_radio_write(dev, 0x033, 0x0019); b43_radio_write(dev, 0x090, 0x0010); b43_radio_write(dev, 0x010, 0x0000); if (dev->phy.rev == 1) { b43_radio_write(dev, 0x060, 0x007f); b43_radio_write(dev, 0x061, 0x0072); b43_radio_write(dev, 0x062, 0x007f); } b43_radio_write(dev, 0x01d, 0x0002); b43_radio_write(dev, 0x01e, 0x0006); b43_phy_write(dev, 0x4ea, 0x4688); b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2); b43_phy_mask(dev, 0x4eb, ~0x01c0); b43_phy_maskset(dev, 0x46a, 0xff00, 0x19); b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0); b43_radio_mask(dev, 0x05b, (u16) ~0xff02); b43_radio_set(dev, 0x004, 0x40); b43_radio_set(dev, 0x120, 0x10); b43_radio_set(dev, 0x078, 0x80); b43_radio_set(dev, 0x129, 0x2); b43_radio_set(dev, 0x057, 0x1); b43_radio_set(dev, 0x05b, 0x2); /* TODO: wait for some bit to be set */ b43_radio_read(dev, 0x05c); b43_radio_mask(dev, 0x05b, (u16) ~0xff02); b43_radio_mask(dev, 0x057, (u16) ~0xff01); b43_phy_write(dev, 0x933, 0x2d6b); b43_phy_write(dev, 0x934, 0x2d6b); b43_phy_write(dev, 0x935, 0x2d6b); b43_phy_write(dev, 0x936, 0x2d6b); b43_phy_write(dev, 0x937, 0x016b); b43_radio_mask(dev, 0x057, (u16) ~0xff02); b43_radio_write(dev, 0x0c2, 0x006f); }
static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, unsigned int new_channel) { struct ieee80211_channel *channel = dev->wl->hw->conf.channel; enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { if ((new_channel < 1) || (new_channel > 14)) return -EINVAL; } else { return -EINVAL; } return b43_phy_ht_set_channel(dev, channel, channel_type); }
/* wlc_phy_init_lcnphy */ static int b43_phy_lcn_op_init(struct b43_wldev *dev) { struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc; b43_phy_set(dev, 0x44a, 0x80); b43_phy_mask(dev, 0x44a, 0x7f); b43_phy_set(dev, 0x6d1, 0x80); b43_phy_write(dev, 0x6d0, 0x7); b43_phy_lcn_afe_set_unset(dev); b43_phy_write(dev, 0x60a, 0xa0); b43_phy_write(dev, 0x46a, 0x19); b43_phy_maskset(dev, 0x663, 0xFF00, 0x64); b43_phy_lcn_tables_init(dev); b43_phy_lcn_rev0_baseband_init(dev); b43_phy_lcn_bu_tweaks(dev); if (dev->phy.radio_ver == 0x2064) b43_radio_2064_init(dev); else B43_WARN_ON(1); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_phy_lcn_tx_pwr_ctl_init(dev); b43_switch_channel(dev, dev->phy.channel); bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9); bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd); /* TODO */ b43_phy_set(dev, 0x448, 0x4000); udelay(100); b43_phy_mask(dev, 0x448, ~0x4000); /* TODO */ return 0; }
static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) { struct b43_phy_ht *phy_ht = dev->phy.ht; u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, B43_PHY_HT_TXPCTL_CMD_C2, B43_PHY_HT_TXPCTL_CMD_C3 }; static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1, B43_PHY_HT_TX_PCTL_STATUS_C2, B43_PHY_HT_TX_PCTL_STATUS_C3 }; int i; if (!enable) { if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { /* We disable enabled TX pwr ctl, save it's state */ for (i = 0; i < 3; i++) phy_ht->tx_pwr_idx[i] = b43_phy_read(dev, status_regs[i]); } b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); } else { b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { for (i = 0; i < 3; i++) b43_phy_write(dev, cmd_regs[i], 0x32); } for (i = 0; i < 3; i++) if (phy_ht->tx_pwr_idx[i] <= B43_PHY_HT_TXPCTL_CMD_C1_INIT) b43_phy_write(dev, cmd_regs[i], phy_ht->tx_pwr_idx[i]); } phy_ht->tx_pwr_ctl = enable; }
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) { struct b43_phy *phy = &(dev->phy); u16 channelcookie, savedcookie; int err; if (new_channel == B43_DEFAULT_CHANNEL) new_channel = phy->ops->get_default_chan(dev); /* First we set the channel radio code to prevent the * firmware from sending ghost packets. */ channelcookie = new_channel; if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) channelcookie |= B43_SHM_SH_CHAN_5GHZ; /* FIXME: set 40Mhz flag if required */ if (0) channelcookie |= B43_SHM_SH_CHAN_40MHZ; savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); /* Now try to switch the PHY hardware channel. */ err = phy->ops->switch_channel(dev, new_channel); if (err) goto err_restore_cookie; dev->phy.channel = new_channel; /* Wait for the radio to tune to the channel and stabilize. */ msleep(8); return 0; err_restore_cookie: b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, savedcookie); return err; }
static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) { struct b43_phy_ht *phy_ht = dev->phy.ht; u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, B43_PHY_HT_TXPCTL_CMD_C2, B43_PHY_HT_TXPCTL_CMD_C3 }; int i; if (!enable) { if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { /* We disable enabled TX pwr ctl, save it's state */ /* * TODO: find the registers. On N-PHY they were 0x1ed * and 0x1ee, we need 3 such a registers for HT-PHY */ } b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); } else { b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { for (i = 0; i < 3; i++) b43_phy_write(dev, cmd_regs[i], 0x32); } for (i = 0; i < 3; i++) if (phy_ht->tx_pwr_idx[i] <= B43_PHY_HT_TXPCTL_CMD_C1_INIT) b43_phy_write(dev, cmd_regs[i], phy_ht->tx_pwr_idx[i]); } phy_ht->tx_pwr_ctl = enable; }
static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) return 11; return 36; }
static int b43_phy_ht_op_init(struct b43_wldev *dev) { u16 tmp; u16 clip_state[3]; b43_phy_ht_tables_init(dev); b43_phy_mask(dev, 0x0be, ~0x2); b43_phy_set(dev, 0x23f, 0x7ff); b43_phy_set(dev, 0x240, 0x7ff); b43_phy_set(dev, 0x241, 0x7ff); b43_phy_ht_zero_extg(dev); b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); b43_phy_write(dev, 0x20d, 0xb8); b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); b43_phy_write(dev, 0x70, 0x50); b43_phy_write(dev, 0x1ff, 0x30); if (0) /* TODO: condition */ ; /* TODO: PHY op on reg 0x217 */ b43_phy_read(dev, 0xb0); /* TODO: what for? */ b43_phy_set(dev, 0xb0, 0x1); b43_phy_set(dev, 0xb1, 0x91); b43_phy_write(dev, 0x32f, 0x0003); b43_phy_write(dev, 0x077, 0x0010); b43_phy_write(dev, 0x0b4, 0x0258); b43_phy_mask(dev, 0x17e, ~0x4000); b43_phy_write(dev, 0x0b9, 0x0072); b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); b43_phy_ht_afe_unk1(dev); b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, 0x8e, 0x96, 0x96, 0x96); b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, 0x8f, 0x9f, 0x9f, 0x9f); b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, 0x8f, 0x9f, 0x9f, 0x9f); b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); /* TODO: Did wl mean 2 instead of 40? */ b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); /* Copy some tables entries */ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); /* Reset CCA */ b43_phy_force_clock(dev, true); tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); b43_phy_force_clock(dev, false); b43_mac_phy_clock_set(dev, true); b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); /* TODO: PHY op on reg 0xb0 */ /* TODO: Should we restore it? Or store it in global PHY info? */ b43_phy_ht_read_clip_detection(dev, clip_state); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_phy_ht_bphy_init(dev); b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); return 0; }
static int b43_phy_ht_op_init(struct b43_wldev *dev) { struct b43_phy_ht *phy_ht = dev->phy.ht; u16 tmp; u16 clip_state[3]; bool saved_tx_pwr_ctl; if (dev->dev->bus_type != B43_BUS_BCMA) { b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); return -EOPNOTSUPP; } b43_phy_ht_tables_init(dev); b43_phy_mask(dev, 0x0be, ~0x2); b43_phy_set(dev, 0x23f, 0x7ff); b43_phy_set(dev, 0x240, 0x7ff); b43_phy_set(dev, 0x241, 0x7ff); b43_phy_ht_zero_extg(dev); b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0); b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0); b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0); b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); b43_phy_write(dev, 0x20d, 0xb8); b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); b43_phy_write(dev, 0x70, 0x50); b43_phy_write(dev, 0x1ff, 0x30); if (0) /* TODO: condition */ ; /* TODO: PHY op on reg 0x217 */ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); else b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, B43_PHY_HT_CLASS_CTL_CCK_EN); b43_phy_set(dev, 0xb1, 0x91); b43_phy_write(dev, 0x32f, 0x0003); b43_phy_write(dev, 0x077, 0x0010); b43_phy_write(dev, 0x0b4, 0x0258); b43_phy_mask(dev, 0x17e, ~0x4000); b43_phy_write(dev, 0x0b9, 0x0072); b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); b43_phy_ht_afe_unk1(dev); b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, 0x8e, 0x96, 0x96, 0x96); b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, 0x8f, 0x9f, 0x9f, 0x9f); b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, 0x8f, 0x9f, 0x9f, 0x9f); b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); /* TODO: Did wl mean 2 instead of 40? */ b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, 0x09, 0x0e, 0x13, 0x18); b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); /* Copy some tables entries */ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); /* Reset CCA */ b43_phy_force_clock(dev, true); tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); b43_phy_force_clock(dev, false); b43_mac_phy_clock_set(dev, true); b43_phy_ht_pa_override(dev, false); b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); b43_phy_ht_pa_override(dev, true); /* TODO: Should we restore it? Or store it in global PHY info? */ b43_phy_ht_classifier(dev, 0, 0); b43_phy_ht_read_clip_detection(dev, clip_state); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) b43_phy_ht_bphy_init(dev); b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl; b43_phy_ht_tx_power_fix(dev); b43_phy_ht_tx_power_ctl(dev, false); b43_phy_ht_tx_power_ctl_idle_tssi(dev); b43_phy_ht_tx_power_ctl_setup(dev); b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl); return 0; }
static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) { struct b43_phy_ht *phy_ht = dev->phy.ht; struct ssb_sprom *sprom = dev->dev->bus_sprom; u8 *idle = phy_ht->idle_tssi; u8 target[3]; s16 a1[3], b0[3], b1[3]; u16 freq = dev->phy.channel_freq; int i, c; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { for (c = 0; c < 3; c++) { target[c] = sprom->core_pwr_info[c].maxpwr_2g; a1[c] = sprom->core_pwr_info[c].pa_2g[0]; b0[c] = sprom->core_pwr_info[c].pa_2g[1]; b1[c] = sprom->core_pwr_info[c].pa_2g[2]; } } else if (freq >= 4900 && freq < 5100) { for (c = 0; c < 3; c++) { target[c] = sprom->core_pwr_info[c].maxpwr_5gl; a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; } } else if (freq >= 5100 && freq < 5500) { for (c = 0; c < 3; c++) { target[c] = sprom->core_pwr_info[c].maxpwr_5g; a1[c] = sprom->core_pwr_info[c].pa_5g[0]; b0[c] = sprom->core_pwr_info[c].pa_5g[1]; b1[c] = sprom->core_pwr_info[c].pa_5g[2]; } } else if (freq >= 5500) { for (c = 0; c < 3; c++) { target[c] = sprom->core_pwr_info[c].maxpwr_5gh; a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; } } else { target[0] = target[1] = target[2] = 52; a1[0] = a1[1] = a1[2] = -424; b0[0] = b0[1] = b0[2] = 5612; b1[0] = b1[1] = b1[2] = -1393; } b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN); b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF); /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */ b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2, ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3, ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19); b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1, idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2, idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2, ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3, idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID, 0xf0); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2, 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT); #if 0 /* TODO: what to mask/set? */ b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0) b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0) #endif b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, ~B43_PHY_HT_TXPCTL_TARG_PWR_C1, target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF, target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT); b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2, ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3, target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT); for (c = 0; c < 3; c++) { s32 num, den, pwr; u32 regval[64]; for (i = 0; i < 64; i++) { num = 8 * (16 * b0[c] + b1[c] * i); den = 32768 + a1[c] * i; pwr = max((4 * num + den / 2) / den, -8); regval[i] = pwr; } b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval); } }