Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27 1036 lines 28 kB view raw
1/* 2 3 Broadcom B43 wireless driver 4 5 G PHY LO (LocalOscillator) Measuring and Control routines 6 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> 12 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. 17 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. 22 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. 27 28*/ 29 30#include "b43.h" 31#include "lo.h" 32#include "phy.h" 33#include "main.h" 34 35#include <linux/delay.h> 36#include <linux/sched.h> 37 38 39static 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) 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 } 52 53 return NULL; 54} 55 56/* Write the LocalOscillator Control (adjust) value-pair. */ 57static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) 58{ 59 struct b43_phy *phy = &dev->phy; 60 u16 value; 61 62 if (B43_DEBUG) { 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); 66 dump_stack(); 67 return; 68 } 69 } 70 B43_WARN_ON(phy->type != B43_PHYTYPE_G); 71 72 value = (u8) (control->q); 73 value |= ((u8) (control->i)) << 8; 74 b43_phy_write(dev, B43_PHY_LO_CTL, value); 75} 76 77static u16 lo_measure_feedthrough(struct b43_wldev *dev, 78 u16 lna, u16 pga, u16 trsw_rx) 79{ 80 struct b43_phy *phy = &dev->phy; 81 u16 rfover; 82 u16 feedthrough; 83 84 if (phy->gmode) { 85 lna <<= B43_PHY_RFOVERVAL_LNA_SHIFT; 86 pga <<= B43_PHY_RFOVERVAL_PGA_SHIFT; 87 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)); 92*/ 93 trsw_rx &= (B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW); 94 95 /* Construct the RF Override Value */ 96 rfover = B43_PHY_RFOVERVAL_UNK; 97 rfover |= pga; 98 rfover |= lna; 99 rfover |= trsw_rx; 100 if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) 101 && phy->rev > 6) 102 rfover |= B43_PHY_RFOVERVAL_EXTLNA; 103 104 b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); 105 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); 106 udelay(10); 107 rfover |= B43_PHY_RFOVERVAL_BW_LBW; 108 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); 109 udelay(10); 110 rfover |= B43_PHY_RFOVERVAL_BW_LPF; 111 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); 112 udelay(10); 113 b43_phy_write(dev, B43_PHY_PGACTL, 0xF300); 114 } else { 115 pga |= B43_PHY_PGACTL_UNKNOWN; 116 b43_phy_write(dev, B43_PHY_PGACTL, pga); 117 udelay(10); 118 pga |= B43_PHY_PGACTL_LOWBANDW; 119 b43_phy_write(dev, B43_PHY_PGACTL, pga); 120 udelay(10); 121 pga |= B43_PHY_PGACTL_LPF; 122 b43_phy_write(dev, B43_PHY_PGACTL, pga); 123 } 124 udelay(21); 125 feedthrough = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); 126 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. */ 130 cond_resched(); 131 132 return feedthrough; 133} 134 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. 139 */ 140static u16 lo_txctl_register_table(struct b43_wldev *dev, 141 u16 * value, u16 * pad_mix_gain) 142{ 143 struct b43_phy *phy = &dev->phy; 144 u16 reg, v, padmix; 145 146 if (phy->type == B43_PHYTYPE_B) { 147 v = 0x30; 148 if (phy->radio_rev <= 5) { 149 reg = 0x43; 150 padmix = 0; 151 } else { 152 reg = 0x52; 153 padmix = 5; 154 } 155 } else { 156 if (phy->rev >= 2 && phy->radio_rev == 8) { 157 reg = 0x43; 158 v = 0x10; 159 padmix = 2; 160 } else { 161 reg = 0x52; 162 v = 0x30; 163 padmix = 5; 164 } 165 } 166 if (value) 167 *value = v; 168 if (pad_mix_gain) 169 *pad_mix_gain = padmix; 170 171 return reg; 172} 173 174static void lo_measure_txctl_values(struct b43_wldev *dev) 175{ 176 struct b43_phy *phy = &dev->phy; 177 struct b43_txpower_lo_control *lo = phy->lo_control; 178 u16 reg, mask; 179 u16 trsw_rx, pga; 180 u16 radio_pctl_reg; 181 182 static const u8 tx_bias_values[] = { 183 0x09, 0x08, 0x0A, 0x01, 0x00, 184 0x02, 0x05, 0x04, 0x06, 185 }; 186 static const u8 tx_magn_values[] = { 187 0x70, 0x40, 188 }; 189 190 if (!has_loopback_gain(phy)) { 191 radio_pctl_reg = 6; 192 trsw_rx = 2; 193 pga = 0; 194 } else { 195 int lb_gain; /* Loopback gain (in dB) */ 196 197 trsw_rx = 0; 198 lb_gain = phy->max_lb_gain / 2; 199 if (lb_gain > 10) { 200 radio_pctl_reg = 0; 201 pga = abs(10 - lb_gain) / 6; 202 pga = clamp_val(pga, 0, 15); 203 } else { 204 int cmp_val; 205 int tmp; 206 207 pga = 0; 208 cmp_val = 0x24; 209 if ((phy->rev >= 2) && 210 (phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) 211 cmp_val = 0x3C; 212 tmp = lb_gain; 213 if ((10 - lb_gain) < cmp_val) 214 tmp = (10 - lb_gain); 215 if (tmp < 0) 216 tmp += 6; 217 else 218 tmp += 3; 219 cmp_val /= 4; 220 tmp /= 4; 221 if (tmp >= cmp_val) 222 radio_pctl_reg = cmp_val; 223 else 224 radio_pctl_reg = tmp; 225 } 226 } 227 b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) 228 & 0xFFF0) | radio_pctl_reg); 229 b43_phy_set_baseband_attenuation(dev, 2); 230 231 reg = lo_txctl_register_table(dev, &mask, NULL); 232 mask = ~mask; 233 b43_radio_write16(dev, reg, b43_radio_read16(dev, reg) 234 & mask); 235 236 if (has_tx_magnification(phy)) { 237 int i, j; 238 int feedthrough; 239 int min_feedth = 0xFFFF; 240 u8 tx_magn, tx_bias; 241 242 for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) { 243 tx_magn = tx_magn_values[i]; 244 b43_radio_write16(dev, 0x52, 245 (b43_radio_read16(dev, 0x52) 246 & 0xFF0F) | tx_magn); 247 for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) { 248 tx_bias = tx_bias_values[j]; 249 b43_radio_write16(dev, 0x52, 250 (b43_radio_read16(dev, 0x52) 251 & 0xFFF0) | tx_bias); 252 feedthrough = 253 lo_measure_feedthrough(dev, 0, pga, 254 trsw_rx); 255 if (feedthrough < min_feedth) { 256 lo->tx_bias = tx_bias; 257 lo->tx_magn = tx_magn; 258 min_feedth = feedthrough; 259 } 260 if (lo->tx_bias == 0) 261 break; 262 } 263 b43_radio_write16(dev, 0x52, 264 (b43_radio_read16(dev, 0x52) 265 & 0xFF00) | lo->tx_bias | lo-> 266 tx_magn); 267 } 268 } else { 269 lo->tx_magn = 0; 270 lo->tx_bias = 0; 271 b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) 272 & 0xFFF0); /* TX bias == 0 */ 273 } 274 lo->txctl_measured_time = jiffies; 275} 276 277static void lo_read_power_vector(struct b43_wldev *dev) 278{ 279 struct b43_phy *phy = &dev->phy; 280 struct b43_txpower_lo_control *lo = phy->lo_control; 281 int i; 282 u64 tmp; 283 u64 power_vector = 0; 284 285 for (i = 0; i < 8; i += 2) { 286 tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); 287 power_vector |= (tmp << (i * 8)); 288 /* Clear the vector on the device. */ 289 b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); 290 } 291 if (power_vector) 292 lo->power_vector = power_vector; 293 lo->pwr_vec_read_time = jiffies; 294} 295 296/* 802.11/LO/GPHY/MeasuringGains */ 297static void lo_measure_gain_values(struct b43_wldev *dev, 298 s16 max_rx_gain, int use_trsw_rx) 299{ 300 struct b43_phy *phy = &dev->phy; 301 u16 tmp; 302 303 if (max_rx_gain < 0) 304 max_rx_gain = 0; 305 306 if (has_loopback_gain(phy)) { 307 int trsw_rx = 0; 308 int trsw_rx_gain; 309 310 if (use_trsw_rx) { 311 trsw_rx_gain = phy->trsw_rx_gain / 2; 312 if (max_rx_gain >= trsw_rx_gain) { 313 trsw_rx_gain = max_rx_gain - trsw_rx_gain; 314 trsw_rx = 0x20; 315 } 316 } else 317 trsw_rx_gain = max_rx_gain; 318 if (trsw_rx_gain < 9) { 319 phy->lna_lod_gain = 0; 320 } else { 321 phy->lna_lod_gain = 1; 322 trsw_rx_gain -= 8; 323 } 324 trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); 325 phy->pga_gain = trsw_rx_gain / 3; 326 if (phy->pga_gain >= 5) { 327 phy->pga_gain -= 5; 328 phy->lna_gain = 2; 329 } else 330 phy->lna_gain = 0; 331 } else { 332 phy->lna_gain = 0; 333 phy->trsw_rx_gain = 0x20; 334 if (max_rx_gain >= 0x14) { 335 phy->lna_lod_gain = 1; 336 phy->pga_gain = 2; 337 } else if (max_rx_gain >= 0x12) { 338 phy->lna_lod_gain = 1; 339 phy->pga_gain = 1; 340 } else if (max_rx_gain >= 0xF) { 341 phy->lna_lod_gain = 1; 342 phy->pga_gain = 0; 343 } else { 344 phy->lna_lod_gain = 0; 345 phy->pga_gain = 0; 346 } 347 } 348 349 tmp = b43_radio_read16(dev, 0x7A); 350 if (phy->lna_lod_gain == 0) 351 tmp &= ~0x0008; 352 else 353 tmp |= 0x0008; 354 b43_radio_write16(dev, 0x7A, tmp); 355} 356 357struct lo_g_saved_values { 358 u8 old_channel; 359 360 /* Core registers */ 361 u16 reg_3F4; 362 u16 reg_3E2; 363 364 /* PHY registers */ 365 u16 phy_lo_mask; 366 u16 phy_extg_01; 367 u16 phy_dacctl_hwpctl; 368 u16 phy_dacctl; 369 u16 phy_cck_14; 370 u16 phy_hpwr_tssictl; 371 u16 phy_analogover; 372 u16 phy_analogoverval; 373 u16 phy_rfover; 374 u16 phy_rfoverval; 375 u16 phy_classctl; 376 u16 phy_cck_3E; 377 u16 phy_crs0; 378 u16 phy_pgactl; 379 u16 phy_cck_2A; 380 u16 phy_syncctl; 381 u16 phy_cck_30; 382 u16 phy_cck_06; 383 384 /* Radio registers */ 385 u16 radio_43; 386 u16 radio_7A; 387 u16 radio_52; 388}; 389 390static void lo_measure_setup(struct b43_wldev *dev, 391 struct lo_g_saved_values *sav) 392{ 393 struct ssb_sprom *sprom = &dev->dev->bus->sprom; 394 struct b43_phy *phy = &dev->phy; 395 struct b43_txpower_lo_control *lo = phy->lo_control; 396 u16 tmp; 397 398 if (b43_has_hardware_pctl(phy)) { 399 sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); 400 sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); 401 sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); 402 sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14)); 403 sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL); 404 405 b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, 406 b43_phy_read(dev, B43_PHY_HPWR_TSSICTL) 407 | 0x100); 408 b43_phy_write(dev, B43_PHY_EXTG(0x01), 409 b43_phy_read(dev, B43_PHY_EXTG(0x01)) 410 | 0x40); 411 b43_phy_write(dev, B43_PHY_DACCTL, 412 b43_phy_read(dev, B43_PHY_DACCTL) 413 | 0x40); 414 b43_phy_write(dev, B43_PHY_CCK(0x14), 415 b43_phy_read(dev, B43_PHY_CCK(0x14)) 416 | 0x200); 417 } 418 if (phy->type == B43_PHYTYPE_B && 419 phy->radio_ver == 0x2050 && phy->radio_rev < 6) { 420 b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); 421 b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); 422 } 423 if (phy->rev >= 2) { 424 sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); 425 sav->phy_analogoverval = 426 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); 427 sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); 428 sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); 429 sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); 430 sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E)); 431 sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); 432 433 b43_phy_write(dev, B43_PHY_CLASSCTL, 434 b43_phy_read(dev, B43_PHY_CLASSCTL) 435 & 0xFFFC); 436 b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) 437 & 0x7FFF); 438 b43_phy_write(dev, B43_PHY_ANALOGOVER, 439 b43_phy_read(dev, B43_PHY_ANALOGOVER) 440 | 0x0003); 441 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 442 b43_phy_read(dev, B43_PHY_ANALOGOVERVAL) 443 & 0xFFFC); 444 if (phy->type == B43_PHYTYPE_G) { 445 if ((phy->rev >= 7) && 446 (sprom->boardflags_lo & B43_BFL_EXTLNA)) { 447 b43_phy_write(dev, B43_PHY_RFOVER, 0x933); 448 } else { 449 b43_phy_write(dev, B43_PHY_RFOVER, 0x133); 450 } 451 } else { 452 b43_phy_write(dev, B43_PHY_RFOVER, 0); 453 } 454 b43_phy_write(dev, B43_PHY_CCK(0x3E), 0); 455 } 456 sav->reg_3F4 = b43_read16(dev, 0x3F4); 457 sav->reg_3E2 = b43_read16(dev, 0x3E2); 458 sav->radio_43 = b43_radio_read16(dev, 0x43); 459 sav->radio_7A = b43_radio_read16(dev, 0x7A); 460 sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); 461 sav->phy_cck_2A = b43_phy_read(dev, B43_PHY_CCK(0x2A)); 462 sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); 463 sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL); 464 465 if (!has_tx_magnification(phy)) { 466 sav->radio_52 = b43_radio_read16(dev, 0x52); 467 sav->radio_52 &= 0x00F0; 468 } 469 if (phy->type == B43_PHYTYPE_B) { 470 sav->phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); 471 sav->phy_cck_06 = b43_phy_read(dev, B43_PHY_CCK(0x06)); 472 b43_phy_write(dev, B43_PHY_CCK(0x30), 0x00FF); 473 b43_phy_write(dev, B43_PHY_CCK(0x06), 0x3F3F); 474 } else { 475 b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) 476 | 0x8000); 477 } 478 b43_write16(dev, 0x3F4, b43_read16(dev, 0x3F4) 479 & 0xF000); 480 481 tmp = 482 (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_CCK(0x2E); 483 b43_phy_write(dev, tmp, 0x007F); 484 485 tmp = sav->phy_syncctl; 486 b43_phy_write(dev, B43_PHY_SYNCCTL, tmp & 0xFF7F); 487 tmp = sav->radio_7A; 488 b43_radio_write16(dev, 0x007A, tmp & 0xFFF0); 489 490 b43_phy_write(dev, B43_PHY_CCK(0x2A), 0x8A3); 491 if (phy->type == B43_PHYTYPE_G || 492 (phy->type == B43_PHYTYPE_B && 493 phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) { 494 b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1003); 495 } else 496 b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); 497 if (phy->rev >= 2) 498 b43_dummy_transmission(dev); 499 b43_radio_selectchannel(dev, 6, 0); 500 b43_radio_read16(dev, 0x51); /* dummy read */ 501 if (phy->type == B43_PHYTYPE_G) 502 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); 503 504 /* Re-measure the txctl values, if needed. */ 505 if (time_before(lo->txctl_measured_time, 506 jiffies - B43_LO_TXCTL_EXPIRE)) 507 lo_measure_txctl_values(dev); 508 509 if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { 510 b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); 511 } else { 512 if (phy->type == B43_PHYTYPE_B) 513 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); 514 else 515 b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); 516 } 517} 518 519static void lo_measure_restore(struct b43_wldev *dev, 520 struct lo_g_saved_values *sav) 521{ 522 struct b43_phy *phy = &dev->phy; 523 u16 tmp; 524 525 if (phy->rev >= 2) { 526 b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); 527 tmp = (phy->pga_gain << 8); 528 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); 529 udelay(5); 530 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); 531 udelay(2); 532 b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); 533 } else { 534 tmp = (phy->pga_gain | 0xEFA0); 535 b43_phy_write(dev, B43_PHY_PGACTL, tmp); 536 } 537 if (phy->type == B43_PHYTYPE_G) { 538 if (phy->rev >= 3) 539 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); 540 else 541 b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); 542 if (phy->rev >= 2) 543 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0202); 544 else 545 b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0101); 546 } 547 b43_write16(dev, 0x3F4, sav->reg_3F4); 548 b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl); 549 b43_phy_write(dev, B43_PHY_CCK(0x2A), sav->phy_cck_2A); 550 b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl); 551 b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl); 552 b43_radio_write16(dev, 0x43, sav->radio_43); 553 b43_radio_write16(dev, 0x7A, sav->radio_7A); 554 if (!has_tx_magnification(phy)) { 555 tmp = sav->radio_52; 556 b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) 557 & 0xFF0F) | tmp); 558 } 559 b43_write16(dev, 0x3E2, sav->reg_3E2); 560 if (phy->type == B43_PHYTYPE_B && 561 phy->radio_ver == 0x2050 && phy->radio_rev <= 5) { 562 b43_phy_write(dev, B43_PHY_CCK(0x30), sav->phy_cck_30); 563 b43_phy_write(dev, B43_PHY_CCK(0x06), sav->phy_cck_06); 564 } 565 if (phy->rev >= 2) { 566 b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover); 567 b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 568 sav->phy_analogoverval); 569 b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl); 570 b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover); 571 b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval); 572 b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); 573 b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); 574 } 575 if (b43_has_hardware_pctl(phy)) { 576 tmp = (sav->phy_lo_mask & 0xBFFF); 577 b43_phy_write(dev, B43_PHY_LO_MASK, tmp); 578 b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); 579 b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl); 580 b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); 581 b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); 582 } 583 b43_radio_selectchannel(dev, sav->old_channel, 1); 584} 585 586struct b43_lo_g_statemachine { 587 int current_state; 588 int nr_measured; 589 int state_val_multiplier; 590 u16 lowest_feedth; 591 struct b43_loctl min_loctl; 592}; 593 594/* Loop over each possible value in this state. */ 595static int lo_probe_possible_loctls(struct b43_wldev *dev, 596 struct b43_loctl *probe_loctl, 597 struct b43_lo_g_statemachine *d) 598{ 599 struct b43_phy *phy = &dev->phy; 600 struct b43_loctl test_loctl; 601 struct b43_loctl orig_loctl; 602 struct b43_loctl prev_loctl = { 603 .i = -100, 604 .q = -100, 605 }; 606 int i; 607 int begin, end; 608 int found_lower = 0; 609 u16 feedth; 610 611 static const struct b43_loctl modifiers[] = { 612 {.i = 1,.q = 1,}, 613 {.i = 1,.q = 0,}, 614 {.i = 1,.q = -1,}, 615 {.i = 0,.q = -1,}, 616 {.i = -1,.q = -1,}, 617 {.i = -1,.q = 0,}, 618 {.i = -1,.q = 1,}, 619 {.i = 0,.q = 1,}, 620 }; 621 622 if (d->current_state == 0) { 623 begin = 1; 624 end = 8; 625 } else if (d->current_state % 2 == 0) { 626 begin = d->current_state - 1; 627 end = d->current_state + 1; 628 } else { 629 begin = d->current_state - 2; 630 end = d->current_state + 2; 631 } 632 if (begin < 1) 633 begin += 8; 634 if (end > 8) 635 end -= 8; 636 637 memcpy(&orig_loctl, probe_loctl, sizeof(struct b43_loctl)); 638 i = begin; 639 d->current_state = i; 640 while (1) { 641 B43_WARN_ON(!(i >= 1 && i <= 8)); 642 memcpy(&test_loctl, &orig_loctl, sizeof(struct b43_loctl)); 643 test_loctl.i += modifiers[i - 1].i * d->state_val_multiplier; 644 test_loctl.q += modifiers[i - 1].q * d->state_val_multiplier; 645 if ((test_loctl.i != prev_loctl.i || 646 test_loctl.q != prev_loctl.q) && 647 (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { 648 b43_lo_write(dev, &test_loctl); 649 feedth = lo_measure_feedthrough(dev, phy->lna_gain, 650 phy->pga_gain, 651 phy->trsw_rx_gain); 652 if (feedth < d->lowest_feedth) { 653 memcpy(probe_loctl, &test_loctl, 654 sizeof(struct b43_loctl)); 655 found_lower = 1; 656 d->lowest_feedth = feedth; 657 if ((d->nr_measured < 2) && 658 !has_loopback_gain(phy)) 659 break; 660 } 661 } 662 memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl)); 663 if (i == end) 664 break; 665 if (i == 8) 666 i = 1; 667 else 668 i++; 669 d->current_state = i; 670 } 671 672 return found_lower; 673} 674 675static void lo_probe_loctls_statemachine(struct b43_wldev *dev, 676 struct b43_loctl *loctl, 677 int *max_rx_gain) 678{ 679 struct b43_phy *phy = &dev->phy; 680 struct b43_lo_g_statemachine d; 681 u16 feedth; 682 int found_lower; 683 struct b43_loctl probe_loctl; 684 int max_repeat = 1, repeat_cnt = 0; 685 686 d.nr_measured = 0; 687 d.state_val_multiplier = 1; 688 if (has_loopback_gain(phy)) 689 d.state_val_multiplier = 3; 690 691 memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); 692 if (has_loopback_gain(phy)) 693 max_repeat = 4; 694 do { 695 b43_lo_write(dev, &d.min_loctl); 696 feedth = lo_measure_feedthrough(dev, phy->lna_gain, 697 phy->pga_gain, 698 phy->trsw_rx_gain); 699 if (feedth < 0x258) { 700 if (feedth >= 0x12C) 701 *max_rx_gain += 6; 702 else 703 *max_rx_gain += 3; 704 feedth = lo_measure_feedthrough(dev, phy->lna_gain, 705 phy->pga_gain, 706 phy->trsw_rx_gain); 707 } 708 d.lowest_feedth = feedth; 709 710 d.current_state = 0; 711 do { 712 B43_WARN_ON(! 713 (d.current_state >= 0 714 && d.current_state <= 8)); 715 memcpy(&probe_loctl, &d.min_loctl, 716 sizeof(struct b43_loctl)); 717 found_lower = 718 lo_probe_possible_loctls(dev, &probe_loctl, &d); 719 if (!found_lower) 720 break; 721 if ((probe_loctl.i == d.min_loctl.i) && 722 (probe_loctl.q == d.min_loctl.q)) 723 break; 724 memcpy(&d.min_loctl, &probe_loctl, 725 sizeof(struct b43_loctl)); 726 d.nr_measured++; 727 } while (d.nr_measured < 24); 728 memcpy(loctl, &d.min_loctl, sizeof(struct b43_loctl)); 729 730 if (has_loopback_gain(phy)) { 731 if (d.lowest_feedth > 0x1194) 732 *max_rx_gain -= 6; 733 else if (d.lowest_feedth < 0x5DC) 734 *max_rx_gain += 3; 735 if (repeat_cnt == 0) { 736 if (d.lowest_feedth <= 0x5DC) { 737 d.state_val_multiplier = 1; 738 repeat_cnt++; 739 } else 740 d.state_val_multiplier = 2; 741 } else if (repeat_cnt == 2) 742 d.state_val_multiplier = 1; 743 } 744 lo_measure_gain_values(dev, *max_rx_gain, 745 has_loopback_gain(phy)); 746 } while (++repeat_cnt < max_repeat); 747} 748 749static 750struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, 751 const struct b43_bbatt *bbatt, 752 const struct b43_rfatt *rfatt) 753{ 754 struct b43_phy *phy = &dev->phy; 755 struct b43_loctl loctl = { 756 .i = 0, 757 .q = 0, 758 }; 759 int max_rx_gain; 760 struct b43_lo_calib *cal; 761 struct lo_g_saved_values uninitialized_var(saved_regs); 762 /* Values from the "TXCTL Register and Value Table" */ 763 u16 txctl_reg; 764 u16 txctl_value; 765 u16 pad_mix_gain; 766 767 saved_regs.old_channel = phy->channel; 768 b43_mac_suspend(dev); 769 lo_measure_setup(dev, &saved_regs); 770 771 txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); 772 773 b43_radio_write16(dev, 0x43, 774 (b43_radio_read16(dev, 0x43) & 0xFFF0) 775 | rfatt->att); 776 b43_radio_write16(dev, txctl_reg, 777 (b43_radio_read16(dev, txctl_reg) & ~txctl_value) 778 | (rfatt->with_padmix) ? txctl_value : 0); 779 780 max_rx_gain = rfatt->att * 2; 781 max_rx_gain += bbatt->att / 2; 782 if (rfatt->with_padmix) 783 max_rx_gain -= pad_mix_gain; 784 if (has_loopback_gain(phy)) 785 max_rx_gain += phy->max_lb_gain; 786 lo_measure_gain_values(dev, max_rx_gain, 787 has_loopback_gain(phy)); 788 789 b43_phy_set_baseband_attenuation(dev, bbatt->att); 790 lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); 791 792 lo_measure_restore(dev, &saved_regs); 793 b43_mac_enable(dev); 794 795 if (b43_debug(dev, B43_DBG_LO)) { 796 b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) " 797 "=> I=%d Q=%d\n", 798 bbatt->att, rfatt->att, rfatt->with_padmix, 799 loctl.i, loctl.q); 800 } 801 802 cal = kmalloc(sizeof(*cal), GFP_KERNEL); 803 if (!cal) { 804 b43warn(dev->wl, "LO calib: out of memory\n"); 805 return NULL; 806 } 807 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); 808 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); 809 memcpy(&cal->ctl, &loctl, sizeof(loctl)); 810 cal->calib_time = jiffies; 811 INIT_LIST_HEAD(&cal->list); 812 813 return cal; 814} 815 816/* Get a calibrated LO setting for the given attenuation values. 817 * Might return a NULL pointer under OOM! */ 818static 819struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, 820 const struct b43_bbatt *bbatt, 821 const struct b43_rfatt *rfatt) 822{ 823 struct b43_txpower_lo_control *lo = dev->phy.lo_control; 824 struct b43_lo_calib *c; 825 826 c = b43_find_lo_calib(lo, bbatt, rfatt); 827 if (c) 828 return c; 829 /* Not in the list of calibrated LO settings. 830 * Calibrate it now. */ 831 c = b43_calibrate_lo_setting(dev, bbatt, rfatt); 832 if (!c) 833 return NULL; 834 list_add(&c->list, &lo->calib_list); 835 836 return c; 837} 838 839void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) 840{ 841 struct b43_phy *phy = &dev->phy; 842 struct b43_txpower_lo_control *lo = phy->lo_control; 843 int i; 844 int rf_offset, bb_offset; 845 const struct b43_rfatt *rfatt; 846 const struct b43_bbatt *bbatt; 847 u64 power_vector; 848 bool table_changed = 0; 849 850 BUILD_BUG_ON(B43_DC_LT_SIZE != 32); 851 B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64); 852 853 power_vector = lo->power_vector; 854 if (!update_all && !power_vector) 855 return; /* Nothing to do. */ 856 857 /* Suspend the MAC now to avoid continuous suspend/enable 858 * cycles in the loop. */ 859 b43_mac_suspend(dev); 860 861 for (i = 0; i < B43_DC_LT_SIZE * 2; i++) { 862 struct b43_lo_calib *cal; 863 int idx; 864 u16 val; 865 866 if (!update_all && !(power_vector & (((u64)1ULL) << i))) 867 continue; 868 /* Update the table entry for this power_vector bit. 869 * The table rows are RFatt entries and columns are BBatt. */ 870 bb_offset = i / lo->rfatt_list.len; 871 rf_offset = i % lo->rfatt_list.len; 872 bbatt = &(lo->bbatt_list.list[bb_offset]); 873 rfatt = &(lo->rfatt_list.list[rf_offset]); 874 875 cal = b43_calibrate_lo_setting(dev, bbatt, rfatt); 876 if (!cal) { 877 b43warn(dev->wl, "LO: Could not " 878 "calibrate DC table entry\n"); 879 continue; 880 } 881 /*FIXME: Is Q really in the low nibble? */ 882 val = (u8)(cal->ctl.q); 883 val |= ((u8)(cal->ctl.i)) << 4; 884 kfree(cal); 885 886 /* Get the index into the hardware DC LT. */ 887 idx = i / 2; 888 /* Change the table in memory. */ 889 if (i % 2) { 890 /* Change the high byte. */ 891 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF) 892 | ((val & 0x00FF) << 8); 893 } else { 894 /* Change the low byte. */ 895 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00) 896 | (val & 0x00FF); 897 } 898 table_changed = 1; 899 } 900 if (table_changed) { 901 /* The table changed in memory. Update the hardware table. */ 902 for (i = 0; i < B43_DC_LT_SIZE; i++) 903 b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]); 904 } 905 b43_mac_enable(dev); 906} 907 908/* Fixup the RF attenuation value for the case where we are 909 * using the PAD mixer. */ 910static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) 911{ 912 if (!rf->with_padmix) 913 return; 914 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) 915 rf->att = 4; 916} 917 918void b43_lo_g_adjust(struct b43_wldev *dev) 919{ 920 struct b43_phy *phy = &dev->phy; 921 struct b43_lo_calib *cal; 922 struct b43_rfatt rf; 923 924 memcpy(&rf, &phy->rfatt, sizeof(rf)); 925 b43_lo_fixup_rfatt(&rf); 926 927 cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf); 928 if (!cal) 929 return; 930 b43_lo_write(dev, &cal->ctl); 931} 932 933void b43_lo_g_adjust_to(struct b43_wldev *dev, 934 u16 rfatt, u16 bbatt, u16 tx_control) 935{ 936 struct b43_rfatt rf; 937 struct b43_bbatt bb; 938 struct b43_lo_calib *cal; 939 940 memset(&rf, 0, sizeof(rf)); 941 memset(&bb, 0, sizeof(bb)); 942 rf.att = rfatt; 943 bb.att = bbatt; 944 b43_lo_fixup_rfatt(&rf); 945 cal = b43_get_calib_lo_settings(dev, &bb, &rf); 946 if (!cal) 947 return; 948 b43_lo_write(dev, &cal->ctl); 949} 950 951/* Periodic LO maintanance work */ 952void b43_lo_g_maintanance_work(struct b43_wldev *dev) 953{ 954 struct b43_phy *phy = &dev->phy; 955 struct b43_txpower_lo_control *lo = phy->lo_control; 956 unsigned long now; 957 unsigned long expire; 958 struct b43_lo_calib *cal, *tmp; 959 bool current_item_expired = 0; 960 bool hwpctl; 961 962 if (!lo) 963 return; 964 now = jiffies; 965 hwpctl = b43_has_hardware_pctl(phy); 966 967 if (hwpctl) { 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); 973 } 974 //FIXME Recalc the whole DC table from time to time? 975 } 976 977 if (hwpctl) 978 return; 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)) 984 continue; 985 /* This item expired. */ 986 if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && 987 b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) { 988 B43_WARN_ON(current_item_expired); 989 current_item_expired = 1; 990 } 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); 997 } 998 list_del(&cal->list); 999 kfree(cal); 1000 } 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, &phy->bbatt, &phy->rfatt); 1006 if (cal) { 1007 list_add(&cal->list, &lo->calib_list); 1008 b43_lo_write(dev, &cal->ctl); 1009 } else 1010 b43warn(dev->wl, "Failed to recalibrate current LO setting\n"); 1011 } 1012} 1013 1014void b43_lo_g_cleanup(struct b43_wldev *dev) 1015{ 1016 struct b43_txpower_lo_control *lo = dev->phy.lo_control; 1017 struct b43_lo_calib *cal, *tmp; 1018 1019 if (!lo) 1020 return; 1021 list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { 1022 list_del(&cal->list); 1023 kfree(cal); 1024 } 1025} 1026 1027/* LO Initialization */ 1028void b43_lo_g_init(struct b43_wldev *dev) 1029{ 1030 struct b43_phy *phy = &dev->phy; 1031 1032 if (b43_has_hardware_pctl(phy)) { 1033 lo_read_power_vector(dev); 1034 b43_gphy_dc_lt_init(dev, 1); 1035 } 1036}