📄 lo.c
字号:
test_loctl.q != prev_loctl.q) && (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { b43_lo_write(dev, &test_loctl); feedth = lo_measure_feedthrough(dev, phy->lna_gain, phy->pga_gain, phy->trsw_rx_gain); if (feedth < d->lowest_feedth) { memcpy(probe_loctl, &test_loctl, sizeof(struct b43_loctl)); found_lower = 1; d->lowest_feedth = feedth; if ((d->nr_measured < 2) && (!has_loopback_gain(phy) || lo->rebuild)) break; } } memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl)); if (i == end) break; if (i == 8) i = 1; else i++; d->current_state = i; } return found_lower;}static void lo_probe_loctls_statemachine(struct b43_wldev *dev, struct b43_loctl *loctl, int *max_rx_gain){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_lo_g_statemachine d; u16 feedth; int found_lower; struct b43_loctl probe_loctl; int max_repeat = 1, repeat_cnt = 0; d.nr_measured = 0; d.state_val_multiplier = 1; if (has_loopback_gain(phy) && !lo->rebuild) d.state_val_multiplier = 3; memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); if (has_loopback_gain(phy) && lo->rebuild) max_repeat = 4; do { b43_lo_write(dev, &d.min_loctl); feedth = lo_measure_feedthrough(dev, phy->lna_gain, phy->pga_gain, phy->trsw_rx_gain); if (!lo->rebuild && feedth < 0x258) { if (feedth >= 0x12C) *max_rx_gain += 6; else *max_rx_gain += 3; feedth = lo_measure_feedthrough(dev, phy->lna_gain, phy->pga_gain, phy->trsw_rx_gain); } d.lowest_feedth = feedth; d.current_state = 0; do { B43_WARN_ON(! (d.current_state >= 0 && d.current_state <= 8)); memcpy(&probe_loctl, &d.min_loctl, sizeof(struct b43_loctl)); found_lower = lo_probe_possible_loctls(dev, &probe_loctl, &d); if (!found_lower) break; if ((probe_loctl.i == d.min_loctl.i) && (probe_loctl.q == d.min_loctl.q)) break; memcpy(&d.min_loctl, &probe_loctl, sizeof(struct b43_loctl)); d.nr_measured++; } while (d.nr_measured < 24); memcpy(loctl, &d.min_loctl, sizeof(struct b43_loctl)); if (has_loopback_gain(phy)) { if (d.lowest_feedth > 0x1194) *max_rx_gain -= 6; else if (d.lowest_feedth < 0x5DC) *max_rx_gain += 3; if (repeat_cnt == 0) { if (d.lowest_feedth <= 0x5DC) { d.state_val_multiplier = 1; repeat_cnt++; } else d.state_val_multiplier = 2; } else if (repeat_cnt == 2) d.state_val_multiplier = 1; } lo_measure_gain_values(dev, *max_rx_gain, has_loopback_gain(phy)); } while (++repeat_cnt < max_repeat);}#if B43_CALIB_ALL_LOCTLSstatic const struct b43_rfatt b43_full_rfatt_list_items[] = { { .att = 0, .with_padmix = 0, }, { .att = 1, .with_padmix = 0, }, { .att = 2, .with_padmix = 0, }, { .att = 3, .with_padmix = 0, }, { .att = 4, .with_padmix = 0, }, { .att = 5, .with_padmix = 0, }, { .att = 6, .with_padmix = 0, }, { .att = 7, .with_padmix = 0, }, { .att = 8, .with_padmix = 0, }, { .att = 9, .with_padmix = 0, }, { .att = 10, .with_padmix = 0, }, { .att = 11, .with_padmix = 0, }, { .att = 12, .with_padmix = 0, }, { .att = 13, .with_padmix = 0, }, { .att = 14, .with_padmix = 0, }, { .att = 15, .with_padmix = 0, }, { .att = 0, .with_padmix = 1, }, { .att = 1, .with_padmix = 1, }, { .att = 2, .with_padmix = 1, }, { .att = 3, .with_padmix = 1, }, { .att = 4, .with_padmix = 1, }, { .att = 5, .with_padmix = 1, }, { .att = 6, .with_padmix = 1, }, { .att = 7, .with_padmix = 1, }, { .att = 8, .with_padmix = 1, }, { .att = 9, .with_padmix = 1, }, { .att = 10, .with_padmix = 1, }, { .att = 11, .with_padmix = 1, }, { .att = 12, .with_padmix = 1, }, { .att = 13, .with_padmix = 1, }, { .att = 14, .with_padmix = 1, }, { .att = 15, .with_padmix = 1, },};static const struct b43_rfatt_list b43_full_rfatt_list = { .list = b43_full_rfatt_list_items, .len = ARRAY_SIZE(b43_full_rfatt_list_items),};static const struct b43_bbatt b43_full_bbatt_list_items[] = { { .att = 0, }, { .att = 1, }, { .att = 2, }, { .att = 3, }, { .att = 4, }, { .att = 5, }, { .att = 6, }, { .att = 7, }, { .att = 8, }, { .att = 9, }, { .att = 10, }, { .att = 11, },};static const struct b43_bbatt_list b43_full_bbatt_list = { .list = b43_full_bbatt_list_items, .len = ARRAY_SIZE(b43_full_bbatt_list_items),};#endif /* B43_CALIB_ALL_LOCTLS */static void lo_measure(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_loctl loctl = { .i = 0, .q = 0, }; struct b43_loctl *ploctl; int max_rx_gain; int rfidx, bbidx; const struct b43_bbatt_list *bbatt_list; const struct b43_rfatt_list *rfatt_list; /* Values from the "TXCTL Register and Value Table" */ u16 txctl_reg; u16 txctl_value; u16 pad_mix_gain; bbatt_list = &lo->bbatt_list; rfatt_list = &lo->rfatt_list;#if B43_CALIB_ALL_LOCTLS bbatt_list = &b43_full_bbatt_list; rfatt_list = &b43_full_rfatt_list;#endif txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); for (rfidx = 0; rfidx < rfatt_list->len; rfidx++) { b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) & 0xFFF0) | rfatt_list->list[rfidx].att); b43_radio_write16(dev, txctl_reg, (b43_radio_read16(dev, txctl_reg) & ~txctl_value) | (rfatt_list->list[rfidx].with_padmix ? txctl_value : 0)); for (bbidx = 0; bbidx < bbatt_list->len; bbidx++) { if (lo->rebuild) {#if B43_CALIB_ALL_LOCTLS ploctl = b43_get_lo_g_ctl(dev, &rfatt_list->list[rfidx], &bbatt_list->list[bbidx]);#else ploctl = b43_get_lo_g_ctl_nopadmix(dev, &rfatt_list-> list[rfidx], &bbatt_list-> list[bbidx]);#endif } else { ploctl = b43_get_lo_g_ctl(dev, &rfatt_list->list[rfidx], &bbatt_list->list[bbidx]); if (!ploctl->used) continue; } memcpy(&loctl, ploctl, sizeof(loctl)); loctl.i = 0; loctl.q = 0; max_rx_gain = rfatt_list->list[rfidx].att * 2; max_rx_gain += bbatt_list->list[bbidx].att / 2; if (rfatt_list->list[rfidx].with_padmix) max_rx_gain -= pad_mix_gain; if (has_loopback_gain(phy)) max_rx_gain += phy->max_lb_gain; lo_measure_gain_values(dev, max_rx_gain, has_loopback_gain(phy)); b43_phy_set_baseband_attenuation(dev, bbatt_list->list[bbidx].att); lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); if (phy->type == B43_PHYTYPE_B) { loctl.i++; loctl.q++; } b43_loctl_set_calibrated(&loctl, 1); memcpy(ploctl, &loctl, sizeof(loctl)); } }}#if B43_DEBUGstatic void do_validate_loctl(struct b43_wldev *dev, struct b43_loctl *control){ const int is_initializing = (b43_status(dev) == B43_STAT_UNINIT); int i = control->i; int q = control->q; if (b43_loctl_is_calibrated(control)) { if ((abs(i) > 16) || (abs(q) > 16)) goto error; } else { if (control->used) goto error; if (dev->phy.lo_control->rebuild) { control->i = 0; control->q = 0; if ((i != B43_LOCTL_POISON) || (q != B43_LOCTL_POISON)) goto error; } } if (is_initializing && control->used) goto error; return;error: b43err(dev->wl, "LO control pair validation failed " "(I: %d, Q: %d, used %u, calib: %u, initing: %d)\n", i, q, control->used, b43_loctl_is_calibrated(control), is_initializing);}static void validate_all_loctls(struct b43_wldev *dev){ b43_call_for_each_loctl(dev, do_validate_loctl);}static void do_reset_calib(struct b43_wldev *dev, struct b43_loctl *control){ if (dev->phy.lo_control->rebuild || control->used) { b43_loctl_set_calibrated(control, 0); control->i = B43_LOCTL_POISON; control->q = B43_LOCTL_POISON; }}static void reset_all_loctl_calibration_states(struct b43_wldev *dev){ b43_call_for_each_loctl(dev, do_reset_calib);}#else /* B43_DEBUG */static inline void validate_all_loctls(struct b43_wldev *dev) { }static inline void reset_all_loctl_calibration_states(struct b43_wldev *dev) { }#endif /* B43_DEBUG */void b43_lo_g_measure(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct lo_g_saved_values uninitialized_var(sav); B43_WARN_ON((phy->type != B43_PHYTYPE_B) && (phy->type != B43_PHYTYPE_G)); sav.old_channel = phy->channel; lo_measure_setup(dev, &sav); reset_all_loctl_calibration_states(dev); lo_measure(dev); lo_measure_restore(dev, &sav); validate_all_loctls(dev); phy->lo_control->lo_measured = 1; phy->lo_control->rebuild = 0;}#if B43_DEBUGstatic void validate_loctl_calibration(struct b43_wldev *dev, struct b43_loctl *loctl, struct b43_rfatt *rfatt, struct b43_bbatt *bbatt){ if (b43_loctl_is_calibrated(loctl)) return; if (!dev->phy.lo_control->lo_measured) { /* On init we set the attenuation values before we * calibrated the LO. I guess that's OK. */ return; } b43err(dev->wl, "Adjusting Local Oscillator to an uncalibrated " "control pair: rfatt=%u,%spadmix bbatt=%u\n", rfatt->att, (rfatt->with_padmix) ? "" : "no-", bbatt->att);}#elsestatic inline void validate_loctl_calibration(struct b43_wldev *dev, struct b43_loctl *loctl, struct b43_rfatt *rfatt, struct b43_bbatt *bbatt){}#endifstatic inline void fixup_rfatt_for_txcontrol(struct b43_rfatt *rf, u8 tx_control){ if (tx_control & B43_TXCTL_TXMIX) { if (rf->att < 5) rf->att = 4; }}void b43_lo_g_adjust(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_rfatt rf; struct b43_loctl *loctl; memcpy(&rf, &phy->rfatt, sizeof(rf)); fixup_rfatt_for_txcontrol(&rf, phy->tx_control); loctl = b43_get_lo_g_ctl(dev, &rf, &phy->bbatt); validate_loctl_calibration(dev, loctl, &rf, &phy->bbatt); b43_lo_write(dev, loctl);}void b43_lo_g_adjust_to(struct b43_wldev *dev, u16 rfatt, u16 bbatt, u16 tx_control){ struct b43_rfatt rf; struct b43_bbatt bb; struct b43_loctl *loctl; memset(&rf, 0, sizeof(rf)); memset(&bb, 0, sizeof(bb)); rf.att = rfatt; bb.att = bbatt; fixup_rfatt_for_txcontrol(&rf, tx_control); loctl = b43_get_lo_g_ctl(dev, &rf, &bb); validate_loctl_calibration(dev, loctl, &rf, &bb); b43_lo_write(dev, loctl);}static void do_mark_unused(struct b43_wldev *dev, struct b43_loctl *control){ control->used = 0;}void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; b43_call_for_each_loctl(dev, do_mark_unused); lo->rebuild = 1;}void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_rfatt rf; memcpy(&rf, &phy->rfatt, sizeof(rf)); fixup_rfatt_for_txcontrol(&rf, phy->tx_control); b43_get_lo_g_ctl(dev, &rf, &phy->bbatt)->used = 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -