Commit f5eda47f authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

b43: Rewrite LO calibration algorithm

This patch distributes the Local Oscillator calibration bursts over time,
so that calibration only happens when it's actually needed.
Currently we periodically perform a recalibration of the whole table.
The table is huge and this takes lots of time. Additionally only small bits
of the table are actually needed at a given time. So instead of maintaining
a huge table with all possible calibration values, we create dynamic calibration
settings that
a) We only calibrate when they are actually needed.
b) Are cached for some time until they expire.
So a recalibration might happen if we need a calibration setting that's not
cached, or if the active calibration setting expires.
Currently the expire timeout is set to 30 seconds. We may raise that in future.

This patch reduces overall memory consumption by nuking the
huge static calibration tables.

This patch has been tested on several 4306, 4311 and 4318 flavours.
Signed-off-by: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2afc4901
...@@ -270,24 +270,22 @@ static int restart_write_file(struct b43_wldev *dev, ...@@ -270,24 +270,22 @@ static int restart_write_file(struct b43_wldev *dev,
return err; return err;
} }
static ssize_t append_lo_table(ssize_t count, char *buf, const size_t bufsize, static unsigned long calc_expire_secs(unsigned long now,
struct b43_loctl table[B43_NR_BB][B43_NR_RF]) unsigned long time,
unsigned long expire)
{ {
unsigned int i, j; expire = time + expire;
struct b43_loctl *ctl;
if (time_after(now, expire))
for (i = 0; i < B43_NR_BB; i++) { return 0; /* expired */
for (j = 0; j < B43_NR_RF; j++) { if (expire < now) {
ctl = &(table[i][j]); /* jiffies wrapped */
fappend("(bbatt %2u, rfatt %2u) -> " expire -= MAX_JIFFY_OFFSET;
"(I %+3d, Q %+3d, Used: %d, Calibrated: %d)\n", now -= MAX_JIFFY_OFFSET;
i, j, ctl->i, ctl->q,
ctl->used,
b43_loctl_is_calibrated(ctl));
}
} }
B43_WARN_ON(expire < now);
return count; return (expire - now) / HZ;
} }
static ssize_t loctls_read_file(struct b43_wldev *dev, static ssize_t loctls_read_file(struct b43_wldev *dev,
...@@ -296,27 +294,45 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, ...@@ -296,27 +294,45 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
ssize_t count = 0; ssize_t count = 0;
struct b43_txpower_lo_control *lo; struct b43_txpower_lo_control *lo;
int i, err = 0; int i, err = 0;
struct b43_lo_calib *cal;
unsigned long now = jiffies;
struct b43_phy *phy = &dev->phy;
if (dev->phy.type != B43_PHYTYPE_G) { if (phy->type != B43_PHYTYPE_G) {
fappend("Device is not a G-PHY\n"); fappend("Device is not a G-PHY\n");
err = -ENODEV; err = -ENODEV;
goto out; goto out;
} }
lo = dev->phy.lo_control; lo = phy->lo_control;
fappend("-- Local Oscillator calibration data --\n\n"); fappend("-- Local Oscillator calibration data --\n\n");
fappend("Measured: %d, Rebuild: %d, HW-power-control: %d\n", fappend("HW-power-control enabled: %d\n",
lo->lo_measured,
lo->rebuild,
dev->phy.hardware_power_control); dev->phy.hardware_power_control);
fappend("TX Bias: 0x%02X, TX Magn: 0x%02X\n", fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n",
lo->tx_bias, lo->tx_magn); lo->tx_bias, lo->tx_magn,
fappend("Power Vector: 0x%08X%08X\n", calc_expire_secs(now, lo->txctl_measured_time,
B43_LO_TXCTL_EXPIRE));
fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n",
(unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
(unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL)); (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL),
fappend("\nControl table WITH PADMIX:\n"); calc_expire_secs(now, lo->pwr_vec_read_time,
count = append_lo_table(count, buf, bufsize, lo->with_padmix); B43_LO_PWRVEC_EXPIRE));
fappend("\nControl table WITHOUT PADMIX:\n");
count = append_lo_table(count, buf, bufsize, lo->no_padmix); fappend("\nCalibrated settings:\n");
list_for_each_entry(cal, &lo->calib_list, list) {
bool active;
active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
b43_compare_rfatt(&cal->rfatt, &phy->rfatt));
fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
"(expires in %lu sec)%s\n",
cal->bbatt.att,
cal->rfatt.att, cal->rfatt.with_padmix,
cal->ctl.i, cal->ctl.q,
calc_expire_secs(now, cal->calib_time,
B43_LO_CALIB_EXPIRE),
active ? " ACTIVE" : "");
}
fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n");
for (i = 0; i < lo->rfatt_list.len; i++) { for (i = 0; i < lo->rfatt_list.len; i++) {
fappend("%u(%d), ", fappend("%u(%d), ",
...@@ -351,7 +367,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, ...@@ -351,7 +367,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
struct b43_dfs_file *dfile; struct b43_dfs_file *dfile;
ssize_t uninitialized_var(ret); ssize_t uninitialized_var(ret);
char *buf; char *buf;
const size_t bufsize = 1024 * 128; const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
const size_t buforder = get_order(bufsize); const size_t buforder = get_order(bufsize);
int err = 0; int err = 0;
...@@ -380,8 +396,6 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, ...@@ -380,8 +396,6 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
err = -ENOMEM; err = -ENOMEM;
goto out_unlock; goto out_unlock;
} }
/* Sparse warns about the following memset, because it has a big
* size value. That warning is bogus, so I will ignore it. --mb */
memset(buf, 0, bufsize); memset(buf, 0, bufsize);
if (dfops->take_irqlock) { if (dfops->take_irqlock) {
spin_lock_irq(&dev->wl->irq_lock); spin_lock_irq(&dev->wl->irq_lock);
...@@ -523,6 +537,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) ...@@ -523,6 +537,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0);
add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0);
add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
#undef add_dyn_dbg #undef add_dyn_dbg
} }
......
...@@ -10,6 +10,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ ...@@ -10,6 +10,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
B43_DBG_DMAVERBOSE, B43_DBG_DMAVERBOSE,
B43_DBG_PWORK_FAST, B43_DBG_PWORK_FAST,
B43_DBG_PWORK_STOP, B43_DBG_PWORK_STOP,
B43_DBG_LO,
__B43_NR_DYNDBG, __B43_NR_DYNDBG,
}; };
......
This diff is collapsed.
...@@ -10,82 +10,63 @@ struct b43_loctl { ...@@ -10,82 +10,63 @@ struct b43_loctl {
/* Control values. */ /* Control values. */
s8 i; s8 i;
s8 q; s8 q;
/* "Used by hardware" flag. */
bool used;
#ifdef CONFIG_B43_DEBUG
/* Is this lo-control-array entry calibrated? */
bool calibrated;
#endif
}; };
/* Debugging: Poison value for i and q values. */ /* Debugging: Poison value for i and q values. */
#define B43_LOCTL_POISON 111 #define B43_LOCTL_POISON 111
/* loctl->calibrated debugging mechanism */ /* This struct holds calibrated LO settings for a set of
#ifdef CONFIG_B43_DEBUG * Baseband and RF attenuation settings. */
static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, struct b43_lo_calib {
bool calibrated) /* The set of attenuation values this set of LO
{ * control values is calibrated for. */
loctl->calibrated = calibrated; struct b43_bbatt bbatt;
} struct b43_rfatt rfatt;
static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) /* The set of control values for the LO. */
{ struct b43_loctl ctl;
return loctl->calibrated; /* The time when these settings were calibrated (in jiffies) */
} unsigned long calib_time;
#else /* List. */
static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, struct list_head list;
bool calibrated) };
{
} /* Size of the DC Lookup Table in 16bit words. */
static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) #define B43_DC_LT_SIZE 32
{
return 1; /* Local Oscillator calibration information */
}
#endif
/* TX Power LO Control Array.
* Value-pairs to adjust the LocalOscillator are stored
* in this structure.
* There are two different set of values. One for "Flag is Set"
* and one for "Flag is Unset".
* By "Flag" the flag in struct b43_rfatt is meant.
* The Value arrays are two-dimensional. The first index
* is the baseband attenuation and the second index
* is the radio attenuation.
* Use b43_get_lo_g_ctl() to retrieve a value from the lists.
*/
struct b43_txpower_lo_control { struct b43_txpower_lo_control {
#define B43_NR_BB 12 /* Lists of RF and BB attenuation values for this device.
#define B43_NR_RF 16 * Used for building hardware power control tables. */
/* LO Control values, with PAD Mixer */
struct b43_loctl with_padmix[B43_NR_BB][B43_NR_RF];
/* LO Control values, without PAD Mixer */
struct b43_loctl no_padmix[B43_NR_BB][B43_NR_RF];
/* Flag to indicate a complete rebuild of the two tables above
* to the LO measuring code. */
bool rebuild;
/* Lists of valid RF and BB attenuation values for this device. */
struct b43_rfatt_list rfatt_list; struct b43_rfatt_list rfatt_list;
struct b43_bbatt_list bbatt_list; struct b43_bbatt_list bbatt_list;
/* The DC Lookup Table is cached in memory here.
* Note that this is only used for Hardware Power Control. */
u16 dc_lt[B43_DC_LT_SIZE];
/* List of calibrated control values (struct b43_lo_calib). */
struct list_head calib_list;
/* Last time the power vector was read (jiffies). */
unsigned long pwr_vec_read_time;
/* Last time the txctl values were measured (jiffies). */
unsigned long txctl_measured_time;
/* Current TX Bias value */ /* Current TX Bias value */
u8 tx_bias; u8 tx_bias;
/* Current TX Magnification Value (if used by the device) */ /* Current TX Magnification Value (if used by the device) */
u8 tx_magn; u8 tx_magn;
/* GPHY LO is measured. */
bool lo_measured;
/* Saved device PowerVector */ /* Saved device PowerVector */
u64 power_vector; u64 power_vector;
}; };
/* Measure the BPHY Local Oscillator. */ /* Calibration expire timeouts.
void b43_lo_b_measure(struct b43_wldev *dev); * Timeouts must be multiple of 15 seconds. To make sure
/* Measure the BPHY/GPHY Local Oscillator. */ * the item really expired when the 15 second timer hits, we
void b43_lo_g_measure(struct b43_wldev *dev); * subtract two additional seconds from the timeout. */
#define B43_LO_CALIB_EXPIRE (HZ * (30 - 2))
#define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2))
#define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4))
/* Adjust the Local Oscillator to the saved attenuation /* Adjust the Local Oscillator to the saved attenuation
* and txctl values. * and txctl values.
...@@ -95,18 +76,10 @@ void b43_lo_g_adjust(struct b43_wldev *dev); ...@@ -95,18 +76,10 @@ void b43_lo_g_adjust(struct b43_wldev *dev);
void b43_lo_g_adjust_to(struct b43_wldev *dev, void b43_lo_g_adjust_to(struct b43_wldev *dev,
u16 rfatt, u16 bbatt, u16 tx_control); u16 rfatt, u16 bbatt, u16 tx_control);
/* Mark all possible b43_lo_g_ctl as "unused" */ void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all);
void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev);
/* Mark the b43_lo_g_ctl corresponding to the current
* attenuation values as used.
*/
void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev);
/* Get a reference to a LO Control value pair in the void b43_lo_g_maintanance_work(struct b43_wldev *dev);
* TX Power LO Control Array. void b43_lo_g_cleanup(struct b43_wldev *dev);
*/ void b43_lo_g_init(struct b43_wldev *dev);
struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev,
const struct b43_rfatt *rfatt,
const struct b43_bbatt *bbatt);
#endif /* B43_LO_H_ */ #endif /* B43_LO_H_ */
...@@ -2308,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) ...@@ -2308,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
} }
/* http://bcm-specs.sipsolutions.net/EnableMac */ /* http://bcm-specs.sipsolutions.net/EnableMac */
static void b43_mac_enable(struct b43_wldev *dev) void b43_mac_enable(struct b43_wldev *dev)
{ {
dev->mac_suspended--; dev->mac_suspended--;
B43_WARN_ON(dev->mac_suspended < 0); B43_WARN_ON(dev->mac_suspended < 0);
...@@ -2331,7 +2331,7 @@ static void b43_mac_enable(struct b43_wldev *dev) ...@@ -2331,7 +2331,7 @@ static void b43_mac_enable(struct b43_wldev *dev)
} }
/* http://bcm-specs.sipsolutions.net/SuspendMAC */ /* http://bcm-specs.sipsolutions.net/SuspendMAC */
static void b43_mac_suspend(struct b43_wldev *dev) void b43_mac_suspend(struct b43_wldev *dev)
{ {
int i; int i;
u32 tmp; u32 tmp;
...@@ -2503,6 +2503,7 @@ static void b43_chip_exit(struct b43_wldev *dev) ...@@ -2503,6 +2503,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
{ {
b43_radio_turn_off(dev, 1); b43_radio_turn_off(dev, 1);
b43_gpio_cleanup(dev); b43_gpio_cleanup(dev);
b43_lo_g_cleanup(dev);
/* firmware is released later */ /* firmware is released later */
} }
...@@ -2609,28 +2610,12 @@ static int b43_chip_init(struct b43_wldev *dev) ...@@ -2609,28 +2610,12 @@ static int b43_chip_init(struct b43_wldev *dev)
return err; return err;
} }
static void b43_periodic_every120sec(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
if (phy->type != B43_PHYTYPE_G || phy->rev < 2)
return;
b43_mac_suspend(dev);
b43_lo_g_measure(dev);
b43_mac_enable(dev);
if (b43_has_hardware_pctl(phy))
b43_lo_g_ctl_mark_all_unused(dev);
}
static void b43_periodic_every60sec(struct b43_wldev *dev) static void b43_periodic_every60sec(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
if (phy->type != B43_PHYTYPE_G) if (phy->type != B43_PHYTYPE_G)
return; return;
if (!b43_has_hardware_pctl(phy))
b43_lo_g_ctl_mark_all_unused(dev);
if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
b43_mac_suspend(dev); b43_mac_suspend(dev);
b43_calc_nrssi_slope(dev); b43_calc_nrssi_slope(dev);
...@@ -2682,6 +2667,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) ...@@ -2682,6 +2667,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
} }
} }
b43_phy_xmitpower(dev); //FIXME: unless scanning? b43_phy_xmitpower(dev); //FIXME: unless scanning?
b43_lo_g_maintanance_work(dev);
//TODO for APHY (temperature?) //TODO for APHY (temperature?)
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
...@@ -2693,8 +2679,6 @@ static void do_periodic_work(struct b43_wldev *dev) ...@@ -2693,8 +2679,6 @@ static void do_periodic_work(struct b43_wldev *dev)
unsigned int state; unsigned int state;
state = dev->periodic_state; state = dev->periodic_state;
if (state % 8 == 0)
b43_periodic_every120sec(dev);
if (state % 4 == 0) if (state % 4 == 0)
b43_periodic_every60sec(dev); b43_periodic_every60sec(dev);
if (state % 2 == 0) if (state % 2 == 0)
...@@ -3668,8 +3652,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev, ...@@ -3668,8 +3652,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
lo = phy->lo_control; lo = phy->lo_control;
if (lo) { if (lo) {
memset(lo, 0, sizeof(*(phy->lo_control))); memset(lo, 0, sizeof(*(phy->lo_control)));
lo->rebuild = 1;
lo->tx_bias = 0xFF; lo->tx_bias = 0xFF;
INIT_LIST_HEAD(&lo->calib_list);
} }
phy->max_lb_gain = 0; phy->max_lb_gain = 0;
phy->trsw_rx_gain = 0; phy->trsw_rx_gain = 0;
......
...@@ -114,4 +114,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason); ...@@ -114,4 +114,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason);
#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ #define B43_PS_ASLEEP (1 << 3) /* Force device asleep */
void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
void b43_mac_suspend(struct b43_wldev *dev);
void b43_mac_enable(struct b43_wldev *dev);
#endif /* B43_MAIN_H_ */ #endif /* B43_MAIN_H_ */
...@@ -145,8 +145,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, ...@@ -145,8 +145,7 @@ static void generate_rfatt_list(struct b43_wldev *dev,
{.att = 9,.with_padmix = 1,}, {.att = 9,.with_padmix = 1,},
}; };
if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) || if (!b43_has_hardware_pctl(phy)) {
(phy->type == B43_PHYTYPE_G && phy->rev < 6)) {
/* Software pctl */ /* Software pctl */
list->list = rfatt_0; list->list = rfatt_0;
list->len = ARRAY_SIZE(rfatt_0); list->len = ARRAY_SIZE(rfatt_0);
...@@ -158,7 +157,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, ...@@ -158,7 +157,7 @@ static void generate_rfatt_list(struct b43_wldev *dev,
/* Hardware pctl */ /* Hardware pctl */
list->list = rfatt_1; list->list = rfatt_1;
list->len = ARRAY_SIZE(rfatt_1); list->len = ARRAY_SIZE(rfatt_1);
list->min_val = 2; list->min_val = 0;
list->max_val = 14; list->max_val = 14;
return; return;
} }
...@@ -346,6 +345,7 @@ void b43_set_txpower_g(struct b43_wldev *dev, ...@@ -346,6 +345,7 @@ void b43_set_txpower_g(struct b43_wldev *dev,
/* Save the values for later */ /* Save the values for later */
phy->tx_control = tx_control; phy->tx_control = tx_control;
memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); memcpy(&phy->rfatt, rfatt, sizeof(*rfatt));
phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);
memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); memcpy(&phy->bbatt, bbatt, sizeof(*bbatt));
if (b43_debug(dev, B43_DBG_XMITPOWER)) { if (b43_debug(dev, B43_DBG_XMITPOWER)) {
...@@ -559,11 +559,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) ...@@ -559,11 +559,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
u16 tmp; u16 tmp;
u8 rf, bb; u8 rf, bb;
if (!lo->lo_measured) {
b43_phy_write(dev, 0x3FF, 0);
return;
}
for (rf = 0; rf < lo->rfatt_list.len; rf++) { for (rf = 0; rf < lo->rfatt_list.len; rf++) {
for (bb = 0; bb < lo->bbatt_list.len; bb++) { for (bb = 0; bb < lo->bbatt_list.len; bb++) {
if (nr_written >= 0x40) if (nr_written >= 0x40)
...@@ -581,42 +576,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) ...@@ -581,42 +576,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
} }
} }
/* GPHY_DC_Lookup_Table */
void b43_gphy_dc_lt_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_txpower_lo_control *lo = phy->lo_control;
struct b43_loctl *loctl0;
struct b43_loctl *loctl1;
int i;
int rf_offset, bb_offset;
u16 tmp;
for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) {
rf_offset = i / lo->rfatt_list.len;
bb_offset = i % lo->rfatt_list.len;
loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
&lo->bbatt_list.list[bb_offset]);
if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) {
rf_offset = (i + 1) / lo->rfatt_list.len;
bb_offset = (i + 1) % lo->rfatt_list.len;
loctl1 =
b43_get_lo_g_ctl(dev,
&lo->rfatt_list.list[rf_offset],
&lo->bbatt_list.list[bb_offset]);
} else
loctl1 = loctl0;
tmp = ((u16) loctl0->q & 0xF);
tmp |= ((u16) loctl0->i & 0xF) << 4;
tmp |= ((u16) loctl1->q & 0xF) << 8;
tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME?
b43_phy_write(dev, 0x3A0 + (i / 2), tmp);
}
}
static void hardware_pctl_init_aphy(struct b43_wldev *dev) static void hardware_pctl_init_aphy(struct b43_wldev *dev)
{ {
//TODO //TODO
...@@ -643,7 +602,7 @@ static void hardware_pctl_init_gphy(struct b43_wldev *dev) ...@@ -643,7 +602,7 @@ static void hardware_pctl_init_gphy(struct b43_wldev *dev)
b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801)
& 0xFFBF); & 0xFFBF);
b43_gphy_dc_lt_init(dev); b43_gphy_dc_lt_init(dev, 1);
} }
/* HardwarePowerControl init for A and G PHY */ /* HardwarePowerControl init for A and G PHY */
...@@ -967,7 +926,7 @@ static void b43_phy_initb2(struct b43_wldev *dev) ...@@ -967,7 +926,7 @@ static void b43_phy_initb2(struct b43_wldev *dev)
b43_phy_write(dev, 0x0032, 0x00CA); b43_phy_write(dev, 0x0032, 0x00CA);
b43_phy_write(dev, 0x0032, 0x00CC); b43_phy_write(dev, 0x0032, 0x00CC);
b43_phy_write(dev, 0x0035, 0x07C2); b43_phy_write(dev, 0x0035, 0x07C2);
b43_lo_b_measure(dev); //XXX won't trigger b43_lo_b_measure(dev);
b43_phy_write(dev, 0x0026, 0xCC00); b43_phy_write(dev, 0x0026, 0xCC00);
if (phy->radio_ver != 0x2050) if (phy->radio_ver != 0x2050)
b43_phy_write(dev, 0x0026, 0xCE00); b43_phy_write(dev, 0x0026, 0xCE00);
...@@ -1017,7 +976,7 @@ static void b43_phy_initb4(struct b43_wldev *dev) ...@@ -1017,7 +976,7 @@ static void b43_phy_initb4(struct b43_wldev *dev)
b43_phy_write(dev, 0x0032, 0x00E0); b43_phy_write(dev, 0x0032, 0x00E0);
b43_phy_write(dev, 0x0035, 0x07C2); b43_phy_write(dev, 0x0035, 0x07C2);
b43_lo_b_measure(dev); //XXX won't trigger b43_lo_b_measure(dev);
b43_phy_write(dev, 0x0026, 0xCC00); b43_phy_write(dev, 0x0026, 0xCC00);
if (phy->radio_ver == 0x2050) if (phy->radio_ver == 0x2050)
...@@ -1259,19 +1218,9 @@ static void b43_phy_initb6(struct b43_wldev *dev) ...@@ -1259,19 +1218,9 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0)
| 0x0004); | 0x0004);
} }
if (phy->type == B43_PHYTYPE_B) { if (phy->type == B43_PHYTYPE_B)
b43_write16(dev, 0x03E6, 0x8140); B43_WARN_ON(1);
b43_phy_write(dev, 0x0016, 0x0410); else if (phy->type == B43_PHYTYPE_G)
b43_phy_write(dev, 0x0017, 0x0820);
b43_phy_write(dev, 0x0062, 0x0007);
b43_radio_init2050(dev);
b43_lo_g_measure(dev);
if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
b43_calc_nrssi_slope(dev);
b43_calc_nrssi_threshold(dev);
}
b43_phy_init_pctl(dev);
} else if (phy->type == B43_PHYTYPE_G)
b43_write16(dev, 0x03E6, 0x0); b43_write16(dev, 0x03E6, 0x0);
} }
...@@ -1534,34 +1483,31 @@ static void b43_phy_initg(struct b43_wldev *dev) ...@@ -1534,34 +1483,31 @@ static void b43_phy_initg(struct b43_wldev *dev)
else else
b43_radio_write16(dev, 0x0078, phy->initval); b43_radio_write16(dev, 0x0078, phy->initval);
} }
if (phy->lo_control->tx_bias == 0xFF) { b43_lo_g_init(dev);
b43_lo_g_measure(dev); if (has_tx_magnification(phy)) {
b43_radio_write16(dev, 0x52,
(b43_radio_read16(dev, 0x52) & 0xFF00)
| phy->lo_control->tx_bias | phy->
lo_control->tx_magn);
} else { } else {
if (has_tx_magnification(phy)) { b43_radio_write16(dev, 0x52,
b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) & 0xFFF0)
(b43_radio_read16(dev, 0x52) & 0xFF00) | phy->lo_control->tx_bias);
| phy->lo_control->tx_bias | phy->
lo_control->tx_magn);
} else {
b43_radio_write16(dev, 0x52,
(b43_radio_read16(dev, 0x52) & 0xFFF0)
| phy->lo_control->tx_bias);
}
if (phy->rev >= 6) {
b43_phy_write(dev, B43_PHY_CCK(0x36),
(b43_phy_read(dev, B43_PHY_CCK(0x36))
& 0x0FFF) | (phy->lo_control->
tx_bias << 12));
}
if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
if (phy->rev < 2)
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
else
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
} }
if (phy->rev >= 6) {
b43_phy_write(dev, B43_PHY_CCK(0x36),
(b43_phy_read(dev, B43_PHY_CCK(0x36))
& 0x0FFF) | (phy->lo_control->
tx_bias << 12));
}
if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
if (phy->rev < 2)
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
else
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
if (phy->gmode || phy->rev >= 2) { if (phy->gmode || phy->rev >= 2) {
b43_lo_g_adjust(dev); b43_lo_g_adjust(dev);
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
...@@ -1821,10 +1767,8 @@ void b43_phy_xmitpower(struct b43_wldev *dev) ...@@ -1821,10 +1767,8 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
bbatt_delta -= 4 * rfatt_delta; bbatt_delta -= 4 * rfatt_delta;
/* So do we finally need to adjust something? */ /* So do we finally need to adjust something? */
if ((rfatt_delta == 0) && (bbatt_delta == 0)) { if ((rfatt_delta == 0) && (bbatt_delta == 0))
b43_lo_g_ctl_mark_cur_used(dev);
return; return;
}
/* Calculate the new attenuation values. */ /* Calculate the new attenuation values. */
bbatt = phy->bbatt.att; bbatt = phy->bbatt.att;
...@@ -1870,7 +1814,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev) ...@@ -1870,7 +1814,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
b43_radio_lock(dev); b43_radio_lock(dev);
b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt,
phy->tx_control); phy->tx_control);
b43_lo_g_ctl_mark_cur_used(dev);
b43_radio_unlock(dev); b43_radio_unlock(dev);
b43_phy_unlock(dev); b43_phy_unlock(dev);
break; break;
......
...@@ -225,7 +225,6 @@ int b43_phy_init(struct b43_wldev *dev); ...@@ -225,7 +225,6 @@ int b43_phy_init(struct b43_wldev *dev);
void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); void b43_set_rx_antenna(struct b43_wldev *dev, int antenna);
void b43_phy_xmitpower(struct b43_wldev *dev); void b43_phy_xmitpower(struct b43_wldev *dev);
void b43_gphy_dc_lt_init(struct b43_wldev *dev);
/* Returns the boolean whether the board has HardwarePowerControl */ /* Returns the boolean whether the board has HardwarePowerControl */
bool b43_has_hardware_pctl(struct b43_phy *phy); bool b43_has_hardware_pctl(struct b43_phy *phy);
...@@ -252,6 +251,14 @@ struct b43_rfatt_list { ...@@ -252,6 +251,14 @@ struct b43_rfatt_list {
u8 max_val; u8 max_val;
}; };
/* Returns true, if the values are the same. */
static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
const struct b43_rfatt *b)
{
return ((a->att == b->att) &&
(a->with_padmix == b->with_padmix));
}
/* Baseband Attenuation */ /* Baseband Attenuation */
struct b43_bbatt { struct b43_bbatt {
u8 att; /* Attenuation value */ u8 att; /* Attenuation value */
...@@ -265,6 +272,13 @@ struct b43_bbatt_list { ...@@ -265,6 +272,13 @@ struct b43_bbatt_list {
u8 max_val; u8 max_val;
}; };
/* Returns true, if the values are the same. */
static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
const struct b43_bbatt *b)
{
return (a->att == b->att);
}
/* tx_control bits. */ /* tx_control bits. */
#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment