3 Broadcom B43 wireless driver
5 G PHY LO (LocalOscillator) Measuring and Control routines
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
9 Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
10 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
11 Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
35 #include <linux/delay.h>
36 #include <linux/sched.h>
39 static struct b43_lo_calib
* b43_find_lo_calib(struct b43_txpower_lo_control
*lo
,
40 const struct b43_bbatt
*bbatt
,
41 const struct b43_rfatt
*rfatt
)
43 struct b43_lo_calib
*c
;
45 list_for_each_entry(c
, &lo
->calib_list
, list
) {
46 if (!b43_compare_bbatt(&c
->bbatt
, bbatt
))
48 if (!b43_compare_rfatt(&c
->rfatt
, rfatt
))
56 /* Write the LocalOscillator Control (adjust) value-pair. */
57 static void b43_lo_write(struct b43_wldev
*dev
, struct b43_loctl
*control
)
59 struct b43_phy
*phy
= &dev
->phy
;
63 if (unlikely(abs(control
->i
) > 16 || abs(control
->q
) > 16)) {
64 b43dbg(dev
->wl
, "Invalid LO control pair "
65 "(I: %d, Q: %d)\n", control
->i
, control
->q
);
70 B43_WARN_ON(phy
->type
!= B43_PHYTYPE_G
);
72 value
= (u8
) (control
->q
);
73 value
|= ((u8
) (control
->i
)) << 8;
74 b43_phy_write(dev
, B43_PHY_LO_CTL
, value
);
77 static u16
lo_measure_feedthrough(struct b43_wldev
*dev
,
78 u16 lna
, u16 pga
, u16 trsw_rx
)
80 struct b43_phy
*phy
= &dev
->phy
;
85 lna
<<= B43_PHY_RFOVERVAL_LNA_SHIFT
;
86 pga
<<= B43_PHY_RFOVERVAL_PGA_SHIFT
;
88 B43_WARN_ON(lna
& ~B43_PHY_RFOVERVAL_LNA
);
89 B43_WARN_ON(pga
& ~B43_PHY_RFOVERVAL_PGA
);
90 /*FIXME This assertion fails B43_WARN_ON(trsw_rx & ~(B43_PHY_RFOVERVAL_TRSWRX |
91 B43_PHY_RFOVERVAL_BW));
93 trsw_rx
&= (B43_PHY_RFOVERVAL_TRSWRX
| B43_PHY_RFOVERVAL_BW
);
95 /* Construct the RF Override Value */
96 rfover
= B43_PHY_RFOVERVAL_UNK
;
100 if ((dev
->dev
->bus
->sprom
.boardflags_lo
& B43_BFL_EXTLNA
)
102 rfover
|= B43_PHY_RFOVERVAL_EXTLNA
;
104 b43_phy_write(dev
, B43_PHY_PGACTL
, 0xE300);
105 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, rfover
);
107 rfover
|= B43_PHY_RFOVERVAL_BW_LBW
;
108 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, rfover
);
110 rfover
|= B43_PHY_RFOVERVAL_BW_LPF
;
111 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, rfover
);
113 b43_phy_write(dev
, B43_PHY_PGACTL
, 0xF300);
115 pga
|= B43_PHY_PGACTL_UNKNOWN
;
116 b43_phy_write(dev
, B43_PHY_PGACTL
, pga
);
118 pga
|= B43_PHY_PGACTL_LOWBANDW
;
119 b43_phy_write(dev
, B43_PHY_PGACTL
, pga
);
121 pga
|= B43_PHY_PGACTL_LPF
;
122 b43_phy_write(dev
, B43_PHY_PGACTL
, pga
);
125 feedthrough
= b43_phy_read(dev
, B43_PHY_LO_LEAKAGE
);
127 /* This is a good place to check if we need to relax a bit,
128 * as this is the main function called regularly
129 * in the LO calibration. */
135 /* TXCTL Register and Value Table.
136 * Returns the "TXCTL Register".
137 * "value" is the "TXCTL Value".
138 * "pad_mix_gain" is the PAD Mixer Gain.
140 static u16
lo_txctl_register_table(struct b43_wldev
*dev
,
141 u16
* value
, u16
* pad_mix_gain
)
143 struct b43_phy
*phy
= &dev
->phy
;
146 if (phy
->type
== B43_PHYTYPE_B
) {
148 if (phy
->radio_rev
<= 5) {
156 if (phy
->rev
>= 2 && phy
->radio_rev
== 8) {
169 *pad_mix_gain
= padmix
;
174 static void lo_measure_txctl_values(struct b43_wldev
*dev
)
176 struct b43_phy
*phy
= &dev
->phy
;
177 struct b43_phy_g
*gphy
= phy
->g
;
178 struct b43_txpower_lo_control
*lo
= gphy
->lo_control
;
183 static const u8 tx_bias_values
[] = {
184 0x09, 0x08, 0x0A, 0x01, 0x00,
185 0x02, 0x05, 0x04, 0x06,
187 static const u8 tx_magn_values
[] = {
191 if (!has_loopback_gain(phy
)) {
196 int lb_gain
; /* Loopback gain (in dB) */
199 lb_gain
= gphy
->max_lb_gain
/ 2;
202 pga
= abs(10 - lb_gain
) / 6;
203 pga
= clamp_val(pga
, 0, 15);
210 if ((phy
->rev
>= 2) &&
211 (phy
->radio_ver
== 0x2050) && (phy
->radio_rev
== 8))
214 if ((10 - lb_gain
) < cmp_val
)
215 tmp
= (10 - lb_gain
);
223 radio_pctl_reg
= cmp_val
;
225 radio_pctl_reg
= tmp
;
228 b43_radio_write16(dev
, 0x43, (b43_radio_read16(dev
, 0x43)
229 & 0xFFF0) | radio_pctl_reg
);
230 b43_gphy_set_baseband_attenuation(dev
, 2);
232 reg
= lo_txctl_register_table(dev
, &mask
, NULL
);
234 b43_radio_write16(dev
, reg
, b43_radio_read16(dev
, reg
)
237 if (has_tx_magnification(phy
)) {
240 int min_feedth
= 0xFFFF;
243 for (i
= 0; i
< ARRAY_SIZE(tx_magn_values
); i
++) {
244 tx_magn
= tx_magn_values
[i
];
245 b43_radio_write16(dev
, 0x52,
246 (b43_radio_read16(dev
, 0x52)
247 & 0xFF0F) | tx_magn
);
248 for (j
= 0; j
< ARRAY_SIZE(tx_bias_values
); j
++) {
249 tx_bias
= tx_bias_values
[j
];
250 b43_radio_write16(dev
, 0x52,
251 (b43_radio_read16(dev
, 0x52)
252 & 0xFFF0) | tx_bias
);
254 lo_measure_feedthrough(dev
, 0, pga
,
256 if (feedthrough
< min_feedth
) {
257 lo
->tx_bias
= tx_bias
;
258 lo
->tx_magn
= tx_magn
;
259 min_feedth
= feedthrough
;
261 if (lo
->tx_bias
== 0)
264 b43_radio_write16(dev
, 0x52,
265 (b43_radio_read16(dev
, 0x52)
266 & 0xFF00) | lo
->tx_bias
| lo
->
272 b43_radio_write16(dev
, 0x52, b43_radio_read16(dev
, 0x52)
273 & 0xFFF0); /* TX bias == 0 */
275 lo
->txctl_measured_time
= jiffies
;
278 static void lo_read_power_vector(struct b43_wldev
*dev
)
280 struct b43_phy
*phy
= &dev
->phy
;
281 struct b43_phy_g
*gphy
= phy
->g
;
282 struct b43_txpower_lo_control
*lo
= gphy
->lo_control
;
285 u64 power_vector
= 0;
287 for (i
= 0; i
< 8; i
+= 2) {
288 tmp
= b43_shm_read16(dev
, B43_SHM_SHARED
, 0x310 + i
);
289 power_vector
|= (tmp
<< (i
* 8));
290 /* Clear the vector on the device. */
291 b43_shm_write16(dev
, B43_SHM_SHARED
, 0x310 + i
, 0);
294 lo
->power_vector
= power_vector
;
295 lo
->pwr_vec_read_time
= jiffies
;
298 /* 802.11/LO/GPHY/MeasuringGains */
299 static void lo_measure_gain_values(struct b43_wldev
*dev
,
300 s16 max_rx_gain
, int use_trsw_rx
)
302 struct b43_phy
*phy
= &dev
->phy
;
303 struct b43_phy_g
*gphy
= phy
->g
;
309 if (has_loopback_gain(phy
)) {
314 trsw_rx_gain
= gphy
->trsw_rx_gain
/ 2;
315 if (max_rx_gain
>= trsw_rx_gain
) {
316 trsw_rx_gain
= max_rx_gain
- trsw_rx_gain
;
320 trsw_rx_gain
= max_rx_gain
;
321 if (trsw_rx_gain
< 9) {
322 gphy
->lna_lod_gain
= 0;
324 gphy
->lna_lod_gain
= 1;
327 trsw_rx_gain
= clamp_val(trsw_rx_gain
, 0, 0x2D);
328 gphy
->pga_gain
= trsw_rx_gain
/ 3;
329 if (gphy
->pga_gain
>= 5) {
336 gphy
->trsw_rx_gain
= 0x20;
337 if (max_rx_gain
>= 0x14) {
338 gphy
->lna_lod_gain
= 1;
340 } else if (max_rx_gain
>= 0x12) {
341 gphy
->lna_lod_gain
= 1;
343 } else if (max_rx_gain
>= 0xF) {
344 gphy
->lna_lod_gain
= 1;
347 gphy
->lna_lod_gain
= 0;
352 tmp
= b43_radio_read16(dev
, 0x7A);
353 if (gphy
->lna_lod_gain
== 0)
357 b43_radio_write16(dev
, 0x7A, tmp
);
360 struct lo_g_saved_values
{
370 u16 phy_dacctl_hwpctl
;
373 u16 phy_hpwr_tssictl
;
375 u16 phy_analogoverval
;
387 /* Radio registers */
393 static void lo_measure_setup(struct b43_wldev
*dev
,
394 struct lo_g_saved_values
*sav
)
396 struct ssb_sprom
*sprom
= &dev
->dev
->bus
->sprom
;
397 struct b43_phy
*phy
= &dev
->phy
;
398 struct b43_phy_g
*gphy
= phy
->g
;
399 struct b43_txpower_lo_control
*lo
= gphy
->lo_control
;
402 if (b43_has_hardware_pctl(dev
)) {
403 sav
->phy_lo_mask
= b43_phy_read(dev
, B43_PHY_LO_MASK
);
404 sav
->phy_extg_01
= b43_phy_read(dev
, B43_PHY_EXTG(0x01));
405 sav
->phy_dacctl_hwpctl
= b43_phy_read(dev
, B43_PHY_DACCTL
);
406 sav
->phy_cck_14
= b43_phy_read(dev
, B43_PHY_CCK(0x14));
407 sav
->phy_hpwr_tssictl
= b43_phy_read(dev
, B43_PHY_HPWR_TSSICTL
);
409 b43_phy_set(dev
, B43_PHY_HPWR_TSSICTL
, 0x100);
410 b43_phy_set(dev
, B43_PHY_EXTG(0x01), 0x40);
411 b43_phy_set(dev
, B43_PHY_DACCTL
, 0x40);
412 b43_phy_set(dev
, B43_PHY_CCK(0x14), 0x200);
414 if (phy
->type
== B43_PHYTYPE_B
&&
415 phy
->radio_ver
== 0x2050 && phy
->radio_rev
< 6) {
416 b43_phy_write(dev
, B43_PHY_CCK(0x16), 0x410);
417 b43_phy_write(dev
, B43_PHY_CCK(0x17), 0x820);
420 sav
->phy_analogover
= b43_phy_read(dev
, B43_PHY_ANALOGOVER
);
421 sav
->phy_analogoverval
=
422 b43_phy_read(dev
, B43_PHY_ANALOGOVERVAL
);
423 sav
->phy_rfover
= b43_phy_read(dev
, B43_PHY_RFOVER
);
424 sav
->phy_rfoverval
= b43_phy_read(dev
, B43_PHY_RFOVERVAL
);
425 sav
->phy_classctl
= b43_phy_read(dev
, B43_PHY_CLASSCTL
);
426 sav
->phy_cck_3E
= b43_phy_read(dev
, B43_PHY_CCK(0x3E));
427 sav
->phy_crs0
= b43_phy_read(dev
, B43_PHY_CRS0
);
429 b43_phy_write(dev
, B43_PHY_CLASSCTL
,
430 b43_phy_read(dev
, B43_PHY_CLASSCTL
)
432 b43_phy_write(dev
, B43_PHY_CRS0
, b43_phy_read(dev
, B43_PHY_CRS0
)
434 b43_phy_set(dev
, B43_PHY_ANALOGOVER
, 0x0003);
435 b43_phy_write(dev
, B43_PHY_ANALOGOVERVAL
,
436 b43_phy_read(dev
, B43_PHY_ANALOGOVERVAL
)
438 if (phy
->type
== B43_PHYTYPE_G
) {
439 if ((phy
->rev
>= 7) &&
440 (sprom
->boardflags_lo
& B43_BFL_EXTLNA
)) {
441 b43_phy_write(dev
, B43_PHY_RFOVER
, 0x933);
443 b43_phy_write(dev
, B43_PHY_RFOVER
, 0x133);
446 b43_phy_write(dev
, B43_PHY_RFOVER
, 0);
448 b43_phy_write(dev
, B43_PHY_CCK(0x3E), 0);
450 sav
->reg_3F4
= b43_read16(dev
, 0x3F4);
451 sav
->reg_3E2
= b43_read16(dev
, 0x3E2);
452 sav
->radio_43
= b43_radio_read16(dev
, 0x43);
453 sav
->radio_7A
= b43_radio_read16(dev
, 0x7A);
454 sav
->phy_pgactl
= b43_phy_read(dev
, B43_PHY_PGACTL
);
455 sav
->phy_cck_2A
= b43_phy_read(dev
, B43_PHY_CCK(0x2A));
456 sav
->phy_syncctl
= b43_phy_read(dev
, B43_PHY_SYNCCTL
);
457 sav
->phy_dacctl
= b43_phy_read(dev
, B43_PHY_DACCTL
);
459 if (!has_tx_magnification(phy
)) {
460 sav
->radio_52
= b43_radio_read16(dev
, 0x52);
461 sav
->radio_52
&= 0x00F0;
463 if (phy
->type
== B43_PHYTYPE_B
) {
464 sav
->phy_cck_30
= b43_phy_read(dev
, B43_PHY_CCK(0x30));
465 sav
->phy_cck_06
= b43_phy_read(dev
, B43_PHY_CCK(0x06));
466 b43_phy_write(dev
, B43_PHY_CCK(0x30), 0x00FF);
467 b43_phy_write(dev
, B43_PHY_CCK(0x06), 0x3F3F);
469 b43_write16(dev
, 0x3E2, b43_read16(dev
, 0x3E2)
472 b43_write16(dev
, 0x3F4, b43_read16(dev
, 0x3F4)
476 (phy
->type
== B43_PHYTYPE_G
) ? B43_PHY_LO_MASK
: B43_PHY_CCK(0x2E);
477 b43_phy_write(dev
, tmp
, 0x007F);
479 tmp
= sav
->phy_syncctl
;
480 b43_phy_write(dev
, B43_PHY_SYNCCTL
, tmp
& 0xFF7F);
482 b43_radio_write16(dev
, 0x007A, tmp
& 0xFFF0);
484 b43_phy_write(dev
, B43_PHY_CCK(0x2A), 0x8A3);
485 if (phy
->type
== B43_PHYTYPE_G
||
486 (phy
->type
== B43_PHYTYPE_B
&&
487 phy
->radio_ver
== 0x2050 && phy
->radio_rev
>= 6)) {
488 b43_phy_write(dev
, B43_PHY_CCK(0x2B), 0x1003);
490 b43_phy_write(dev
, B43_PHY_CCK(0x2B), 0x0802);
492 b43_dummy_transmission(dev
);
493 b43_gphy_channel_switch(dev
, 6, 0);
494 b43_radio_read16(dev
, 0x51); /* dummy read */
495 if (phy
->type
== B43_PHYTYPE_G
)
496 b43_phy_write(dev
, B43_PHY_CCK(0x2F), 0);
498 /* Re-measure the txctl values, if needed. */
499 if (time_before(lo
->txctl_measured_time
,
500 jiffies
- B43_LO_TXCTL_EXPIRE
))
501 lo_measure_txctl_values(dev
);
503 if (phy
->type
== B43_PHYTYPE_G
&& phy
->rev
>= 3) {
504 b43_phy_write(dev
, B43_PHY_LO_MASK
, 0xC078);
506 if (phy
->type
== B43_PHYTYPE_B
)
507 b43_phy_write(dev
, B43_PHY_CCK(0x2E), 0x8078);
509 b43_phy_write(dev
, B43_PHY_LO_MASK
, 0x8078);
513 static void lo_measure_restore(struct b43_wldev
*dev
,
514 struct lo_g_saved_values
*sav
)
516 struct b43_phy
*phy
= &dev
->phy
;
517 struct b43_phy_g
*gphy
= phy
->g
;
521 b43_phy_write(dev
, B43_PHY_PGACTL
, 0xE300);
522 tmp
= (gphy
->pga_gain
<< 8);
523 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, tmp
| 0xA0);
525 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, tmp
| 0xA2);
527 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, tmp
| 0xA3);
529 tmp
= (gphy
->pga_gain
| 0xEFA0);
530 b43_phy_write(dev
, B43_PHY_PGACTL
, tmp
);
532 if (phy
->type
== B43_PHYTYPE_G
) {
534 b43_phy_write(dev
, B43_PHY_CCK(0x2E), 0xC078);
536 b43_phy_write(dev
, B43_PHY_CCK(0x2E), 0x8078);
538 b43_phy_write(dev
, B43_PHY_CCK(0x2F), 0x0202);
540 b43_phy_write(dev
, B43_PHY_CCK(0x2F), 0x0101);
542 b43_write16(dev
, 0x3F4, sav
->reg_3F4
);
543 b43_phy_write(dev
, B43_PHY_PGACTL
, sav
->phy_pgactl
);
544 b43_phy_write(dev
, B43_PHY_CCK(0x2A), sav
->phy_cck_2A
);
545 b43_phy_write(dev
, B43_PHY_SYNCCTL
, sav
->phy_syncctl
);
546 b43_phy_write(dev
, B43_PHY_DACCTL
, sav
->phy_dacctl
);
547 b43_radio_write16(dev
, 0x43, sav
->radio_43
);
548 b43_radio_write16(dev
, 0x7A, sav
->radio_7A
);
549 if (!has_tx_magnification(phy
)) {
551 b43_radio_write16(dev
, 0x52, (b43_radio_read16(dev
, 0x52)
554 b43_write16(dev
, 0x3E2, sav
->reg_3E2
);
555 if (phy
->type
== B43_PHYTYPE_B
&&
556 phy
->radio_ver
== 0x2050 && phy
->radio_rev
<= 5) {
557 b43_phy_write(dev
, B43_PHY_CCK(0x30), sav
->phy_cck_30
);
558 b43_phy_write(dev
, B43_PHY_CCK(0x06), sav
->phy_cck_06
);
561 b43_phy_write(dev
, B43_PHY_ANALOGOVER
, sav
->phy_analogover
);
562 b43_phy_write(dev
, B43_PHY_ANALOGOVERVAL
,
563 sav
->phy_analogoverval
);
564 b43_phy_write(dev
, B43_PHY_CLASSCTL
, sav
->phy_classctl
);
565 b43_phy_write(dev
, B43_PHY_RFOVER
, sav
->phy_rfover
);
566 b43_phy_write(dev
, B43_PHY_RFOVERVAL
, sav
->phy_rfoverval
);
567 b43_phy_write(dev
, B43_PHY_CCK(0x3E), sav
->phy_cck_3E
);
568 b43_phy_write(dev
, B43_PHY_CRS0
, sav
->phy_crs0
);
570 if (b43_has_hardware_pctl(dev
)) {
571 tmp
= (sav
->phy_lo_mask
& 0xBFFF);
572 b43_phy_write(dev
, B43_PHY_LO_MASK
, tmp
);
573 b43_phy_write(dev
, B43_PHY_EXTG(0x01), sav
->phy_extg_01
);
574 b43_phy_write(dev
, B43_PHY_DACCTL
, sav
->phy_dacctl_hwpctl
);
575 b43_phy_write(dev
, B43_PHY_CCK(0x14), sav
->phy_cck_14
);
576 b43_phy_write(dev
, B43_PHY_HPWR_TSSICTL
, sav
->phy_hpwr_tssictl
);
578 b43_gphy_channel_switch(dev
, sav
->old_channel
, 1);
581 struct b43_lo_g_statemachine
{
584 int state_val_multiplier
;
586 struct b43_loctl min_loctl
;
589 /* Loop over each possible value in this state. */
590 static int lo_probe_possible_loctls(struct b43_wldev
*dev
,
591 struct b43_loctl
*probe_loctl
,
592 struct b43_lo_g_statemachine
*d
)
594 struct b43_phy
*phy
= &dev
->phy
;
595 struct b43_phy_g
*gphy
= phy
->g
;
596 struct b43_loctl test_loctl
;
597 struct b43_loctl orig_loctl
;
598 struct b43_loctl prev_loctl
= {
607 static const struct b43_loctl modifiers
[] = {
618 if (d
->current_state
== 0) {
621 } else if (d
->current_state
% 2 == 0) {
622 begin
= d
->current_state
- 1;
623 end
= d
->current_state
+ 1;
625 begin
= d
->current_state
- 2;
626 end
= d
->current_state
+ 2;
633 memcpy(&orig_loctl
, probe_loctl
, sizeof(struct b43_loctl
));
635 d
->current_state
= i
;
637 B43_WARN_ON(!(i
>= 1 && i
<= 8));
638 memcpy(&test_loctl
, &orig_loctl
, sizeof(struct b43_loctl
));
639 test_loctl
.i
+= modifiers
[i
- 1].i
* d
->state_val_multiplier
;
640 test_loctl
.q
+= modifiers
[i
- 1].q
* d
->state_val_multiplier
;
641 if ((test_loctl
.i
!= prev_loctl
.i
||
642 test_loctl
.q
!= prev_loctl
.q
) &&
643 (abs(test_loctl
.i
) <= 16 && abs(test_loctl
.q
) <= 16)) {
644 b43_lo_write(dev
, &test_loctl
);
645 feedth
= lo_measure_feedthrough(dev
, gphy
->lna_gain
,
648 if (feedth
< d
->lowest_feedth
) {
649 memcpy(probe_loctl
, &test_loctl
,
650 sizeof(struct b43_loctl
));
652 d
->lowest_feedth
= feedth
;
653 if ((d
->nr_measured
< 2) &&
654 !has_loopback_gain(phy
))
658 memcpy(&prev_loctl
, &test_loctl
, sizeof(prev_loctl
));
665 d
->current_state
= i
;
671 static void lo_probe_loctls_statemachine(struct b43_wldev
*dev
,
672 struct b43_loctl
*loctl
,
675 struct b43_phy
*phy
= &dev
->phy
;
676 struct b43_phy_g
*gphy
= phy
->g
;
677 struct b43_lo_g_statemachine d
;
680 struct b43_loctl probe_loctl
;
681 int max_repeat
= 1, repeat_cnt
= 0;
684 d
.state_val_multiplier
= 1;
685 if (has_loopback_gain(phy
))
686 d
.state_val_multiplier
= 3;
688 memcpy(&d
.min_loctl
, loctl
, sizeof(struct b43_loctl
));
689 if (has_loopback_gain(phy
))
692 b43_lo_write(dev
, &d
.min_loctl
);
693 feedth
= lo_measure_feedthrough(dev
, gphy
->lna_gain
,
696 if (feedth
< 0x258) {
701 feedth
= lo_measure_feedthrough(dev
, gphy
->lna_gain
,
705 d
.lowest_feedth
= feedth
;
710 (d
.current_state
>= 0
711 && d
.current_state
<= 8));
712 memcpy(&probe_loctl
, &d
.min_loctl
,
713 sizeof(struct b43_loctl
));
715 lo_probe_possible_loctls(dev
, &probe_loctl
, &d
);
718 if ((probe_loctl
.i
== d
.min_loctl
.i
) &&
719 (probe_loctl
.q
== d
.min_loctl
.q
))
721 memcpy(&d
.min_loctl
, &probe_loctl
,
722 sizeof(struct b43_loctl
));
724 } while (d
.nr_measured
< 24);
725 memcpy(loctl
, &d
.min_loctl
, sizeof(struct b43_loctl
));
727 if (has_loopback_gain(phy
)) {
728 if (d
.lowest_feedth
> 0x1194)
730 else if (d
.lowest_feedth
< 0x5DC)
732 if (repeat_cnt
== 0) {
733 if (d
.lowest_feedth
<= 0x5DC) {
734 d
.state_val_multiplier
= 1;
737 d
.state_val_multiplier
= 2;
738 } else if (repeat_cnt
== 2)
739 d
.state_val_multiplier
= 1;
741 lo_measure_gain_values(dev
, *max_rx_gain
,
742 has_loopback_gain(phy
));
743 } while (++repeat_cnt
< max_repeat
);
747 struct b43_lo_calib
* b43_calibrate_lo_setting(struct b43_wldev
*dev
,
748 const struct b43_bbatt
*bbatt
,
749 const struct b43_rfatt
*rfatt
)
751 struct b43_phy
*phy
= &dev
->phy
;
752 struct b43_phy_g
*gphy
= phy
->g
;
753 struct b43_loctl loctl
= {
758 struct b43_lo_calib
*cal
;
759 struct lo_g_saved_values
uninitialized_var(saved_regs
);
760 /* Values from the "TXCTL Register and Value Table" */
765 saved_regs
.old_channel
= phy
->channel
;
766 b43_mac_suspend(dev
);
767 lo_measure_setup(dev
, &saved_regs
);
769 txctl_reg
= lo_txctl_register_table(dev
, &txctl_value
, &pad_mix_gain
);
771 b43_radio_write16(dev
, 0x43,
772 (b43_radio_read16(dev
, 0x43) & 0xFFF0)
774 b43_radio_write16(dev
, txctl_reg
,
775 (b43_radio_read16(dev
, txctl_reg
) & ~txctl_value
)
776 | (rfatt
->with_padmix
? txctl_value
: 0));
778 max_rx_gain
= rfatt
->att
* 2;
779 max_rx_gain
+= bbatt
->att
/ 2;
780 if (rfatt
->with_padmix
)
781 max_rx_gain
-= pad_mix_gain
;
782 if (has_loopback_gain(phy
))
783 max_rx_gain
+= gphy
->max_lb_gain
;
784 lo_measure_gain_values(dev
, max_rx_gain
,
785 has_loopback_gain(phy
));
787 b43_gphy_set_baseband_attenuation(dev
, bbatt
->att
);
788 lo_probe_loctls_statemachine(dev
, &loctl
, &max_rx_gain
);
790 lo_measure_restore(dev
, &saved_regs
);
793 if (b43_debug(dev
, B43_DBG_LO
)) {
794 b43dbg(dev
->wl
, "LO: Calibrated for BB(%u), RF(%u,%u) "
796 bbatt
->att
, rfatt
->att
, rfatt
->with_padmix
,
800 cal
= kmalloc(sizeof(*cal
), GFP_KERNEL
);
802 b43warn(dev
->wl
, "LO calib: out of memory\n");
805 memcpy(&cal
->bbatt
, bbatt
, sizeof(*bbatt
));
806 memcpy(&cal
->rfatt
, rfatt
, sizeof(*rfatt
));
807 memcpy(&cal
->ctl
, &loctl
, sizeof(loctl
));
808 cal
->calib_time
= jiffies
;
809 INIT_LIST_HEAD(&cal
->list
);
814 /* Get a calibrated LO setting for the given attenuation values.
815 * Might return a NULL pointer under OOM! */
817 struct b43_lo_calib
* b43_get_calib_lo_settings(struct b43_wldev
*dev
,
818 const struct b43_bbatt
*bbatt
,
819 const struct b43_rfatt
*rfatt
)
821 struct b43_txpower_lo_control
*lo
= dev
->phy
.g
->lo_control
;
822 struct b43_lo_calib
*c
;
824 c
= b43_find_lo_calib(lo
, bbatt
, rfatt
);
827 /* Not in the list of calibrated LO settings.
828 * Calibrate it now. */
829 c
= b43_calibrate_lo_setting(dev
, bbatt
, rfatt
);
832 list_add(&c
->list
, &lo
->calib_list
);
837 void b43_gphy_dc_lt_init(struct b43_wldev
*dev
, bool update_all
)
839 struct b43_phy
*phy
= &dev
->phy
;
840 struct b43_phy_g
*gphy
= phy
->g
;
841 struct b43_txpower_lo_control
*lo
= gphy
->lo_control
;
843 int rf_offset
, bb_offset
;
844 const struct b43_rfatt
*rfatt
;
845 const struct b43_bbatt
*bbatt
;
847 bool table_changed
= 0;
849 BUILD_BUG_ON(B43_DC_LT_SIZE
!= 32);
850 B43_WARN_ON(lo
->rfatt_list
.len
* lo
->bbatt_list
.len
> 64);
852 power_vector
= lo
->power_vector
;
853 if (!update_all
&& !power_vector
)
854 return; /* Nothing to do. */
856 /* Suspend the MAC now to avoid continuous suspend/enable
857 * cycles in the loop. */
858 b43_mac_suspend(dev
);
860 for (i
= 0; i
< B43_DC_LT_SIZE
* 2; i
++) {
861 struct b43_lo_calib
*cal
;
865 if (!update_all
&& !(power_vector
& (((u64
)1ULL) << i
)))
867 /* Update the table entry for this power_vector bit.
868 * The table rows are RFatt entries and columns are BBatt. */
869 bb_offset
= i
/ lo
->rfatt_list
.len
;
870 rf_offset
= i
% lo
->rfatt_list
.len
;
871 bbatt
= &(lo
->bbatt_list
.list
[bb_offset
]);
872 rfatt
= &(lo
->rfatt_list
.list
[rf_offset
]);
874 cal
= b43_calibrate_lo_setting(dev
, bbatt
, rfatt
);
876 b43warn(dev
->wl
, "LO: Could not "
877 "calibrate DC table entry\n");
880 /*FIXME: Is Q really in the low nibble? */
881 val
= (u8
)(cal
->ctl
.q
);
882 val
|= ((u8
)(cal
->ctl
.i
)) << 4;
885 /* Get the index into the hardware DC LT. */
887 /* Change the table in memory. */
889 /* Change the high byte. */
890 lo
->dc_lt
[idx
] = (lo
->dc_lt
[idx
] & 0x00FF)
891 | ((val
& 0x00FF) << 8);
893 /* Change the low byte. */
894 lo
->dc_lt
[idx
] = (lo
->dc_lt
[idx
] & 0xFF00)
900 /* The table changed in memory. Update the hardware table. */
901 for (i
= 0; i
< B43_DC_LT_SIZE
; i
++)
902 b43_phy_write(dev
, 0x3A0 + i
, lo
->dc_lt
[i
]);
907 /* Fixup the RF attenuation value for the case where we are
908 * using the PAD mixer. */
909 static inline void b43_lo_fixup_rfatt(struct b43_rfatt
*rf
)
911 if (!rf
->with_padmix
)
913 if ((rf
->att
!= 1) && (rf
->att
!= 2) && (rf
->att
!= 3))
917 void b43_lo_g_adjust(struct b43_wldev
*dev
)
919 struct b43_phy_g
*gphy
= dev
->phy
.g
;
920 struct b43_lo_calib
*cal
;
923 memcpy(&rf
, &gphy
->rfatt
, sizeof(rf
));
924 b43_lo_fixup_rfatt(&rf
);
926 cal
= b43_get_calib_lo_settings(dev
, &gphy
->bbatt
, &rf
);
929 b43_lo_write(dev
, &cal
->ctl
);
932 void b43_lo_g_adjust_to(struct b43_wldev
*dev
,
933 u16 rfatt
, u16 bbatt
, u16 tx_control
)
937 struct b43_lo_calib
*cal
;
939 memset(&rf
, 0, sizeof(rf
));
940 memset(&bb
, 0, sizeof(bb
));
943 b43_lo_fixup_rfatt(&rf
);
944 cal
= b43_get_calib_lo_settings(dev
, &bb
, &rf
);
947 b43_lo_write(dev
, &cal
->ctl
);
950 /* Periodic LO maintanance work */
951 void b43_lo_g_maintanance_work(struct b43_wldev
*dev
)
953 struct b43_phy
*phy
= &dev
->phy
;
954 struct b43_phy_g
*gphy
= phy
->g
;
955 struct b43_txpower_lo_control
*lo
= gphy
->lo_control
;
957 unsigned long expire
;
958 struct b43_lo_calib
*cal
, *tmp
;
959 bool current_item_expired
= 0;
965 hwpctl
= b43_has_hardware_pctl(dev
);
968 /* Read the power vector and update it, if needed. */
969 expire
= now
- B43_LO_PWRVEC_EXPIRE
;
970 if (time_before(lo
->pwr_vec_read_time
, expire
)) {
971 lo_read_power_vector(dev
);
972 b43_gphy_dc_lt_init(dev
, 0);
974 //FIXME Recalc the whole DC table from time to time?
979 /* Search for expired LO settings. Remove them.
980 * Recalibrate the current setting, if expired. */
981 expire
= now
- B43_LO_CALIB_EXPIRE
;
982 list_for_each_entry_safe(cal
, tmp
, &lo
->calib_list
, list
) {
983 if (!time_before(cal
->calib_time
, expire
))
985 /* This item expired. */
986 if (b43_compare_bbatt(&cal
->bbatt
, &gphy
->bbatt
) &&
987 b43_compare_rfatt(&cal
->rfatt
, &gphy
->rfatt
)) {
988 B43_WARN_ON(current_item_expired
);
989 current_item_expired
= 1;
991 if (b43_debug(dev
, B43_DBG_LO
)) {
992 b43dbg(dev
->wl
, "LO: Item BB(%u), RF(%u,%u), "
993 "I=%d, Q=%d expired\n",
994 cal
->bbatt
.att
, cal
->rfatt
.att
,
995 cal
->rfatt
.with_padmix
,
996 cal
->ctl
.i
, cal
->ctl
.q
);
998 list_del(&cal
->list
);
1001 if (current_item_expired
|| unlikely(list_empty(&lo
->calib_list
))) {
1002 /* Recalibrate currently used LO setting. */
1003 if (b43_debug(dev
, B43_DBG_LO
))
1004 b43dbg(dev
->wl
, "LO: Recalibrating current LO setting\n");
1005 cal
= b43_calibrate_lo_setting(dev
, &gphy
->bbatt
, &gphy
->rfatt
);
1007 list_add(&cal
->list
, &lo
->calib_list
);
1008 b43_lo_write(dev
, &cal
->ctl
);
1010 b43warn(dev
->wl
, "Failed to recalibrate current LO setting\n");
1014 void b43_lo_g_cleanup(struct b43_wldev
*dev
)
1016 struct b43_txpower_lo_control
*lo
= dev
->phy
.g
->lo_control
;
1017 struct b43_lo_calib
*cal
, *tmp
;
1021 list_for_each_entry_safe(cal
, tmp
, &lo
->calib_list
, list
) {
1022 list_del(&cal
->list
);
1027 /* LO Initialization */
1028 void b43_lo_g_init(struct b43_wldev
*dev
)
1030 if (b43_has_hardware_pctl(dev
)) {
1031 lo_read_power_vector(dev
);
1032 b43_gphy_dc_lt_init(dev
, 1);