| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010 Atheros Communications Inc. | 2 * Copyright (c) 2010 Atheros Communications Inc. |
| 3 * | 3 * |
| 4 * Permission to use, copy, modify, and/or distribute this software for any | 4 * Permission to use, copy, modify, and/or distribute this software for any |
| 5 * purpose with or without fee is hereby granted, provided that the above | 5 * purpose with or without fee is hereby granted, provided that the above |
| 6 * copyright notice and this permission notice appear in all copies. | 6 * copyright notice and this permission notice appear in all copies. |
| 7 * | 7 * |
| 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 15 */ | 15 */ |
| 16 | 16 |
| 17 #include "hw.h" | 17 #include "hw.h" |
| 18 #include "ar9003_phy.h" | 18 #include "ar9003_phy.h" |
| 19 | 19 |
| 20 void ar9003_paprd_enable(struct ath_hw *ah, bool val) | 20 void ar9003_paprd_enable(struct ath_hw *ah, bool val) |
| 21 { | 21 { |
| 22 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 23 struct ath9k_channel *chan = ah->curchan; |
| 24 |
| 25 if (val) { |
| 26 ah->paprd_table_write_done = true; |
| 27 |
| 28 ah->eep_ops->set_txpower(ah, chan, |
| 29 ath9k_regd_get_ctl(regulatory, chan), |
| 30 chan->chan->max_antenna_gain * 2, |
| 31 chan->chan->max_power * 2, |
| 32 min((u32) MAX_RATE_POWER, |
| 33 (u32) regulatory->power_limit)); |
| 34 } |
| 35 |
| 22 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, | 36 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, |
| 23 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 37 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
| 24 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, | 38 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, |
| 25 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 39 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
| 26 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | 40 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, |
| 27 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 41 AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
| 28 } | 42 } |
| 29 EXPORT_SYMBOL(ar9003_paprd_enable); | 43 EXPORT_SYMBOL(ar9003_paprd_enable); |
| 30 | 44 |
| 31 static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | 45 static int ar9003_get_training_power_2g(struct ath_hw *ah) |
| 32 { | 46 { |
| 33 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 47 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
| 34 » struct ar9300_modal_eep_header *hdr; | 48 » struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G; |
| 49 » unsigned int power, scale, delta; |
| 50 |
| 51 » scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1); |
| 52 » power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, |
| 53 » » » AR_PHY_POWERTX_RATE5_POWERTXHT20_0); |
| 54 |
| 55 » delta = abs((int) ah->paprd_target_power - (int) power); |
| 56 » if (delta > scale) |
| 57 » » return -1; |
| 58 |
| 59 » if (delta < 4) |
| 60 » » power -= 4 - delta; |
| 61 |
| 62 » return power; |
| 63 } |
| 64 |
| 65 static int ar9003_get_training_power_5g(struct ath_hw *ah) |
| 66 { |
| 67 » struct ath_common *common = ath9k_hw_common(ah); |
| 68 » struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
| 69 » struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G; |
| 70 » struct ath9k_channel *chan = ah->curchan; |
| 71 » unsigned int power, scale, delta; |
| 72 |
| 73 » if (chan->channel >= 5700) |
| 74 » » scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), |
| 75 » » » AR9300_PAPRD_SCALE_1); |
| 76 » else if (chan->channel >= 5400) |
| 77 » » scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), |
| 78 » » » AR9300_PAPRD_SCALE_2); |
| 79 » else |
| 80 » » scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), |
| 81 » » » AR9300_PAPRD_SCALE_1); |
| 82 |
| 83 » if (IS_CHAN_HT40(chan)) |
| 84 » » power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8, |
| 85 » » » AR_PHY_POWERTX_RATE8_POWERTXHT40_5); |
| 86 » else |
| 87 » » power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6, |
| 88 » » » AR_PHY_POWERTX_RATE6_POWERTXHT20_5); |
| 89 |
| 90 » power += scale; |
| 91 » delta = abs((int) ah->paprd_target_power - (int) power); |
| 92 » if (delta > scale) |
| 93 » » return -1; |
| 94 |
| 95 » power += 2 * get_streams(common->tx_chainmask); |
| 96 » return power; |
| 97 } |
| 98 |
| 99 static int ar9003_paprd_setup_single_table(struct ath_hw *ah) |
| 100 { |
| 101 » struct ath_common *common = ath9k_hw_common(ah); |
| 35 const u32 ctrl0[3] = { | 102 const u32 ctrl0[3] = { |
| 36 AR_PHY_PAPRD_CTRL0_B0, | 103 AR_PHY_PAPRD_CTRL0_B0, |
| 37 AR_PHY_PAPRD_CTRL0_B1, | 104 AR_PHY_PAPRD_CTRL0_B1, |
| 38 AR_PHY_PAPRD_CTRL0_B2 | 105 AR_PHY_PAPRD_CTRL0_B2 |
| 39 }; | 106 }; |
| 40 const u32 ctrl1[3] = { | 107 const u32 ctrl1[3] = { |
| 41 AR_PHY_PAPRD_CTRL1_B0, | 108 AR_PHY_PAPRD_CTRL1_B0, |
| 42 AR_PHY_PAPRD_CTRL1_B1, | 109 AR_PHY_PAPRD_CTRL1_B1, |
| 43 AR_PHY_PAPRD_CTRL1_B2 | 110 AR_PHY_PAPRD_CTRL1_B2 |
| 44 }; | 111 }; |
| 45 » u32 am_mask, ht40_mask; | 112 » int training_power; |
| 46 int i; | 113 int i; |
| 47 | 114 |
| 48 » if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) | 115 » if (IS_CHAN_2GHZ(ah->curchan)) |
| 49 » » hdr = &eep->modalHeader5G; | 116 » » training_power = ar9003_get_training_power_2g(ah); |
| 50 else | 117 else |
| 51 » » hdr = &eep->modalHeader2G; | 118 » » training_power = ar9003_get_training_power_5g(ah); |
| 52 | 119 |
| 53 » am_mask = le32_to_cpu(hdr->papdRateMaskHt20); | 120 » if (training_power < 0) { |
| 54 » ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); | 121 » » ath_print(common, ATH_DBG_CALIBRATE, |
| 122 » » » "PAPRD target power delta out of range"); |
| 123 » » return -ERANGE; |
| 124 » } |
| 125 » ah->paprd_training_power = training_power; |
| 126 » ath_print(common, ATH_DBG_CALIBRATE, |
| 127 » » "Training power: %d, Target power: %d\n", |
| 128 » » ah->paprd_training_power, ah->paprd_target_power); |
| 55 | 129 |
| 56 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); | 130 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, |
| 57 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); | 131 » » ah->paprd_ratemask); |
| 58 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); | 132 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, |
| 133 » » ah->paprd_ratemask); |
| 134 » REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, |
| 135 » » ah->paprd_ratemask_ht40); |
| 59 | 136 |
| 60 for (i = 0; i < 3; i++) { | 137 for (i = 0; i < 3; i++) { |
| 61 REG_RMW_FIELD(ah, ctrl0[i], | 138 REG_RMW_FIELD(ah, ctrl0[i], |
| 62 AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); | 139 AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); |
| 63 REG_RMW_FIELD(ah, ctrl1[i], | 140 REG_RMW_FIELD(ah, ctrl1[i], |
| 64 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); | 141 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); |
| 65 REG_RMW_FIELD(ah, ctrl1[i], | 142 REG_RMW_FIELD(ah, ctrl1[i], |
| 66 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); | 143 AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); |
| 67 REG_RMW_FIELD(ah, ctrl1[i], | 144 REG_RMW_FIELD(ah, ctrl1[i], |
| 68 AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | 145 AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, | 202 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, |
| 126 AR_PHY_PAPRD_PRE_POST_SCALING, 220464); | 203 AR_PHY_PAPRD_PRE_POST_SCALING, 220464); |
| 127 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, | 204 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, |
| 128 AR_PHY_PAPRD_PRE_POST_SCALING, 208194); | 205 AR_PHY_PAPRD_PRE_POST_SCALING, 208194); |
| 129 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, | 206 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, |
| 130 AR_PHY_PAPRD_PRE_POST_SCALING, 196949); | 207 AR_PHY_PAPRD_PRE_POST_SCALING, 196949); |
| 131 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, | 208 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, |
| 132 AR_PHY_PAPRD_PRE_POST_SCALING, 185706); | 209 AR_PHY_PAPRD_PRE_POST_SCALING, 185706); |
| 133 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, | 210 REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, |
| 134 AR_PHY_PAPRD_PRE_POST_SCALING, 175487); | 211 AR_PHY_PAPRD_PRE_POST_SCALING, 175487); |
| 212 return 0; |
| 135 } | 213 } |
| 136 | 214 |
| 137 static void ar9003_paprd_get_gain_table(struct ath_hw *ah) | 215 static void ar9003_paprd_get_gain_table(struct ath_hw *ah) |
| 138 { | 216 { |
| 139 u32 *entry = ah->paprd_gain_table_entries; | 217 u32 *entry = ah->paprd_gain_table_entries; |
| 140 u8 *index = ah->paprd_gain_table_index; | 218 u8 *index = ah->paprd_gain_table_index; |
| 141 u32 reg = AR_PHY_TXGAIN_TABLE; | 219 u32 reg = AR_PHY_TXGAIN_TABLE; |
| 142 int i; | 220 int i; |
| 143 | 221 |
| 144 memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); | 222 memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 *gain = G_fxp; | 657 *gain = G_fxp; |
| 580 return true; | 658 return true; |
| 581 } | 659 } |
| 582 | 660 |
| 583 void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 661 void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
| 584 struct ath9k_hw_cal_data *caldata, | 662 struct ath9k_hw_cal_data *caldata, |
| 585 int chain) | 663 int chain) |
| 586 { | 664 { |
| 587 u32 *paprd_table_val = caldata->pa_table[chain]; | 665 u32 *paprd_table_val = caldata->pa_table[chain]; |
| 588 u32 small_signal_gain = caldata->small_signal_gain[chain]; | 666 u32 small_signal_gain = caldata->small_signal_gain[chain]; |
| 589 » u32 training_power; | 667 » u32 training_power = ah->paprd_training_power; |
| 590 u32 reg = 0; | 668 u32 reg = 0; |
| 591 int i; | 669 int i; |
| 592 | 670 |
| 593 training_power = | |
| 594 REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | |
| 595 AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | |
| 596 training_power -= 4; | |
| 597 | |
| 598 if (chain == 0) | 671 if (chain == 0) |
| 599 reg = AR_PHY_PAPRD_MEM_TAB_B0; | 672 reg = AR_PHY_PAPRD_MEM_TAB_B0; |
| 600 else if (chain == 1) | 673 else if (chain == 1) |
| 601 reg = AR_PHY_PAPRD_MEM_TAB_B1; | 674 reg = AR_PHY_PAPRD_MEM_TAB_B1; |
| 602 else if (chain == 2) | 675 else if (chain == 2) |
| 603 reg = AR_PHY_PAPRD_MEM_TAB_B2; | 676 reg = AR_PHY_PAPRD_MEM_TAB_B2; |
| 604 | 677 |
| 605 for (i = 0; i < PAPRD_TABLE_SZ; i++) { | 678 for (i = 0; i < PAPRD_TABLE_SZ; i++) { |
| 606 REG_WRITE(ah, reg, paprd_table_val[i]); | 679 REG_WRITE(ah, reg, paprd_table_val[i]); |
| 607 reg = reg + 4; | 680 reg = reg + 4; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 625 training_power); | 698 training_power); |
| 626 | 699 |
| 627 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, | 700 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, |
| 628 AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | 701 AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, |
| 629 training_power); | 702 training_power); |
| 630 } | 703 } |
| 631 EXPORT_SYMBOL(ar9003_paprd_populate_single_table); | 704 EXPORT_SYMBOL(ar9003_paprd_populate_single_table); |
| 632 | 705 |
| 633 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | 706 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) |
| 634 { | 707 { |
| 635 | |
| 636 unsigned int i, desired_gain, gain_index; | 708 unsigned int i, desired_gain, gain_index; |
| 637 » unsigned int train_power; | 709 » unsigned int train_power = ah->paprd_training_power; |
| 638 | |
| 639 » train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | |
| 640 » » » » AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | |
| 641 | |
| 642 » train_power = train_power - 4; | |
| 643 | 710 |
| 644 desired_gain = ar9003_get_desired_gain(ah, chain, train_power); | 711 desired_gain = ar9003_get_desired_gain(ah, chain, train_power); |
| 645 | 712 |
| 646 gain_index = 0; | 713 gain_index = 0; |
| 647 for (i = 0; i < 32; i++) { | 714 for (i = 0; i < 32; i++) { |
| 648 if (ah->paprd_gain_table_index[i] >= desired_gain) | 715 if (ah->paprd_gain_table_index[i] >= desired_gain) |
| 649 break; | 716 break; |
| 650 gain_index++; | 717 gain_index++; |
| 651 } | 718 } |
| 652 | 719 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | 765 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); |
| 699 | 766 |
| 700 kfree(buf); | 767 kfree(buf); |
| 701 | 768 |
| 702 return status; | 769 return status; |
| 703 } | 770 } |
| 704 EXPORT_SYMBOL(ar9003_paprd_create_curve); | 771 EXPORT_SYMBOL(ar9003_paprd_create_curve); |
| 705 | 772 |
| 706 int ar9003_paprd_init_table(struct ath_hw *ah) | 773 int ar9003_paprd_init_table(struct ath_hw *ah) |
| 707 { | 774 { |
| 708 » ar9003_paprd_setup_single_table(ah); | 775 » int ret; |
| 776 |
| 777 » ret = ar9003_paprd_setup_single_table(ah); |
| 778 » if (ret < 0) |
| 779 » return ret; |
| 780 |
| 709 ar9003_paprd_get_gain_table(ah); | 781 ar9003_paprd_get_gain_table(ah); |
| 710 return 0; | 782 return 0; |
| 711 } | 783 } |
| 712 EXPORT_SYMBOL(ar9003_paprd_init_table); | 784 EXPORT_SYMBOL(ar9003_paprd_init_table); |
| 713 | 785 |
| 714 bool ar9003_paprd_is_done(struct ath_hw *ah) | 786 bool ar9003_paprd_is_done(struct ath_hw *ah) |
| 715 { | 787 { |
| 716 return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, | 788 return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, |
| 717 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | 789 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); |
| 718 } | 790 } |
| 719 EXPORT_SYMBOL(ar9003_paprd_is_done); | 791 EXPORT_SYMBOL(ar9003_paprd_is_done); |
| OLD | NEW |