diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2012-01-02 13:31:22 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-24 14:06:05 -0500 |
commit | d3fd8bf77affcbf80bb8297d177e17ad0b61abc8 (patch) | |
tree | a86c6cf34526395bc9ba9a3d34bc55601837f76f /drivers | |
parent | 5056635c10151970d87ae256b7f52f056291799e (diff) |
b43: N-PHY: implement TX power control setup
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 217 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.h | 1 |
2 files changed, 217 insertions, 1 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 9530f12c0282..fbbdbdad1019 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -2420,6 +2420,221 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
2420 | nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; | 2420 | nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; |
2421 | } | 2421 | } |
2422 | 2422 | ||
2423 | /* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ | ||
2424 | static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev) | ||
2425 | { | ||
2426 | struct b43_phy_n *nphy = dev->phy.n; | ||
2427 | |||
2428 | u8 idx, delta; | ||
2429 | u8 i, stf_mode; | ||
2430 | |||
2431 | for (i = 0; i < 4; i++) | ||
2432 | nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; | ||
2433 | |||
2434 | for (stf_mode = 0; stf_mode < 4; stf_mode++) { | ||
2435 | delta = 0; | ||
2436 | switch (stf_mode) { | ||
2437 | case 0: | ||
2438 | if (dev->phy.is_40mhz && dev->phy.rev >= 5) { | ||
2439 | idx = 68; | ||
2440 | } else { | ||
2441 | delta = 1; | ||
2442 | idx = dev->phy.is_40mhz ? 52 : 4; | ||
2443 | } | ||
2444 | break; | ||
2445 | case 1: | ||
2446 | idx = dev->phy.is_40mhz ? 76 : 28; | ||
2447 | break; | ||
2448 | case 2: | ||
2449 | idx = dev->phy.is_40mhz ? 84 : 36; | ||
2450 | break; | ||
2451 | case 3: | ||
2452 | idx = dev->phy.is_40mhz ? 92 : 44; | ||
2453 | break; | ||
2454 | } | ||
2455 | |||
2456 | for (i = 0; i < 20; i++) { | ||
2457 | nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = | ||
2458 | nphy->tx_power_offset[idx]; | ||
2459 | if (i == 0) | ||
2460 | idx += delta; | ||
2461 | if (i == 14) | ||
2462 | idx += 1 - delta; | ||
2463 | if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || | ||
2464 | i == 13) | ||
2465 | idx += 1; | ||
2466 | } | ||
2467 | } | ||
2468 | } | ||
2469 | |||
2470 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ | ||
2471 | static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) | ||
2472 | { | ||
2473 | struct b43_phy_n *nphy = dev->phy.n; | ||
2474 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
2475 | |||
2476 | s16 a1[2], b0[2], b1[2]; | ||
2477 | u8 idle[2]; | ||
2478 | s8 target[2]; | ||
2479 | s32 num, den, pwr; | ||
2480 | u32 regval[64]; | ||
2481 | |||
2482 | u16 freq = dev->phy.channel_freq; | ||
2483 | u16 tmp; | ||
2484 | u16 r; /* routing */ | ||
2485 | u8 i, c; | ||
2486 | |||
2487 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { | ||
2488 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); | ||
2489 | b43_read32(dev, B43_MMIO_MACCTL); | ||
2490 | udelay(1); | ||
2491 | } | ||
2492 | |||
2493 | if (nphy->hang_avoid) | ||
2494 | b43_nphy_stay_in_carrier_search(dev, true); | ||
2495 | |||
2496 | b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN); | ||
2497 | if (dev->phy.rev >= 3) | ||
2498 | b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, | ||
2499 | ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); | ||
2500 | else | ||
2501 | b43_phy_set(dev, B43_NPHY_TXPCTL_CMD, | ||
2502 | B43_NPHY_TXPCTL_CMD_PCTLEN); | ||
2503 | |||
2504 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) | ||
2505 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); | ||
2506 | |||
2507 | if (sprom->revision < 4) { | ||
2508 | idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; | ||
2509 | idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; | ||
2510 | target[0] = target[1] = 52; | ||
2511 | a1[0] = a1[1] = -424; | ||
2512 | b0[0] = b0[1] = 5612; | ||
2513 | b1[0] = b1[1] = -1393; | ||
2514 | } else { | ||
2515 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2516 | for (c = 0; c < 2; c++) { | ||
2517 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; | ||
2518 | target[c] = sprom->core_pwr_info[c].maxpwr_2g; | ||
2519 | a1[c] = sprom->core_pwr_info[c].pa_2g[0]; | ||
2520 | b0[c] = sprom->core_pwr_info[c].pa_2g[1]; | ||
2521 | b1[c] = sprom->core_pwr_info[c].pa_2g[2]; | ||
2522 | } | ||
2523 | } else if (freq >= 4900 && freq < 5100) { | ||
2524 | for (c = 0; c < 2; c++) { | ||
2525 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2526 | target[c] = sprom->core_pwr_info[c].maxpwr_5gl; | ||
2527 | a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; | ||
2528 | b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; | ||
2529 | b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; | ||
2530 | } | ||
2531 | } else if (freq >= 5100 && freq < 5500) { | ||
2532 | for (c = 0; c < 2; c++) { | ||
2533 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2534 | target[c] = sprom->core_pwr_info[c].maxpwr_5g; | ||
2535 | a1[c] = sprom->core_pwr_info[c].pa_5g[0]; | ||
2536 | b0[c] = sprom->core_pwr_info[c].pa_5g[1]; | ||
2537 | b1[c] = sprom->core_pwr_info[c].pa_5g[2]; | ||
2538 | } | ||
2539 | } else if (freq >= 5500) { | ||
2540 | for (c = 0; c < 2; c++) { | ||
2541 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2542 | target[c] = sprom->core_pwr_info[c].maxpwr_5gh; | ||
2543 | a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; | ||
2544 | b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; | ||
2545 | b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; | ||
2546 | } | ||
2547 | } else { | ||
2548 | idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; | ||
2549 | idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; | ||
2550 | target[0] = target[1] = 52; | ||
2551 | a1[0] = a1[1] = -424; | ||
2552 | b0[0] = b0[1] = 5612; | ||
2553 | b1[0] = b1[1] = -1393; | ||
2554 | } | ||
2555 | } | ||
2556 | /* target[0] = target[1] = nphy->tx_power_max; */ | ||
2557 | |||
2558 | if (dev->phy.rev >= 3) { | ||
2559 | if (sprom->fem.ghz2.tssipos) | ||
2560 | b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000); | ||
2561 | if (dev->phy.rev >= 7) { | ||
2562 | for (c = 0; c < 2; c++) { | ||
2563 | r = c ? 0x190 : 0x170; | ||
2564 | if (b43_nphy_ipa(dev)) | ||
2565 | b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC); | ||
2566 | } | ||
2567 | } else { | ||
2568 | if (b43_nphy_ipa(dev)) { | ||
2569 | tmp = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; | ||
2570 | b43_radio_write(dev, | ||
2571 | B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); | ||
2572 | b43_radio_write(dev, | ||
2573 | B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); | ||
2574 | } else { | ||
2575 | b43_radio_write(dev, | ||
2576 | B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); | ||
2577 | b43_radio_write(dev, | ||
2578 | B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); | ||
2579 | } | ||
2580 | } | ||
2581 | } | ||
2582 | |||
2583 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { | ||
2584 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); | ||
2585 | b43_read32(dev, B43_MMIO_MACCTL); | ||
2586 | udelay(1); | ||
2587 | } | ||
2588 | |||
2589 | if (dev->phy.rev >= 7) { | ||
2590 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | ||
2591 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); | ||
2592 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | ||
2593 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19); | ||
2594 | } else { | ||
2595 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | ||
2596 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x40); | ||
2597 | if (dev->phy.rev > 1) | ||
2598 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | ||
2599 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40); | ||
2600 | } | ||
2601 | |||
2602 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) | ||
2603 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); | ||
2604 | |||
2605 | b43_phy_write(dev, B43_NPHY_TXPCTL_N, | ||
2606 | 0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT | | ||
2607 | 3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT); | ||
2608 | b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI, | ||
2609 | idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT | | ||
2610 | idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT | | ||
2611 | B43_NPHY_TXPCTL_ITSSI_BINF); | ||
2612 | b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR, | ||
2613 | target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT | | ||
2614 | target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT); | ||
2615 | |||
2616 | for (c = 0; c < 2; c++) { | ||
2617 | for (i = 0; i < 64; i++) { | ||
2618 | num = 8 * (16 * b0[c] + b1[c] * i); | ||
2619 | den = 32768 + a1[c] * i; | ||
2620 | pwr = max((4 * num + den / 2) / den, -8); | ||
2621 | if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1))) | ||
2622 | pwr = max(pwr, target[c] + 1); | ||
2623 | regval[i] = pwr; | ||
2624 | } | ||
2625 | b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval); | ||
2626 | } | ||
2627 | |||
2628 | b43_nphy_tx_prepare_adjusted_power_table(dev); | ||
2629 | /* | ||
2630 | b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); | ||
2631 | b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); | ||
2632 | */ | ||
2633 | |||
2634 | if (nphy->hang_avoid) | ||
2635 | b43_nphy_stay_in_carrier_search(dev, false); | ||
2636 | } | ||
2637 | |||
2423 | static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) | 2638 | static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) |
2424 | { | 2639 | { |
2425 | struct b43_phy *phy = &dev->phy; | 2640 | struct b43_phy *phy = &dev->phy; |
@@ -4107,7 +4322,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
4107 | b43_nphy_tx_power_ctrl(dev, false); | 4322 | b43_nphy_tx_power_ctrl(dev, false); |
4108 | b43_nphy_tx_power_fix(dev); | 4323 | b43_nphy_tx_power_fix(dev); |
4109 | b43_nphy_tx_power_ctl_idle_tssi(dev); | 4324 | b43_nphy_tx_power_ctl_idle_tssi(dev); |
4110 | /* TODO N PHY TX Power Control Setup */ | 4325 | b43_nphy_tx_power_ctl_setup(dev); |
4111 | b43_nphy_tx_gain_table_upload(dev); | 4326 | b43_nphy_tx_gain_table_upload(dev); |
4112 | 4327 | ||
4113 | if (nphy->phyrxchain != 3) | 4328 | if (nphy->phyrxchain != 3) |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 5de8f74cc02f..fd12b386fea1 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -798,6 +798,7 @@ struct b43_phy_n { | |||
798 | bool txpwrctrl; | 798 | bool txpwrctrl; |
799 | bool pwg_gain_5ghz; | 799 | bool pwg_gain_5ghz; |
800 | u8 tx_pwr_idx[2]; | 800 | u8 tx_pwr_idx[2]; |
801 | s8 tx_power_offset[101]; | ||
801 | u16 adj_pwr_tbl[84]; | 802 | u16 adj_pwr_tbl[84]; |
802 | u16 txcal_bbmult; | 803 | u16 txcal_bbmult; |
803 | u16 txiqlocal_bestc[11]; | 804 | u16 txiqlocal_bestc[11]; |