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 |