diff options
| -rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 776d0082ef1c..d08feffdce68 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
| @@ -464,6 +464,105 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, | |||
| 464 | } | 464 | } |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ | ||
| 468 | static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) | ||
| 469 | { | ||
| 470 | int i; | ||
| 471 | s32 iq; | ||
| 472 | u32 ii; | ||
| 473 | u32 qq; | ||
| 474 | int iq_nbits, qq_nbits; | ||
| 475 | int arsh, brsh; | ||
| 476 | u16 tmp, a, b; | ||
| 477 | |||
| 478 | struct nphy_iq_est est; | ||
| 479 | struct b43_phy_n_iq_comp old; | ||
| 480 | struct b43_phy_n_iq_comp new = { }; | ||
| 481 | bool error = false; | ||
| 482 | |||
| 483 | if (mask == 0) | ||
| 484 | return; | ||
| 485 | |||
| 486 | b43_nphy_rx_iq_coeffs(dev, false, &old); | ||
| 487 | b43_nphy_rx_iq_coeffs(dev, true, &new); | ||
| 488 | b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); | ||
| 489 | new = old; | ||
| 490 | |||
| 491 | for (i = 0; i < 2; i++) { | ||
| 492 | if (i == 0 && (mask & 1)) { | ||
| 493 | iq = est.iq0_prod; | ||
| 494 | ii = est.i0_pwr; | ||
| 495 | qq = est.q0_pwr; | ||
| 496 | } else if (i == 1 && (mask & 2)) { | ||
| 497 | iq = est.iq1_prod; | ||
| 498 | ii = est.i1_pwr; | ||
| 499 | qq = est.q1_pwr; | ||
| 500 | } else { | ||
| 501 | B43_WARN_ON(1); | ||
| 502 | continue; | ||
| 503 | } | ||
| 504 | |||
| 505 | if (ii + qq < 2) { | ||
| 506 | error = true; | ||
| 507 | break; | ||
| 508 | } | ||
| 509 | |||
| 510 | iq_nbits = fls(abs(iq)); | ||
| 511 | qq_nbits = fls(qq); | ||
| 512 | |||
| 513 | arsh = iq_nbits - 20; | ||
| 514 | if (arsh >= 0) { | ||
| 515 | a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); | ||
| 516 | tmp = ii >> arsh; | ||
| 517 | } else { | ||
| 518 | a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); | ||
| 519 | tmp = ii << -arsh; | ||
| 520 | } | ||
| 521 | if (tmp == 0) { | ||
| 522 | error = true; | ||
| 523 | break; | ||
| 524 | } | ||
| 525 | a /= tmp; | ||
| 526 | |||
| 527 | brsh = qq_nbits - 11; | ||
| 528 | if (brsh >= 0) { | ||
| 529 | b = (qq << (31 - qq_nbits)); | ||
| 530 | tmp = ii >> brsh; | ||
| 531 | } else { | ||
| 532 | b = (qq << (31 - qq_nbits)); | ||
| 533 | tmp = ii << -brsh; | ||
| 534 | } | ||
| 535 | if (tmp == 0) { | ||
| 536 | error = true; | ||
| 537 | break; | ||
| 538 | } | ||
| 539 | b = int_sqrt(b / tmp - a * a) - (1 << 10); | ||
| 540 | |||
| 541 | if (i == 0 && (mask & 0x1)) { | ||
| 542 | if (dev->phy.rev >= 3) { | ||
| 543 | new.a0 = a & 0x3FF; | ||
| 544 | new.b0 = b & 0x3FF; | ||
| 545 | } else { | ||
| 546 | new.a0 = b & 0x3FF; | ||
| 547 | new.b0 = a & 0x3FF; | ||
| 548 | } | ||
| 549 | } else if (i == 1 && (mask & 0x2)) { | ||
| 550 | if (dev->phy.rev >= 3) { | ||
| 551 | new.a1 = a & 0x3FF; | ||
| 552 | new.b1 = b & 0x3FF; | ||
| 553 | } else { | ||
| 554 | new.a1 = b & 0x3FF; | ||
| 555 | new.b1 = a & 0x3FF; | ||
| 556 | } | ||
| 557 | } | ||
| 558 | } | ||
| 559 | |||
| 560 | if (error) | ||
| 561 | new = old; | ||
| 562 | |||
| 563 | b43_nphy_rx_iq_coeffs(dev, true, &new); | ||
| 564 | } | ||
| 565 | |||
| 467 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ | 566 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ |
| 468 | static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) | 567 | static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) |
| 469 | { | 568 | { |
