aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-04-20 10:03:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:12 -0400
commitf5eda47f45e90dfa38e25d569b9ac84ba94f8301 (patch)
tree5f806ae4729696cebef0bef0c261c6353b18045a /drivers
parent2afc49015db927fea7bc6ca33c0a60bf5d7c2c5f (diff)
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: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/b43/debugfs.c77
-rw-r--r--drivers/net/wireless/b43/debugfs.h1
-rw-r--r--drivers/net/wireless/b43/lo.c721
-rw-r--r--drivers/net/wireless/b43/lo.h115
-rw-r--r--drivers/net/wireless/b43/main.c26
-rw-r--r--drivers/net/wireless/b43/main.h3
-rw-r--r--drivers/net/wireless/b43/phy.c123
-rw-r--r--drivers/net/wireless/b43/phy.h16
8 files changed, 396 insertions, 686 deletions
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 7fca2ebc747f..210e2789c1c3 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -270,24 +270,22 @@ static int restart_write_file(struct b43_wldev *dev,
270 return err; 270 return err;
271} 271}
272 272
273static ssize_t append_lo_table(ssize_t count, char *buf, const size_t bufsize, 273static unsigned long calc_expire_secs(unsigned long now,
274 struct b43_loctl table[B43_NR_BB][B43_NR_RF]) 274 unsigned long time,
275 unsigned long expire)
275{ 276{
276 unsigned int i, j; 277 expire = time + expire;
277 struct b43_loctl *ctl; 278
278 279 if (time_after(now, expire))
279 for (i = 0; i < B43_NR_BB; i++) { 280 return 0; /* expired */
280 for (j = 0; j < B43_NR_RF; j++) { 281 if (expire < now) {
281 ctl = &(table[i][j]); 282 /* jiffies wrapped */
282 fappend("(bbatt %2u, rfatt %2u) -> " 283 expire -= MAX_JIFFY_OFFSET;
283 "(I %+3d, Q %+3d, Used: %d, Calibrated: %d)\n", 284 now -= MAX_JIFFY_OFFSET;
284 i, j, ctl->i, ctl->q,
285 ctl->used,
286 b43_loctl_is_calibrated(ctl));
287 }
288 } 285 }
286 B43_WARN_ON(expire < now);
289 287
290 return count; 288 return (expire - now) / HZ;
291} 289}
292 290
293static ssize_t loctls_read_file(struct b43_wldev *dev, 291static ssize_t loctls_read_file(struct b43_wldev *dev,
@@ -296,27 +294,45 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
296 ssize_t count = 0; 294 ssize_t count = 0;
297 struct b43_txpower_lo_control *lo; 295 struct b43_txpower_lo_control *lo;
298 int i, err = 0; 296 int i, err = 0;
297 struct b43_lo_calib *cal;
298 unsigned long now = jiffies;
299 struct b43_phy *phy = &dev->phy;
299 300
300 if (dev->phy.type != B43_PHYTYPE_G) { 301 if (phy->type != B43_PHYTYPE_G) {
301 fappend("Device is not a G-PHY\n"); 302 fappend("Device is not a G-PHY\n");
302 err = -ENODEV; 303 err = -ENODEV;
303 goto out; 304 goto out;
304 } 305 }
305 lo = dev->phy.lo_control; 306 lo = phy->lo_control;
306 fappend("-- Local Oscillator calibration data --\n\n"); 307 fappend("-- Local Oscillator calibration data --\n\n");
307 fappend("Measured: %d, Rebuild: %d, HW-power-control: %d\n", 308 fappend("HW-power-control enabled: %d\n",
308 lo->lo_measured,
309 lo->rebuild,
310 dev->phy.hardware_power_control); 309 dev->phy.hardware_power_control);
311 fappend("TX Bias: 0x%02X, TX Magn: 0x%02X\n", 310 fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n",
312 lo->tx_bias, lo->tx_magn); 311 lo->tx_bias, lo->tx_magn,
313 fappend("Power Vector: 0x%08X%08X\n", 312 calc_expire_secs(now, lo->txctl_measured_time,
313 B43_LO_TXCTL_EXPIRE));
314 fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n",
314 (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), 315 (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
315 (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL)); 316 (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL),
316 fappend("\nControl table WITH PADMIX:\n"); 317 calc_expire_secs(now, lo->pwr_vec_read_time,
317 count = append_lo_table(count, buf, bufsize, lo->with_padmix); 318 B43_LO_PWRVEC_EXPIRE));
318 fappend("\nControl table WITHOUT PADMIX:\n"); 319
319 count = append_lo_table(count, buf, bufsize, lo->no_padmix); 320 fappend("\nCalibrated settings:\n");
321 list_for_each_entry(cal, &lo->calib_list, list) {
322 bool active;
323
324 active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
325 b43_compare_rfatt(&cal->rfatt, &phy->rfatt));
326 fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
327 "(expires in %lu sec)%s\n",
328 cal->bbatt.att,
329 cal->rfatt.att, cal->rfatt.with_padmix,
330 cal->ctl.i, cal->ctl.q,
331 calc_expire_secs(now, cal->calib_time,
332 B43_LO_CALIB_EXPIRE),
333 active ? " ACTIVE" : "");
334 }
335
320 fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); 336 fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n");
321 for (i = 0; i < lo->rfatt_list.len; i++) { 337 for (i = 0; i < lo->rfatt_list.len; i++) {
322 fappend("%u(%d), ", 338 fappend("%u(%d), ",
@@ -351,7 +367,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
351 struct b43_dfs_file *dfile; 367 struct b43_dfs_file *dfile;
352 ssize_t uninitialized_var(ret); 368 ssize_t uninitialized_var(ret);
353 char *buf; 369 char *buf;
354 const size_t bufsize = 1024 * 128; 370 const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
355 const size_t buforder = get_order(bufsize); 371 const size_t buforder = get_order(bufsize);
356 int err = 0; 372 int err = 0;
357 373
@@ -380,8 +396,6 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
380 err = -ENOMEM; 396 err = -ENOMEM;
381 goto out_unlock; 397 goto out_unlock;
382 } 398 }
383 /* Sparse warns about the following memset, because it has a big
384 * size value. That warning is bogus, so I will ignore it. --mb */
385 memset(buf, 0, bufsize); 399 memset(buf, 0, bufsize);
386 if (dfops->take_irqlock) { 400 if (dfops->take_irqlock) {
387 spin_lock_irq(&dev->wl->irq_lock); 401 spin_lock_irq(&dev->wl->irq_lock);
@@ -523,6 +537,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
523 add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); 537 add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0);
524 add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); 538 add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0);
525 add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); 539 add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
540 add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
526 541
527#undef add_dyn_dbg 542#undef add_dyn_dbg
528} 543}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index 6eebe858db5a..c75cff4151d9 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -10,6 +10,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
10 B43_DBG_DMAVERBOSE, 10 B43_DBG_DMAVERBOSE,
11 B43_DBG_PWORK_FAST, 11 B43_DBG_PWORK_FAST,
12 B43_DBG_PWORK_STOP, 12 B43_DBG_PWORK_STOP,
13 B43_DBG_LO,
13 __B43_NR_DYNDBG, 14 __B43_NR_DYNDBG,
14}; 15};
15 16
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index d890f366a23b..4edee6da2b8b 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -36,10 +36,22 @@
36#include <linux/sched.h> 36#include <linux/sched.h>
37 37
38 38
39/* Define to 1 to always calibrate all possible LO control pairs. 39static struct b43_lo_calib * b43_find_lo_calib(struct b43_txpower_lo_control *lo,
40 * This is a workaround until we fix the partial LO calibration optimization. */ 40 const struct b43_bbatt *bbatt,
41#define B43_CALIB_ALL_LOCTLS 1 41 const struct b43_rfatt *rfatt)
42{
43 struct b43_lo_calib *c;
44
45 list_for_each_entry(c, &lo->calib_list, list) {
46 if (!b43_compare_bbatt(&c->bbatt, bbatt))
47 continue;
48 if (!b43_compare_rfatt(&c->rfatt, rfatt))
49 continue;
50 return c;
51 }
42 52
53 return NULL;
54}
43 55
44/* Write the LocalOscillator Control (adjust) value-pair. */ 56/* Write the LocalOscillator Control (adjust) value-pair. */
45static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) 57static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control)
@@ -64,183 +76,6 @@ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control)
64 b43_phy_write(dev, reg, value); 76 b43_phy_write(dev, reg, value);
65} 77}
66 78
67static int assert_rfatt_and_bbatt(const struct b43_rfatt *rfatt,
68 const struct b43_bbatt *bbatt,
69 struct b43_wldev *dev)
70{
71 int err = 0;
72
73 /* Check the attenuation values against the LO control array sizes. */
74 if (unlikely(rfatt->att >= B43_NR_RF)) {
75 b43err(dev->wl, "rfatt(%u) >= size of LO array\n", rfatt->att);
76 err = -EINVAL;
77 }
78 if (unlikely(bbatt->att >= B43_NR_BB)) {
79 b43err(dev->wl, "bbatt(%u) >= size of LO array\n", bbatt->att);
80 err = -EINVAL;
81 }
82
83 return err;
84}
85
86#if !B43_CALIB_ALL_LOCTLS
87static
88struct b43_loctl *b43_get_lo_g_ctl_nopadmix(struct b43_wldev *dev,
89 const struct b43_rfatt *rfatt,
90 const struct b43_bbatt *bbatt)
91{
92 struct b43_phy *phy = &dev->phy;
93 struct b43_txpower_lo_control *lo = phy->lo_control;
94
95 if (assert_rfatt_and_bbatt(rfatt, bbatt, dev))
96 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
97 return &(lo->no_padmix[bbatt->att][rfatt->att]);
98}
99#endif /* !B43_CALIB_ALL_LOCTLS */
100
101struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev,
102 const struct b43_rfatt *rfatt,
103 const struct b43_bbatt *bbatt)
104{
105 struct b43_phy *phy = &dev->phy;
106 struct b43_txpower_lo_control *lo = phy->lo_control;
107
108 if (assert_rfatt_and_bbatt(rfatt, bbatt, dev))
109 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
110 if (rfatt->with_padmix)
111 return &(lo->with_padmix[bbatt->att][rfatt->att]);
112 return &(lo->no_padmix[bbatt->att][rfatt->att]);
113}
114
115/* Call a function for every possible LO control value-pair. */
116static void b43_call_for_each_loctl(struct b43_wldev *dev,
117 void (*func) (struct b43_wldev *,
118 struct b43_loctl *))
119{
120 struct b43_phy *phy = &dev->phy;
121 struct b43_txpower_lo_control *ctl = phy->lo_control;
122 int i, j;
123
124 for (i = 0; i < B43_NR_BB; i++) {
125 for (j = 0; j < B43_NR_RF; j++)
126 func(dev, &(ctl->with_padmix[i][j]));
127 }
128 for (i = 0; i < B43_NR_BB; i++) {
129 for (j = 0; j < B43_NR_RF; j++)
130 func(dev, &(ctl->no_padmix[i][j]));
131 }
132}
133
134static u16 lo_b_r15_loop(struct b43_wldev *dev)
135{
136 int i;
137 u16 ret = 0;
138
139 for (i = 0; i < 10; i++) {
140 b43_phy_write(dev, 0x0015, 0xAFA0);
141 udelay(1);
142 b43_phy_write(dev, 0x0015, 0xEFA0);
143 udelay(10);
144 b43_phy_write(dev, 0x0015, 0xFFA0);
145 udelay(40);
146 ret += b43_phy_read(dev, 0x002C);
147 }
148
149 return ret;
150}
151
152void b43_lo_b_measure(struct b43_wldev *dev)
153{
154 struct b43_phy *phy = &dev->phy;
155 u16 regstack[12] = { 0 };
156 u16 mls;
157 u16 fval;
158 int i, j;
159
160 regstack[0] = b43_phy_read(dev, 0x0015);
161 regstack[1] = b43_radio_read16(dev, 0x0052) & 0xFFF0;
162
163 if (phy->radio_ver == 0x2053) {
164 regstack[2] = b43_phy_read(dev, 0x000A);
165 regstack[3] = b43_phy_read(dev, 0x002A);
166 regstack[4] = b43_phy_read(dev, 0x0035);
167 regstack[5] = b43_phy_read(dev, 0x0003);
168 regstack[6] = b43_phy_read(dev, 0x0001);
169 regstack[7] = b43_phy_read(dev, 0x0030);
170
171 regstack[8] = b43_radio_read16(dev, 0x0043);
172 regstack[9] = b43_radio_read16(dev, 0x007A);
173 regstack[10] = b43_read16(dev, 0x03EC);
174 regstack[11] = b43_radio_read16(dev, 0x0052) & 0x00F0;
175
176 b43_phy_write(dev, 0x0030, 0x00FF);
177 b43_write16(dev, 0x03EC, 0x3F3F);
178 b43_phy_write(dev, 0x0035, regstack[4] & 0xFF7F);
179 b43_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0);
180 }
181 b43_phy_write(dev, 0x0015, 0xB000);
182 b43_phy_write(dev, 0x002B, 0x0004);
183
184 if (phy->radio_ver == 0x2053) {
185 b43_phy_write(dev, 0x002B, 0x0203);
186 b43_phy_write(dev, 0x002A, 0x08A3);
187 }
188
189 phy->minlowsig[0] = 0xFFFF;
190
191 for (i = 0; i < 4; i++) {
192 b43_radio_write16(dev, 0x0052, regstack[1] | i);
193 lo_b_r15_loop(dev);
194 }
195 for (i = 0; i < 10; i++) {
196 b43_radio_write16(dev, 0x0052, regstack[1] | i);
197 mls = lo_b_r15_loop(dev) / 10;
198 if (mls < phy->minlowsig[0]) {
199 phy->minlowsig[0] = mls;
200 phy->minlowsigpos[0] = i;
201 }
202 }
203 b43_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]);
204
205 phy->minlowsig[1] = 0xFFFF;
206
207 for (i = -4; i < 5; i += 2) {
208 for (j = -4; j < 5; j += 2) {
209 if (j < 0)
210 fval = (0x0100 * i) + j + 0x0100;
211 else
212 fval = (0x0100 * i) + j;
213 b43_phy_write(dev, 0x002F, fval);
214 mls = lo_b_r15_loop(dev) / 10;
215 if (mls < phy->minlowsig[1]) {
216 phy->minlowsig[1] = mls;
217 phy->minlowsigpos[1] = fval;
218 }
219 }
220 }
221 phy->minlowsigpos[1] += 0x0101;
222
223 b43_phy_write(dev, 0x002F, phy->minlowsigpos[1]);
224 if (phy->radio_ver == 0x2053) {
225 b43_phy_write(dev, 0x000A, regstack[2]);
226 b43_phy_write(dev, 0x002A, regstack[3]);
227 b43_phy_write(dev, 0x0035, regstack[4]);
228 b43_phy_write(dev, 0x0003, regstack[5]);
229 b43_phy_write(dev, 0x0001, regstack[6]);
230 b43_phy_write(dev, 0x0030, regstack[7]);
231
232 b43_radio_write16(dev, 0x0043, regstack[8]);
233 b43_radio_write16(dev, 0x007A, regstack[9]);
234
235 b43_radio_write16(dev, 0x0052,
236 (b43_radio_read16(dev, 0x0052) & 0x000F)
237 | regstack[11]);
238
239 b43_write16(dev, 0x03EC, regstack[10]);
240 }
241 b43_phy_write(dev, 0x0015, regstack[0]);
242}
243
244static u16 lo_measure_feedthrough(struct b43_wldev *dev, 79static u16 lo_measure_feedthrough(struct b43_wldev *dev,
245 u16 lna, u16 pga, u16 trsw_rx) 80 u16 lna, u16 pga, u16 trsw_rx)
246{ 81{
@@ -438,48 +273,26 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
438 b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) 273 b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52)
439 & 0xFFF0); /* TX bias == 0 */ 274 & 0xFFF0); /* TX bias == 0 */
440 } 275 }
276 lo->txctl_measured_time = jiffies;
441} 277}
442 278
443static void lo_read_power_vector(struct b43_wldev *dev) 279static void lo_read_power_vector(struct b43_wldev *dev)
444{ 280{
445 struct b43_phy *phy = &dev->phy; 281 struct b43_phy *phy = &dev->phy;
446 struct b43_txpower_lo_control *lo = phy->lo_control; 282 struct b43_txpower_lo_control *lo = phy->lo_control;
447 u16 i; 283 int i;
448 u64 tmp; 284 u64 tmp;
449 u64 power_vector = 0; 285 u64 power_vector = 0;
450 int rf_offset, bb_offset;
451 struct b43_loctl *loctl;
452 286
453 for (i = 0; i < 8; i += 2) { 287 for (i = 0; i < 8; i += 2) {
454 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); 288 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i);
455 /* Clear the top byte. We get holes in the bitmap... */
456 tmp &= 0xFF;
457 power_vector |= (tmp << (i * 8)); 289 power_vector |= (tmp << (i * 8));
458 /* Clear the vector on the device. */ 290 /* Clear the vector on the device. */
459 b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); 291 b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0);
460 } 292 }
461
462 if (power_vector) 293 if (power_vector)
463 lo->power_vector = power_vector; 294 lo->power_vector = power_vector;
464 power_vector = lo->power_vector; 295 lo->pwr_vec_read_time = jiffies;
465
466 for (i = 0; i < 64; i++) {
467 if (power_vector & ((u64) 1ULL << i)) {
468 /* Now figure out which b43_loctl corresponds
469 * to this bit.
470 */
471 rf_offset = i / lo->rfatt_list.len;
472 bb_offset = i % lo->rfatt_list.len; //FIXME?
473 loctl =
474 b43_get_lo_g_ctl(dev,
475 &lo->rfatt_list.list[rf_offset],
476 &lo->bbatt_list.list[bb_offset]);
477 /* And mark it as "used", as the device told us
478 * through the bitmap it is using it.
479 */
480 loctl->used = 1;
481 }
482 }
483} 296}
484 297
485/* 802.11/LO/GPHY/MeasuringGains */ 298/* 802.11/LO/GPHY/MeasuringGains */
@@ -609,8 +422,6 @@ static void lo_measure_setup(struct b43_wldev *dev,
609 b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); 422 b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410);
610 b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); 423 b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820);
611 } 424 }
612 if (!lo->rebuild && b43_has_hardware_pctl(phy))
613 lo_read_power_vector(dev);
614 if (phy->rev >= 2) { 425 if (phy->rev >= 2) {
615 sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); 426 sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);
616 sav->phy_analogoverval = 427 sav->phy_analogoverval =
@@ -691,8 +502,12 @@ static void lo_measure_setup(struct b43_wldev *dev,
691 b43_radio_read16(dev, 0x51); /* dummy read */ 502 b43_radio_read16(dev, 0x51); /* dummy read */
692 if (phy->type == B43_PHYTYPE_G) 503 if (phy->type == B43_PHYTYPE_G)
693 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); 504 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0);
694 if (lo->rebuild) 505
506 /* Re-measure the txctl values, if needed. */
507 if (time_before(lo->txctl_measured_time,
508 jiffies - B43_LO_TXCTL_EXPIRE))
695 lo_measure_txctl_values(dev); 509 lo_measure_txctl_values(dev);
510
696 if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { 511 if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) {
697 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); 512 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078);
698 } else { 513 } else {
@@ -707,7 +522,6 @@ static void lo_measure_restore(struct b43_wldev *dev,
707 struct lo_g_saved_values *sav) 522 struct lo_g_saved_values *sav)
708{ 523{
709 struct b43_phy *phy = &dev->phy; 524 struct b43_phy *phy = &dev->phy;
710 struct b43_txpower_lo_control *lo = phy->lo_control;
711 u16 tmp; 525 u16 tmp;
712 526
713 if (phy->rev >= 2) { 527 if (phy->rev >= 2) {
@@ -722,14 +536,6 @@ static void lo_measure_restore(struct b43_wldev *dev,
722 tmp = (phy->pga_gain | 0xEFA0); 536 tmp = (phy->pga_gain | 0xEFA0);
723 b43_phy_write(dev, B43_PHY_PGACTL, tmp); 537 b43_phy_write(dev, B43_PHY_PGACTL, tmp);
724 } 538 }
725 if (b43_has_hardware_pctl(phy)) {
726 b43_gphy_dc_lt_init(dev);
727 } else {
728 if (lo->rebuild)
729 b43_lo_g_adjust_to(dev, 3, 2, 0);
730 else
731 b43_lo_g_adjust(dev);
732 }
733 if (phy->type == B43_PHYTYPE_G) { 539 if (phy->type == B43_PHYTYPE_G) {
734 if (phy->rev >= 3) 540 if (phy->rev >= 3)
735 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); 541 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078);
@@ -793,7 +599,6 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
793 struct b43_lo_g_statemachine *d) 599 struct b43_lo_g_statemachine *d)
794{ 600{
795 struct b43_phy *phy = &dev->phy; 601 struct b43_phy *phy = &dev->phy;
796 struct b43_txpower_lo_control *lo = phy->lo_control;
797 struct b43_loctl test_loctl; 602 struct b43_loctl test_loctl;
798 struct b43_loctl orig_loctl; 603 struct b43_loctl orig_loctl;
799 struct b43_loctl prev_loctl = { 604 struct b43_loctl prev_loctl = {
@@ -852,7 +657,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
852 found_lower = 1; 657 found_lower = 1;
853 d->lowest_feedth = feedth; 658 d->lowest_feedth = feedth;
854 if ((d->nr_measured < 2) && 659 if ((d->nr_measured < 2) &&
855 (!has_loopback_gain(phy) || lo->rebuild)) 660 !has_loopback_gain(phy))
856 break; 661 break;
857 } 662 }
858 } 663 }
@@ -874,7 +679,6 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
874 int *max_rx_gain) 679 int *max_rx_gain)
875{ 680{
876 struct b43_phy *phy = &dev->phy; 681 struct b43_phy *phy = &dev->phy;
877 struct b43_txpower_lo_control *lo = phy->lo_control;
878 struct b43_lo_g_statemachine d; 682 struct b43_lo_g_statemachine d;
879 u16 feedth; 683 u16 feedth;
880 int found_lower; 684 int found_lower;
@@ -883,18 +687,18 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
883 687
884 d.nr_measured = 0; 688 d.nr_measured = 0;
885 d.state_val_multiplier = 1; 689 d.state_val_multiplier = 1;
886 if (has_loopback_gain(phy) && !lo->rebuild) 690 if (has_loopback_gain(phy))
887 d.state_val_multiplier = 3; 691 d.state_val_multiplier = 3;
888 692
889 memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); 693 memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl));
890 if (has_loopback_gain(phy) && lo->rebuild) 694 if (has_loopback_gain(phy))
891 max_repeat = 4; 695 max_repeat = 4;
892 do { 696 do {
893 b43_lo_write(dev, &d.min_loctl); 697 b43_lo_write(dev, &d.min_loctl);
894 feedth = lo_measure_feedthrough(dev, phy->lna_gain, 698 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
895 phy->pga_gain, 699 phy->pga_gain,
896 phy->trsw_rx_gain); 700 phy->trsw_rx_gain);
897 if (!lo->rebuild && feedth < 0x258) { 701 if (feedth < 0x258) {
898 if (feedth >= 0x12C) 702 if (feedth >= 0x12C)
899 *max_rx_gain += 6; 703 *max_rx_gain += 6;
900 else 704 else
@@ -944,278 +748,188 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
944 } while (++repeat_cnt < max_repeat); 748 } while (++repeat_cnt < max_repeat);
945} 749}
946 750
947#if B43_CALIB_ALL_LOCTLS 751static
948static const struct b43_rfatt b43_full_rfatt_list_items[] = { 752struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
949 { .att = 0, .with_padmix = 0, }, 753 const struct b43_bbatt *bbatt,
950 { .att = 1, .with_padmix = 0, }, 754 const struct b43_rfatt *rfatt)
951 { .att = 2, .with_padmix = 0, },
952 { .att = 3, .with_padmix = 0, },
953 { .att = 4, .with_padmix = 0, },
954 { .att = 5, .with_padmix = 0, },
955 { .att = 6, .with_padmix = 0, },
956 { .att = 7, .with_padmix = 0, },
957 { .att = 8, .with_padmix = 0, },
958 { .att = 9, .with_padmix = 0, },
959 { .att = 10, .with_padmix = 0, },
960 { .att = 11, .with_padmix = 0, },
961 { .att = 12, .with_padmix = 0, },
962 { .att = 13, .with_padmix = 0, },
963 { .att = 14, .with_padmix = 0, },
964 { .att = 15, .with_padmix = 0, },
965 { .att = 0, .with_padmix = 1, },
966 { .att = 1, .with_padmix = 1, },
967 { .att = 2, .with_padmix = 1, },
968 { .att = 3, .with_padmix = 1, },
969 { .att = 4, .with_padmix = 1, },
970 { .att = 5, .with_padmix = 1, },
971 { .att = 6, .with_padmix = 1, },
972 { .att = 7, .with_padmix = 1, },
973 { .att = 8, .with_padmix = 1, },
974 { .att = 9, .with_padmix = 1, },
975 { .att = 10, .with_padmix = 1, },
976 { .att = 11, .with_padmix = 1, },
977 { .att = 12, .with_padmix = 1, },
978 { .att = 13, .with_padmix = 1, },
979 { .att = 14, .with_padmix = 1, },
980 { .att = 15, .with_padmix = 1, },
981};
982static const struct b43_rfatt_list b43_full_rfatt_list = {
983 .list = b43_full_rfatt_list_items,
984 .len = ARRAY_SIZE(b43_full_rfatt_list_items),
985};
986
987static const struct b43_bbatt b43_full_bbatt_list_items[] = {
988 { .att = 0, },
989 { .att = 1, },
990 { .att = 2, },
991 { .att = 3, },
992 { .att = 4, },
993 { .att = 5, },
994 { .att = 6, },
995 { .att = 7, },
996 { .att = 8, },
997 { .att = 9, },
998 { .att = 10, },
999 { .att = 11, },
1000};
1001static const struct b43_bbatt_list b43_full_bbatt_list = {
1002 .list = b43_full_bbatt_list_items,
1003 .len = ARRAY_SIZE(b43_full_bbatt_list_items),
1004};
1005#endif /* B43_CALIB_ALL_LOCTLS */
1006
1007static void lo_measure(struct b43_wldev *dev)
1008{ 755{
1009 struct b43_phy *phy = &dev->phy; 756 struct b43_phy *phy = &dev->phy;
1010 struct b43_txpower_lo_control *lo = phy->lo_control;
1011 struct b43_loctl loctl = { 757 struct b43_loctl loctl = {
1012 .i = 0, 758 .i = 0,
1013 .q = 0, 759 .q = 0,
1014 }; 760 };
1015 struct b43_loctl *ploctl;
1016 int max_rx_gain; 761 int max_rx_gain;
1017 int rfidx, bbidx; 762 struct b43_lo_calib *cal;
1018 const struct b43_bbatt_list *bbatt_list; 763 struct lo_g_saved_values uninitialized_var(saved_regs);
1019 const struct b43_rfatt_list *rfatt_list;
1020
1021 /* Values from the "TXCTL Register and Value Table" */ 764 /* Values from the "TXCTL Register and Value Table" */
1022 u16 txctl_reg; 765 u16 txctl_reg;
1023 u16 txctl_value; 766 u16 txctl_value;
1024 u16 pad_mix_gain; 767 u16 pad_mix_gain;
1025 768
1026 bbatt_list = &lo->bbatt_list; 769 saved_regs.old_channel = phy->channel;
1027 rfatt_list = &lo->rfatt_list; 770 b43_mac_suspend(dev);
1028#if B43_CALIB_ALL_LOCTLS 771 lo_measure_setup(dev, &saved_regs);
1029 bbatt_list = &b43_full_bbatt_list;
1030 rfatt_list = &b43_full_rfatt_list;
1031#endif
1032 772
1033 txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); 773 txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain);
1034 774
1035 for (rfidx = 0; rfidx < rfatt_list->len; rfidx++) { 775 b43_radio_write16(dev, 0x43,
1036 776 (b43_radio_read16(dev, 0x43) & 0xFFF0)
1037 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) 777 | rfatt->att);
1038 & 0xFFF0) | 778 b43_radio_write16(dev, txctl_reg,
1039 rfatt_list->list[rfidx].att); 779 (b43_radio_read16(dev, txctl_reg) & ~txctl_value)
1040 b43_radio_write16(dev, txctl_reg, 780 | (rfatt->with_padmix) ? txctl_value : 0);
1041 (b43_radio_read16(dev, txctl_reg)
1042 & ~txctl_value)
1043 | (rfatt_list->list[rfidx].with_padmix ?
1044 txctl_value : 0));
1045
1046 for (bbidx = 0; bbidx < bbatt_list->len; bbidx++) {
1047 if (lo->rebuild) {
1048#if B43_CALIB_ALL_LOCTLS
1049 ploctl = b43_get_lo_g_ctl(dev,
1050 &rfatt_list->list[rfidx],
1051 &bbatt_list->list[bbidx]);
1052#else
1053 ploctl = b43_get_lo_g_ctl_nopadmix(dev,
1054 &rfatt_list->
1055 list[rfidx],
1056 &bbatt_list->
1057 list[bbidx]);
1058#endif
1059 } else {
1060 ploctl = b43_get_lo_g_ctl(dev,
1061 &rfatt_list->list[rfidx],
1062 &bbatt_list->list[bbidx]);
1063 if (!ploctl->used)
1064 continue;
1065 }
1066 memcpy(&loctl, ploctl, sizeof(loctl));
1067 loctl.i = 0;
1068 loctl.q = 0;
1069
1070 max_rx_gain = rfatt_list->list[rfidx].att * 2;
1071 max_rx_gain += bbatt_list->list[bbidx].att / 2;
1072 if (rfatt_list->list[rfidx].with_padmix)
1073 max_rx_gain -= pad_mix_gain;
1074 if (has_loopback_gain(phy))
1075 max_rx_gain += phy->max_lb_gain;
1076 lo_measure_gain_values(dev, max_rx_gain,
1077 has_loopback_gain(phy));
1078
1079 b43_phy_set_baseband_attenuation(dev,
1080 bbatt_list->list[bbidx].att);
1081 lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
1082 if (phy->type == B43_PHYTYPE_B) {
1083 loctl.i++;
1084 loctl.q++;
1085 }
1086 b43_loctl_set_calibrated(&loctl, 1);
1087 memcpy(ploctl, &loctl, sizeof(loctl));
1088 }
1089 }
1090}
1091
1092#if B43_DEBUG
1093static void do_validate_loctl(struct b43_wldev *dev, struct b43_loctl *control)
1094{
1095 const int is_initializing = (b43_status(dev) == B43_STAT_UNINIT);
1096 int i = control->i;
1097 int q = control->q;
1098 781
1099 if (b43_loctl_is_calibrated(control)) { 782 max_rx_gain = rfatt->att * 2;
1100 if ((abs(i) > 16) || (abs(q) > 16)) 783 max_rx_gain += bbatt->att / 2;
1101 goto error; 784 if (rfatt->with_padmix)
1102 } else { 785 max_rx_gain -= pad_mix_gain;
1103 if (control->used) 786 if (has_loopback_gain(phy))
1104 goto error; 787 max_rx_gain += phy->max_lb_gain;
1105 if (dev->phy.lo_control->rebuild) { 788 lo_measure_gain_values(dev, max_rx_gain,
1106 control->i = 0; 789 has_loopback_gain(phy));
1107 control->q = 0; 790
1108 if ((i != B43_LOCTL_POISON) || 791 b43_phy_set_baseband_attenuation(dev, bbatt->att);
1109 (q != B43_LOCTL_POISON)) 792 lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
1110 goto error; 793
1111 } 794 lo_measure_restore(dev, &saved_regs);
795 b43_mac_enable(dev);
796
797 if (b43_debug(dev, B43_DBG_LO)) {
798 b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) "
799 "=> I=%d Q=%d\n",
800 bbatt->att, rfatt->att, rfatt->with_padmix,
801 loctl.i, loctl.q);
1112 } 802 }
1113 if (is_initializing && control->used)
1114 goto error;
1115
1116 return;
1117error:
1118 b43err(dev->wl, "LO control pair validation failed "
1119 "(I: %d, Q: %d, used %u, calib: %u, initing: %d)\n",
1120 i, q, control->used,
1121 b43_loctl_is_calibrated(control),
1122 is_initializing);
1123}
1124 803
1125static void validate_all_loctls(struct b43_wldev *dev) 804 cal = kmalloc(sizeof(*cal), GFP_KERNEL);
1126{ 805 if (!cal) {
1127 b43_call_for_each_loctl(dev, do_validate_loctl); 806 b43warn(dev->wl, "LO calib: out of memory\n");
1128} 807 return NULL;
1129
1130static void do_reset_calib(struct b43_wldev *dev, struct b43_loctl *control)
1131{
1132 if (dev->phy.lo_control->rebuild ||
1133 control->used) {
1134 b43_loctl_set_calibrated(control, 0);
1135 control->i = B43_LOCTL_POISON;
1136 control->q = B43_LOCTL_POISON;
1137 } 808 }
809 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
810 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
811 memcpy(&cal->ctl, &loctl, sizeof(loctl));
812 cal->calib_time = jiffies;
813 INIT_LIST_HEAD(&cal->list);
814
815 return cal;
1138} 816}
1139 817
1140static void reset_all_loctl_calibration_states(struct b43_wldev *dev) 818/* Get a calibrated LO setting for the given attenuation values.
819 * Might return a NULL pointer under OOM! */
820static
821struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
822 const struct b43_bbatt *bbatt,
823 const struct b43_rfatt *rfatt)
1141{ 824{
1142 b43_call_for_each_loctl(dev, do_reset_calib); 825 struct b43_txpower_lo_control *lo = dev->phy.lo_control;
826 struct b43_lo_calib *c;
827
828 c = b43_find_lo_calib(lo, bbatt, rfatt);
829 if (c)
830 return c;
831 /* Not in the list of calibrated LO settings.
832 * Calibrate it now. */
833 c = b43_calibrate_lo_setting(dev, bbatt, rfatt);
834 if (!c)
835 return NULL;
836 list_add(&c->list, &lo->calib_list);
837
838 return c;
1143} 839}
1144 840
1145#else /* B43_DEBUG */ 841void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
1146static inline void validate_all_loctls(struct b43_wldev *dev) { }
1147static inline void reset_all_loctl_calibration_states(struct b43_wldev *dev) { }
1148#endif /* B43_DEBUG */
1149
1150void b43_lo_g_measure(struct b43_wldev *dev)
1151{ 842{
1152 struct b43_phy *phy = &dev->phy; 843 struct b43_phy *phy = &dev->phy;
1153 struct lo_g_saved_values uninitialized_var(sav); 844 struct b43_txpower_lo_control *lo = phy->lo_control;
1154 845 int i;
1155 B43_WARN_ON((phy->type != B43_PHYTYPE_B) && 846 int rf_offset, bb_offset;
1156 (phy->type != B43_PHYTYPE_G)); 847 const struct b43_rfatt *rfatt;
1157 848 const struct b43_bbatt *bbatt;
1158 sav.old_channel = phy->channel; 849 u64 power_vector;
1159 lo_measure_setup(dev, &sav); 850 bool table_changed = 0;
1160 reset_all_loctl_calibration_states(dev);
1161 lo_measure(dev);
1162 lo_measure_restore(dev, &sav);
1163
1164 validate_all_loctls(dev);
1165 851
1166 phy->lo_control->lo_measured = 1; 852 BUILD_BUG_ON(B43_DC_LT_SIZE != 32);
1167 phy->lo_control->rebuild = 0; 853 B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64);
1168}
1169 854
1170#if B43_DEBUG 855 power_vector = lo->power_vector;
1171static void validate_loctl_calibration(struct b43_wldev *dev, 856 if (!update_all && !power_vector)
1172 struct b43_loctl *loctl, 857 return; /* Nothing to do. */
1173 struct b43_rfatt *rfatt, 858
1174 struct b43_bbatt *bbatt) 859 /* Suspend the MAC now to avoid continuous suspend/enable
1175{ 860 * cycles in the loop. */
1176 if (b43_loctl_is_calibrated(loctl)) 861 b43_mac_suspend(dev);
1177 return; 862
1178 if (!dev->phy.lo_control->lo_measured) { 863 for (i = 0; i < B43_DC_LT_SIZE * 2; i++) {
1179 /* On init we set the attenuation values before we 864 struct b43_lo_calib *cal;
1180 * calibrated the LO. I guess that's OK. */ 865 int idx;
1181 return; 866 u16 val;
867
868 if (!update_all && !(power_vector & (((u64)1ULL) << i)))
869 continue;
870 /* Update the table entry for this power_vector bit.
871 * The table rows are RFatt entries and columns are BBatt. */
872 bb_offset = i / lo->rfatt_list.len;
873 rf_offset = i % lo->rfatt_list.len;
874 bbatt = &(lo->bbatt_list.list[bb_offset]);
875 rfatt = &(lo->rfatt_list.list[rf_offset]);
876
877 cal = b43_calibrate_lo_setting(dev, bbatt, rfatt);
878 if (!cal) {
879 b43warn(dev->wl, "LO: Could not "
880 "calibrate DC table entry\n");
881 continue;
882 }
883 /*FIXME: Is Q really in the low nibble? */
884 val = (u8)(cal->ctl.q);
885 val |= ((u8)(cal->ctl.i)) << 4;
886 kfree(cal);
887
888 /* Get the index into the hardware DC LT. */
889 idx = i / 2;
890 /* Change the table in memory. */
891 if (i % 2) {
892 /* Change the high byte. */
893 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF)
894 | ((val & 0x00FF) << 8);
895 } else {
896 /* Change the low byte. */
897 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00)
898 | (val & 0x00FF);
899 }
900 table_changed = 1;
1182 } 901 }
1183 b43err(dev->wl, "Adjusting Local Oscillator to an uncalibrated " 902 if (table_changed) {
1184 "control pair: rfatt=%u,%spadmix bbatt=%u\n", 903 /* The table changed in memory. Update the hardware table. */
1185 rfatt->att, 904 for (i = 0; i < B43_DC_LT_SIZE; i++)
1186 (rfatt->with_padmix) ? "" : "no-", 905 b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]);
1187 bbatt->att); 906 }
1188} 907 b43_mac_enable(dev);
1189#else
1190static inline void validate_loctl_calibration(struct b43_wldev *dev,
1191 struct b43_loctl *loctl,
1192 struct b43_rfatt *rfatt,
1193 struct b43_bbatt *bbatt)
1194{
1195} 908}
1196#endif
1197 909
1198static inline void fixup_rfatt_for_txcontrol(struct b43_rfatt *rf, 910/* Fixup the RF attenuation value for the case where we are
1199 u8 tx_control) 911 * using the PAD mixer. */
912static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf)
1200{ 913{
1201 if (tx_control & B43_TXCTL_TXMIX) { 914 if (!rf->with_padmix)
1202 if (rf->att < 5) 915 return;
1203 rf->att = 4; 916 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
1204 } 917 rf->att = 4;
1205} 918}
1206 919
1207void b43_lo_g_adjust(struct b43_wldev *dev) 920void b43_lo_g_adjust(struct b43_wldev *dev)
1208{ 921{
1209 struct b43_phy *phy = &dev->phy; 922 struct b43_phy *phy = &dev->phy;
923 struct b43_lo_calib *cal;
1210 struct b43_rfatt rf; 924 struct b43_rfatt rf;
1211 struct b43_loctl *loctl;
1212 925
1213 memcpy(&rf, &phy->rfatt, sizeof(rf)); 926 memcpy(&rf, &phy->rfatt, sizeof(rf));
1214 fixup_rfatt_for_txcontrol(&rf, phy->tx_control); 927 b43_lo_fixup_rfatt(&rf);
1215 928
1216 loctl = b43_get_lo_g_ctl(dev, &rf, &phy->bbatt); 929 cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf);
1217 validate_loctl_calibration(dev, loctl, &rf, &phy->bbatt); 930 if (!cal)
1218 b43_lo_write(dev, loctl); 931 return;
932 b43_lo_write(dev, &cal->ctl);
1219} 933}
1220 934
1221void b43_lo_g_adjust_to(struct b43_wldev *dev, 935void b43_lo_g_adjust_to(struct b43_wldev *dev,
@@ -1223,39 +937,102 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev,
1223{ 937{
1224 struct b43_rfatt rf; 938 struct b43_rfatt rf;
1225 struct b43_bbatt bb; 939 struct b43_bbatt bb;
1226 struct b43_loctl *loctl; 940 struct b43_lo_calib *cal;
1227 941
1228 memset(&rf, 0, sizeof(rf)); 942 memset(&rf, 0, sizeof(rf));
1229 memset(&bb, 0, sizeof(bb)); 943 memset(&bb, 0, sizeof(bb));
1230 rf.att = rfatt; 944 rf.att = rfatt;
1231 bb.att = bbatt; 945 bb.att = bbatt;
1232 fixup_rfatt_for_txcontrol(&rf, tx_control); 946 b43_lo_fixup_rfatt(&rf);
1233 loctl = b43_get_lo_g_ctl(dev, &rf, &bb); 947 cal = b43_get_calib_lo_settings(dev, &bb, &rf);
1234 validate_loctl_calibration(dev, loctl, &rf, &bb); 948 if (!cal)
1235 b43_lo_write(dev, loctl); 949 return;
950 b43_lo_write(dev, &cal->ctl);
1236} 951}
1237 952
1238static void do_mark_unused(struct b43_wldev *dev, struct b43_loctl *control) 953/* Periodic LO maintanance work */
954void b43_lo_g_maintanance_work(struct b43_wldev *dev)
1239{ 955{
1240 control->used = 0; 956 struct b43_phy *phy = &dev->phy;
957 struct b43_txpower_lo_control *lo = phy->lo_control;
958 unsigned long now;
959 unsigned long expire;
960 struct b43_lo_calib *cal, *tmp;
961 bool current_item_expired = 0;
962 bool hwpctl;
963
964 if (!lo)
965 return;
966 now = jiffies;
967 hwpctl = b43_has_hardware_pctl(phy);
968
969 if (hwpctl) {
970 /* Read the power vector and update it, if needed. */
971 expire = now - B43_LO_PWRVEC_EXPIRE;
972 if (time_before(lo->pwr_vec_read_time, expire)) {
973 lo_read_power_vector(dev);
974 b43_gphy_dc_lt_init(dev, 0);
975 }
976 //FIXME Recalc the whole DC table from time to time?
977 }
978
979 if (hwpctl)
980 return;
981 /* Search for expired LO settings. Remove them.
982 * Recalibrate the current setting, if expired. */
983 expire = now - B43_LO_CALIB_EXPIRE;
984 list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) {
985 if (!time_before(cal->calib_time, expire))
986 continue;
987 /* This item expired. */
988 if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
989 b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) {
990 B43_WARN_ON(current_item_expired);
991 current_item_expired = 1;
992 }
993 if (b43_debug(dev, B43_DBG_LO)) {
994 b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), "
995 "I=%d, Q=%d expired\n",
996 cal->bbatt.att, cal->rfatt.att,
997 cal->rfatt.with_padmix,
998 cal->ctl.i, cal->ctl.q);
999 }
1000 list_del(&cal->list);
1001 kfree(cal);
1002 }
1003 if (current_item_expired || unlikely(list_empty(&lo->calib_list))) {
1004 /* Recalibrate currently used LO setting. */
1005 if (b43_debug(dev, B43_DBG_LO))
1006 b43dbg(dev->wl, "LO: Recalibrating current LO setting\n");
1007 cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt);
1008 if (cal) {
1009 list_add(&cal->list, &lo->calib_list);
1010 b43_lo_write(dev, &cal->ctl);
1011 } else
1012 b43warn(dev->wl, "Failed to recalibrate current LO setting\n");
1013 }
1241} 1014}
1242 1015
1243void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev) 1016void b43_lo_g_cleanup(struct b43_wldev *dev)
1244{ 1017{
1245 struct b43_phy *phy = &dev->phy; 1018 struct b43_txpower_lo_control *lo = dev->phy.lo_control;
1246 struct b43_txpower_lo_control *lo = phy->lo_control; 1019 struct b43_lo_calib *cal, *tmp;
1247 1020
1248 b43_call_for_each_loctl(dev, do_mark_unused); 1021 if (!lo)
1249 lo->rebuild = 1; 1022 return;
1023 list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) {
1024 list_del(&cal->list);
1025 kfree(cal);
1026 }
1250} 1027}
1251 1028
1252void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev) 1029/* LO Initialization */
1030void b43_lo_g_init(struct b43_wldev *dev)
1253{ 1031{
1254 struct b43_phy *phy = &dev->phy; 1032 struct b43_phy *phy = &dev->phy;
1255 struct b43_rfatt rf;
1256 1033
1257 memcpy(&rf, &phy->rfatt, sizeof(rf)); 1034 if (b43_has_hardware_pctl(phy)) {
1258 fixup_rfatt_for_txcontrol(&rf, phy->tx_control); 1035 lo_read_power_vector(dev);
1259 1036 b43_gphy_dc_lt_init(dev, 1);
1260 b43_get_lo_g_ctl(dev, &rf, &phy->bbatt)->used = 1; 1037 }
1261} 1038}
diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h
index 455615d1f8c6..1da321cabc12 100644
--- a/drivers/net/wireless/b43/lo.h
+++ b/drivers/net/wireless/b43/lo.h
@@ -10,82 +10,63 @@ struct b43_loctl {
10 /* Control values. */ 10 /* Control values. */
11 s8 i; 11 s8 i;
12 s8 q; 12 s8 q;
13 /* "Used by hardware" flag. */
14 bool used;
15#ifdef CONFIG_B43_DEBUG
16 /* Is this lo-control-array entry calibrated? */
17 bool calibrated;
18#endif
19}; 13};
20
21/* Debugging: Poison value for i and q values. */ 14/* Debugging: Poison value for i and q values. */
22#define B43_LOCTL_POISON 111 15#define B43_LOCTL_POISON 111
23 16
24/* loctl->calibrated debugging mechanism */ 17/* This struct holds calibrated LO settings for a set of
25#ifdef CONFIG_B43_DEBUG 18 * Baseband and RF attenuation settings. */
26static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, 19struct b43_lo_calib {
27 bool calibrated) 20 /* The set of attenuation values this set of LO
28{ 21 * control values is calibrated for. */
29 loctl->calibrated = calibrated; 22 struct b43_bbatt bbatt;
30} 23 struct b43_rfatt rfatt;
31static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) 24 /* The set of control values for the LO. */
32{ 25 struct b43_loctl ctl;
33 return loctl->calibrated; 26 /* The time when these settings were calibrated (in jiffies) */
34} 27 unsigned long calib_time;
35#else 28 /* List. */
36static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, 29 struct list_head list;
37 bool calibrated) 30};
38{ 31
39} 32/* Size of the DC Lookup Table in 16bit words. */
40static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) 33#define B43_DC_LT_SIZE 32
41{ 34
42 return 1; 35/* Local Oscillator calibration information */
43}
44#endif
45
46/* TX Power LO Control Array.
47 * Value-pairs to adjust the LocalOscillator are stored
48 * in this structure.
49 * There are two different set of values. One for "Flag is Set"
50 * and one for "Flag is Unset".
51 * By "Flag" the flag in struct b43_rfatt is meant.
52 * The Value arrays are two-dimensional. The first index
53 * is the baseband attenuation and the second index
54 * is the radio attenuation.
55 * Use b43_get_lo_g_ctl() to retrieve a value from the lists.
56 */
57struct b43_txpower_lo_control { 36struct b43_txpower_lo_control {
58#define B43_NR_BB 12 37 /* Lists of RF and BB attenuation values for this device.
59#define B43_NR_RF 16 38 * Used for building hardware power control tables. */
60 /* LO Control values, with PAD Mixer */
61 struct b43_loctl with_padmix[B43_NR_BB][B43_NR_RF];
62 /* LO Control values, without PAD Mixer */
63 struct b43_loctl no_padmix[B43_NR_BB][B43_NR_RF];
64
65 /* Flag to indicate a complete rebuild of the two tables above
66 * to the LO measuring code. */
67 bool rebuild;
68
69 /* Lists of valid RF and BB attenuation values for this device. */
70 struct b43_rfatt_list rfatt_list; 39 struct b43_rfatt_list rfatt_list;
71 struct b43_bbatt_list bbatt_list; 40 struct b43_bbatt_list bbatt_list;
72 41
42 /* The DC Lookup Table is cached in memory here.
43 * Note that this is only used for Hardware Power Control. */
44 u16 dc_lt[B43_DC_LT_SIZE];
45
46 /* List of calibrated control values (struct b43_lo_calib). */
47 struct list_head calib_list;
48 /* Last time the power vector was read (jiffies). */
49 unsigned long pwr_vec_read_time;
50 /* Last time the txctl values were measured (jiffies). */
51 unsigned long txctl_measured_time;
52
73 /* Current TX Bias value */ 53 /* Current TX Bias value */
74 u8 tx_bias; 54 u8 tx_bias;
75 /* Current TX Magnification Value (if used by the device) */ 55 /* Current TX Magnification Value (if used by the device) */
76 u8 tx_magn; 56 u8 tx_magn;
77 57
78 /* GPHY LO is measured. */
79 bool lo_measured;
80
81 /* Saved device PowerVector */ 58 /* Saved device PowerVector */
82 u64 power_vector; 59 u64 power_vector;
83}; 60};
84 61
85/* Measure the BPHY Local Oscillator. */ 62/* Calibration expire timeouts.
86void b43_lo_b_measure(struct b43_wldev *dev); 63 * Timeouts must be multiple of 15 seconds. To make sure
87/* Measure the BPHY/GPHY Local Oscillator. */ 64 * the item really expired when the 15 second timer hits, we
88void b43_lo_g_measure(struct b43_wldev *dev); 65 * subtract two additional seconds from the timeout. */
66#define B43_LO_CALIB_EXPIRE (HZ * (30 - 2))
67#define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2))
68#define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4))
69
89 70
90/* Adjust the Local Oscillator to the saved attenuation 71/* Adjust the Local Oscillator to the saved attenuation
91 * and txctl values. 72 * and txctl values.
@@ -95,18 +76,10 @@ void b43_lo_g_adjust(struct b43_wldev *dev);
95void b43_lo_g_adjust_to(struct b43_wldev *dev, 76void b43_lo_g_adjust_to(struct b43_wldev *dev,
96 u16 rfatt, u16 bbatt, u16 tx_control); 77 u16 rfatt, u16 bbatt, u16 tx_control);
97 78
98/* Mark all possible b43_lo_g_ctl as "unused" */ 79void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all);
99void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev);
100/* Mark the b43_lo_g_ctl corresponding to the current
101 * attenuation values as used.
102 */
103void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev);
104 80
105/* Get a reference to a LO Control value pair in the 81void b43_lo_g_maintanance_work(struct b43_wldev *dev);
106 * TX Power LO Control Array. 82void b43_lo_g_cleanup(struct b43_wldev *dev);
107 */ 83void b43_lo_g_init(struct b43_wldev *dev);
108struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev,
109 const struct b43_rfatt *rfatt,
110 const struct b43_bbatt *bbatt);
111 84
112#endif /* B43_LO_H_ */ 85#endif /* B43_LO_H_ */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 8fdba9415c04..e3d8555d4a99 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2308,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
2308} 2308}
2309 2309
2310/* http://bcm-specs.sipsolutions.net/EnableMac */ 2310/* http://bcm-specs.sipsolutions.net/EnableMac */
2311static void b43_mac_enable(struct b43_wldev *dev) 2311void b43_mac_enable(struct b43_wldev *dev)
2312{ 2312{
2313 dev->mac_suspended--; 2313 dev->mac_suspended--;
2314 B43_WARN_ON(dev->mac_suspended < 0); 2314 B43_WARN_ON(dev->mac_suspended < 0);
@@ -2331,7 +2331,7 @@ static void b43_mac_enable(struct b43_wldev *dev)
2331} 2331}
2332 2332
2333/* http://bcm-specs.sipsolutions.net/SuspendMAC */ 2333/* http://bcm-specs.sipsolutions.net/SuspendMAC */
2334static void b43_mac_suspend(struct b43_wldev *dev) 2334void b43_mac_suspend(struct b43_wldev *dev)
2335{ 2335{
2336 int i; 2336 int i;
2337 u32 tmp; 2337 u32 tmp;
@@ -2503,6 +2503,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
2503{ 2503{
2504 b43_radio_turn_off(dev, 1); 2504 b43_radio_turn_off(dev, 1);
2505 b43_gpio_cleanup(dev); 2505 b43_gpio_cleanup(dev);
2506 b43_lo_g_cleanup(dev);
2506 /* firmware is released later */ 2507 /* firmware is released later */
2507} 2508}
2508 2509
@@ -2609,28 +2610,12 @@ err_gpio_clean:
2609 return err; 2610 return err;
2610} 2611}
2611 2612
2612static void b43_periodic_every120sec(struct b43_wldev *dev)
2613{
2614 struct b43_phy *phy = &dev->phy;
2615
2616 if (phy->type != B43_PHYTYPE_G || phy->rev < 2)
2617 return;
2618
2619 b43_mac_suspend(dev);
2620 b43_lo_g_measure(dev);
2621 b43_mac_enable(dev);
2622 if (b43_has_hardware_pctl(phy))
2623 b43_lo_g_ctl_mark_all_unused(dev);
2624}
2625
2626static void b43_periodic_every60sec(struct b43_wldev *dev) 2613static void b43_periodic_every60sec(struct b43_wldev *dev)
2627{ 2614{
2628 struct b43_phy *phy = &dev->phy; 2615 struct b43_phy *phy = &dev->phy;
2629 2616
2630 if (phy->type != B43_PHYTYPE_G) 2617 if (phy->type != B43_PHYTYPE_G)
2631 return; 2618 return;
2632 if (!b43_has_hardware_pctl(phy))
2633 b43_lo_g_ctl_mark_all_unused(dev);
2634 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { 2619 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
2635 b43_mac_suspend(dev); 2620 b43_mac_suspend(dev);
2636 b43_calc_nrssi_slope(dev); 2621 b43_calc_nrssi_slope(dev);
@@ -2682,6 +2667,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
2682 } 2667 }
2683 } 2668 }
2684 b43_phy_xmitpower(dev); //FIXME: unless scanning? 2669 b43_phy_xmitpower(dev); //FIXME: unless scanning?
2670 b43_lo_g_maintanance_work(dev);
2685 //TODO for APHY (temperature?) 2671 //TODO for APHY (temperature?)
2686 2672
2687 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); 2673 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
@@ -2693,8 +2679,6 @@ static void do_periodic_work(struct b43_wldev *dev)
2693 unsigned int state; 2679 unsigned int state;
2694 2680
2695 state = dev->periodic_state; 2681 state = dev->periodic_state;
2696 if (state % 8 == 0)
2697 b43_periodic_every120sec(dev);
2698 if (state % 4 == 0) 2682 if (state % 4 == 0)
2699 b43_periodic_every60sec(dev); 2683 b43_periodic_every60sec(dev);
2700 if (state % 2 == 0) 2684 if (state % 2 == 0)
@@ -3668,8 +3652,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
3668 lo = phy->lo_control; 3652 lo = phy->lo_control;
3669 if (lo) { 3653 if (lo) {
3670 memset(lo, 0, sizeof(*(phy->lo_control))); 3654 memset(lo, 0, sizeof(*(phy->lo_control)));
3671 lo->rebuild = 1;
3672 lo->tx_bias = 0xFF; 3655 lo->tx_bias = 0xFF;
3656 INIT_LIST_HEAD(&lo->calib_list);
3673 } 3657 }
3674 phy->max_lb_gain = 0; 3658 phy->max_lb_gain = 0;
3675 phy->trsw_rx_gain = 0; 3659 phy->trsw_rx_gain = 0;
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 5230aeca78bf..dad23c42b422 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -114,4 +114,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason);
114#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ 114#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */
115void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); 115void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
116 116
117void b43_mac_suspend(struct b43_wldev *dev);
118void b43_mac_enable(struct b43_wldev *dev);
119
117#endif /* B43_MAIN_H_ */ 120#endif /* B43_MAIN_H_ */
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index de024dc03718..fd1f301748c2 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -145,8 +145,7 @@ static void generate_rfatt_list(struct b43_wldev *dev,
145 {.att = 9,.with_padmix = 1,}, 145 {.att = 9,.with_padmix = 1,},
146 }; 146 };
147 147
148 if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) || 148 if (!b43_has_hardware_pctl(phy)) {
149 (phy->type == B43_PHYTYPE_G && phy->rev < 6)) {
150 /* Software pctl */ 149 /* Software pctl */
151 list->list = rfatt_0; 150 list->list = rfatt_0;
152 list->len = ARRAY_SIZE(rfatt_0); 151 list->len = ARRAY_SIZE(rfatt_0);
@@ -158,7 +157,7 @@ static void generate_rfatt_list(struct b43_wldev *dev,
158 /* Hardware pctl */ 157 /* Hardware pctl */
159 list->list = rfatt_1; 158 list->list = rfatt_1;
160 list->len = ARRAY_SIZE(rfatt_1); 159 list->len = ARRAY_SIZE(rfatt_1);
161 list->min_val = 2; 160 list->min_val = 0;
162 list->max_val = 14; 161 list->max_val = 14;
163 return; 162 return;
164 } 163 }
@@ -346,6 +345,7 @@ void b43_set_txpower_g(struct b43_wldev *dev,
346 /* Save the values for later */ 345 /* Save the values for later */
347 phy->tx_control = tx_control; 346 phy->tx_control = tx_control;
348 memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); 347 memcpy(&phy->rfatt, rfatt, sizeof(*rfatt));
348 phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);
349 memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); 349 memcpy(&phy->bbatt, bbatt, sizeof(*bbatt));
350 350
351 if (b43_debug(dev, B43_DBG_XMITPOWER)) { 351 if (b43_debug(dev, B43_DBG_XMITPOWER)) {
@@ -559,11 +559,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
559 u16 tmp; 559 u16 tmp;
560 u8 rf, bb; 560 u8 rf, bb;
561 561
562 if (!lo->lo_measured) {
563 b43_phy_write(dev, 0x3FF, 0);
564 return;
565 }
566
567 for (rf = 0; rf < lo->rfatt_list.len; rf++) { 562 for (rf = 0; rf < lo->rfatt_list.len; rf++) {
568 for (bb = 0; bb < lo->bbatt_list.len; bb++) { 563 for (bb = 0; bb < lo->bbatt_list.len; bb++) {
569 if (nr_written >= 0x40) 564 if (nr_written >= 0x40)
@@ -581,42 +576,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
581 } 576 }
582} 577}
583 578
584/* GPHY_DC_Lookup_Table */
585void b43_gphy_dc_lt_init(struct b43_wldev *dev)
586{
587 struct b43_phy *phy = &dev->phy;
588 struct b43_txpower_lo_control *lo = phy->lo_control;
589 struct b43_loctl *loctl0;
590 struct b43_loctl *loctl1;
591 int i;
592 int rf_offset, bb_offset;
593 u16 tmp;
594
595 for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) {
596 rf_offset = i / lo->rfatt_list.len;
597 bb_offset = i % lo->rfatt_list.len;
598
599 loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
600 &lo->bbatt_list.list[bb_offset]);
601 if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) {
602 rf_offset = (i + 1) / lo->rfatt_list.len;
603 bb_offset = (i + 1) % lo->rfatt_list.len;
604
605 loctl1 =
606 b43_get_lo_g_ctl(dev,
607 &lo->rfatt_list.list[rf_offset],
608 &lo->bbatt_list.list[bb_offset]);
609 } else
610 loctl1 = loctl0;
611
612 tmp = ((u16) loctl0->q & 0xF);
613 tmp |= ((u16) loctl0->i & 0xF) << 4;
614 tmp |= ((u16) loctl1->q & 0xF) << 8;
615 tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME?
616 b43_phy_write(dev, 0x3A0 + (i / 2), tmp);
617 }
618}
619
620static void hardware_pctl_init_aphy(struct b43_wldev *dev) 579static void hardware_pctl_init_aphy(struct b43_wldev *dev)
621{ 580{
622 //TODO 581 //TODO
@@ -643,7 +602,7 @@ static void hardware_pctl_init_gphy(struct b43_wldev *dev)
643 b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) 602 b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801)
644 & 0xFFBF); 603 & 0xFFBF);
645 604
646 b43_gphy_dc_lt_init(dev); 605 b43_gphy_dc_lt_init(dev, 1);
647} 606}
648 607
649/* HardwarePowerControl init for A and G PHY */ 608/* HardwarePowerControl init for A and G PHY */
@@ -967,7 +926,7 @@ static void b43_phy_initb2(struct b43_wldev *dev)
967 b43_phy_write(dev, 0x0032, 0x00CA); 926 b43_phy_write(dev, 0x0032, 0x00CA);
968 b43_phy_write(dev, 0x0032, 0x00CC); 927 b43_phy_write(dev, 0x0032, 0x00CC);
969 b43_phy_write(dev, 0x0035, 0x07C2); 928 b43_phy_write(dev, 0x0035, 0x07C2);
970 b43_lo_b_measure(dev); 929//XXX won't trigger b43_lo_b_measure(dev);
971 b43_phy_write(dev, 0x0026, 0xCC00); 930 b43_phy_write(dev, 0x0026, 0xCC00);
972 if (phy->radio_ver != 0x2050) 931 if (phy->radio_ver != 0x2050)
973 b43_phy_write(dev, 0x0026, 0xCE00); 932 b43_phy_write(dev, 0x0026, 0xCE00);
@@ -1017,7 +976,7 @@ static void b43_phy_initb4(struct b43_wldev *dev)
1017 b43_phy_write(dev, 0x0032, 0x00E0); 976 b43_phy_write(dev, 0x0032, 0x00E0);
1018 b43_phy_write(dev, 0x0035, 0x07C2); 977 b43_phy_write(dev, 0x0035, 0x07C2);
1019 978
1020 b43_lo_b_measure(dev); 979//XXX won't trigger b43_lo_b_measure(dev);
1021 980
1022 b43_phy_write(dev, 0x0026, 0xCC00); 981 b43_phy_write(dev, 0x0026, 0xCC00);
1023 if (phy->radio_ver == 0x2050) 982 if (phy->radio_ver == 0x2050)
@@ -1259,19 +1218,9 @@ static void b43_phy_initb6(struct b43_wldev *dev)
1259 b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) 1218 b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0)
1260 | 0x0004); 1219 | 0x0004);
1261 } 1220 }
1262 if (phy->type == B43_PHYTYPE_B) { 1221 if (phy->type == B43_PHYTYPE_B)
1263 b43_write16(dev, 0x03E6, 0x8140); 1222 B43_WARN_ON(1);
1264 b43_phy_write(dev, 0x0016, 0x0410); 1223 else if (phy->type == B43_PHYTYPE_G)
1265 b43_phy_write(dev, 0x0017, 0x0820);
1266 b43_phy_write(dev, 0x0062, 0x0007);
1267 b43_radio_init2050(dev);
1268 b43_lo_g_measure(dev);
1269 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
1270 b43_calc_nrssi_slope(dev);
1271 b43_calc_nrssi_threshold(dev);
1272 }
1273 b43_phy_init_pctl(dev);
1274 } else if (phy->type == B43_PHYTYPE_G)
1275 b43_write16(dev, 0x03E6, 0x0); 1224 b43_write16(dev, 0x03E6, 0x0);
1276} 1225}
1277 1226
@@ -1534,34 +1483,31 @@ static void b43_phy_initg(struct b43_wldev *dev)
1534 else 1483 else
1535 b43_radio_write16(dev, 0x0078, phy->initval); 1484 b43_radio_write16(dev, 0x0078, phy->initval);
1536 } 1485 }
1537 if (phy->lo_control->tx_bias == 0xFF) { 1486 b43_lo_g_init(dev);
1538 b43_lo_g_measure(dev); 1487 if (has_tx_magnification(phy)) {
1488 b43_radio_write16(dev, 0x52,
1489 (b43_radio_read16(dev, 0x52) & 0xFF00)
1490 | phy->lo_control->tx_bias | phy->
1491 lo_control->tx_magn);
1539 } else { 1492 } else {
1540 if (has_tx_magnification(phy)) { 1493 b43_radio_write16(dev, 0x52,
1541 b43_radio_write16(dev, 0x52, 1494 (b43_radio_read16(dev, 0x52) & 0xFFF0)
1542 (b43_radio_read16(dev, 0x52) & 0xFF00) 1495 | phy->lo_control->tx_bias);
1543 | phy->lo_control->tx_bias | phy->
1544 lo_control->tx_magn);
1545 } else {
1546 b43_radio_write16(dev, 0x52,
1547 (b43_radio_read16(dev, 0x52) & 0xFFF0)
1548 | phy->lo_control->tx_bias);
1549 }
1550 if (phy->rev >= 6) {
1551 b43_phy_write(dev, B43_PHY_CCK(0x36),
1552 (b43_phy_read(dev, B43_PHY_CCK(0x36))
1553 & 0x0FFF) | (phy->lo_control->
1554 tx_bias << 12));
1555 }
1556 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
1557 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
1558 else
1559 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
1560 if (phy->rev < 2)
1561 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
1562 else
1563 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
1564 } 1496 }
1497 if (phy->rev >= 6) {
1498 b43_phy_write(dev, B43_PHY_CCK(0x36),
1499 (b43_phy_read(dev, B43_PHY_CCK(0x36))
1500 & 0x0FFF) | (phy->lo_control->
1501 tx_bias << 12));
1502 }
1503 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
1504 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
1505 else
1506 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
1507 if (phy->rev < 2)
1508 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
1509 else
1510 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
1565 if (phy->gmode || phy->rev >= 2) { 1511 if (phy->gmode || phy->rev >= 2) {
1566 b43_lo_g_adjust(dev); 1512 b43_lo_g_adjust(dev);
1567 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); 1513 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
@@ -1821,10 +1767,8 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
1821 bbatt_delta -= 4 * rfatt_delta; 1767 bbatt_delta -= 4 * rfatt_delta;
1822 1768
1823 /* So do we finally need to adjust something? */ 1769 /* So do we finally need to adjust something? */
1824 if ((rfatt_delta == 0) && (bbatt_delta == 0)) { 1770 if ((rfatt_delta == 0) && (bbatt_delta == 0))
1825 b43_lo_g_ctl_mark_cur_used(dev);
1826 return; 1771 return;
1827 }
1828 1772
1829 /* Calculate the new attenuation values. */ 1773 /* Calculate the new attenuation values. */
1830 bbatt = phy->bbatt.att; 1774 bbatt = phy->bbatt.att;
@@ -1870,7 +1814,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
1870 b43_radio_lock(dev); 1814 b43_radio_lock(dev);
1871 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, 1815 b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt,
1872 phy->tx_control); 1816 phy->tx_control);
1873 b43_lo_g_ctl_mark_cur_used(dev);
1874 b43_radio_unlock(dev); 1817 b43_radio_unlock(dev);
1875 b43_phy_unlock(dev); 1818 b43_phy_unlock(dev);
1876 break; 1819 break;
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h
index 6d165d822175..4aab10903529 100644
--- a/drivers/net/wireless/b43/phy.h
+++ b/drivers/net/wireless/b43/phy.h
@@ -225,7 +225,6 @@ int b43_phy_init(struct b43_wldev *dev);
225void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); 225void b43_set_rx_antenna(struct b43_wldev *dev, int antenna);
226 226
227void b43_phy_xmitpower(struct b43_wldev *dev); 227void b43_phy_xmitpower(struct b43_wldev *dev);
228void b43_gphy_dc_lt_init(struct b43_wldev *dev);
229 228
230/* Returns the boolean whether the board has HardwarePowerControl */ 229/* Returns the boolean whether the board has HardwarePowerControl */
231bool b43_has_hardware_pctl(struct b43_phy *phy); 230bool b43_has_hardware_pctl(struct b43_phy *phy);
@@ -252,6 +251,14 @@ struct b43_rfatt_list {
252 u8 max_val; 251 u8 max_val;
253}; 252};
254 253
254/* Returns true, if the values are the same. */
255static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
256 const struct b43_rfatt *b)
257{
258 return ((a->att == b->att) &&
259 (a->with_padmix == b->with_padmix));
260}
261
255/* Baseband Attenuation */ 262/* Baseband Attenuation */
256struct b43_bbatt { 263struct b43_bbatt {
257 u8 att; /* Attenuation value */ 264 u8 att; /* Attenuation value */
@@ -265,6 +272,13 @@ struct b43_bbatt_list {
265 u8 max_val; 272 u8 max_val;
266}; 273};
267 274
275/* Returns true, if the values are the same. */
276static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
277 const struct b43_bbatt *b)
278{
279 return (a->att == b->att);
280}
281
268/* tx_control bits. */ 282/* tx_control bits. */
269#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ 283#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
270#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ 284#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */