aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
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 */