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