diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-06-12 00:34:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-14 15:39:32 -0400 |
commit | 717f6bedcd2d3d39624437e1de7067c90ec931f0 (patch) | |
tree | d4d2048c61a32d96c49cfb77cff17212454ab96c /drivers | |
parent | 4935250ac14d9aac7d98411bdead2e33a9fadeac (diff) |
ath9k_hw: add functions for controlling PA predistortion calibration
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 714 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 18 |
5 files changed, 746 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index dd112be218ab..973ae4f49f35 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -32,7 +32,8 @@ ath9k_hw-y:= \ | |||
32 | mac.o \ | 32 | mac.o \ |
33 | ar9002_mac.o \ | 33 | ar9002_mac.o \ |
34 | ar9003_mac.o \ | 34 | ar9003_mac.o \ |
35 | ar9003_eeprom.o | 35 | ar9003_eeprom.o \ |
36 | ar9003_paprd.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 38 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
38 | 39 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 40731077cbb4..06ef71019c12 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -470,6 +470,14 @@ static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
470 | ads->ctl11 &= ~AR_VirtMoreFrag; | 470 | ads->ctl11 &= ~AR_VirtMoreFrag; |
471 | } | 471 | } |
472 | 472 | ||
473 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | ||
474 | { | ||
475 | struct ar9003_txc *ads = ds; | ||
476 | |||
477 | ads->ctl12 |= SM(chains, AR_PAPRDChainMask); | ||
478 | } | ||
479 | EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); | ||
480 | |||
473 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 481 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
474 | { | 482 | { |
475 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 483 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 5a7a286e2773..f76f27d16f77 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h | |||
@@ -40,6 +40,10 @@ | |||
40 | 40 | ||
41 | #define AR_Not_Sounding 0x20000000 | 41 | #define AR_Not_Sounding 0x20000000 |
42 | 42 | ||
43 | /* ctl 12 */ | ||
44 | #define AR_PAPRDChainMask 0x00000e00 | ||
45 | #define AR_PAPRDChainMask_S 9 | ||
46 | |||
43 | #define MAP_ISR_S2_CST 6 | 47 | #define MAP_ISR_S2_CST 6 |
44 | #define MAP_ISR_S2_GTT 6 | 48 | #define MAP_ISR_S2_GTT 6 |
45 | #define MAP_ISR_S2_TIM 3 | 49 | #define MAP_ISR_S2_TIM 3 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c new file mode 100644 index 000000000000..49e0c865ce5c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -0,0 +1,714 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
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 | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
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 | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "hw.h" | ||
18 | #include "ar9003_phy.h" | ||
19 | |||
20 | void ar9003_paprd_enable(struct ath_hw *ah, bool val) | ||
21 | { | ||
22 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, | ||
23 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
24 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, | ||
25 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
26 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | ||
27 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
28 | } | ||
29 | EXPORT_SYMBOL(ar9003_paprd_enable); | ||
30 | |||
31 | static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | ||
32 | { | ||
33 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
34 | struct ar9300_modal_eep_header *hdr; | ||
35 | const u32 ctrl0[3] = { | ||
36 | AR_PHY_PAPRD_CTRL0_B0, | ||
37 | AR_PHY_PAPRD_CTRL0_B1, | ||
38 | AR_PHY_PAPRD_CTRL0_B2 | ||
39 | }; | ||
40 | const u32 ctrl1[3] = { | ||
41 | AR_PHY_PAPRD_CTRL1_B0, | ||
42 | AR_PHY_PAPRD_CTRL1_B1, | ||
43 | AR_PHY_PAPRD_CTRL1_B2 | ||
44 | }; | ||
45 | u32 am_mask, ht40_mask; | ||
46 | int i; | ||
47 | |||
48 | if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) | ||
49 | hdr = &eep->modalHeader5G; | ||
50 | else | ||
51 | hdr = &eep->modalHeader2G; | ||
52 | |||
53 | am_mask = le32_to_cpu(hdr->papdRateMaskHt20); | ||
54 | ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); | ||
55 | |||
56 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); | ||
57 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); | ||
58 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); | ||
59 | |||
60 | for (i = 0; i < 3; i++) { | ||
61 | REG_RMW_FIELD(ah, ctrl0[i], | ||
62 | AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); | ||
63 | REG_RMW_FIELD(ah, ctrl1[i], | ||
64 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); | ||
65 | REG_RMW_FIELD(ah, ctrl1[i], | ||
66 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); | ||
67 | REG_RMW_FIELD(ah, ctrl1[i], | ||
68 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
69 | REG_RMW_FIELD(ah, ctrl1[i], | ||
70 | AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181); | ||
71 | REG_RMW_FIELD(ah, ctrl1[i], | ||
72 | AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361); | ||
73 | REG_RMW_FIELD(ah, ctrl1[i], | ||
74 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
75 | REG_RMW_FIELD(ah, ctrl0[i], | ||
76 | AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3); | ||
77 | } | ||
78 | |||
79 | ar9003_paprd_enable(ah, false); | ||
80 | |||
81 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
82 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30); | ||
83 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
84 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1); | ||
85 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
86 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1); | ||
87 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
88 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0); | ||
89 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
90 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0); | ||
91 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
92 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28); | ||
93 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
94 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1); | ||
95 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2, | ||
96 | AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147); | ||
97 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
98 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4); | ||
99 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
100 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4); | ||
101 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
102 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); | ||
103 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
104 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); | ||
105 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
106 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); | ||
107 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
108 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, | ||
109 | -15); | ||
110 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
111 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1); | ||
112 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
113 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0); | ||
114 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
115 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400); | ||
116 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
117 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, | ||
118 | 100); | ||
119 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0, | ||
120 | AR_PHY_PAPRD_PRE_POST_SCALING, 261376); | ||
121 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0, | ||
122 | AR_PHY_PAPRD_PRE_POST_SCALING, 248079); | ||
123 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0, | ||
124 | AR_PHY_PAPRD_PRE_POST_SCALING, 233759); | ||
125 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, | ||
126 | AR_PHY_PAPRD_PRE_POST_SCALING, 220464); | ||
127 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, | ||
128 | AR_PHY_PAPRD_PRE_POST_SCALING, 208194); | ||
129 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, | ||
130 | AR_PHY_PAPRD_PRE_POST_SCALING, 196949); | ||
131 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, | ||
132 | AR_PHY_PAPRD_PRE_POST_SCALING, 185706); | ||
133 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, | ||
134 | AR_PHY_PAPRD_PRE_POST_SCALING, 175487); | ||
135 | } | ||
136 | |||
137 | static void ar9003_paprd_get_gain_table(struct ath_hw *ah) | ||
138 | { | ||
139 | u32 *entry = ah->paprd_gain_table_entries; | ||
140 | u8 *index = ah->paprd_gain_table_index; | ||
141 | u32 reg = AR_PHY_TXGAIN_TABLE; | ||
142 | int i; | ||
143 | |||
144 | memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); | ||
145 | memset(index, 0, sizeof(ah->paprd_gain_table_index)); | ||
146 | |||
147 | for (i = 0; i < 32; i++) { | ||
148 | entry[i] = REG_READ(ah, reg); | ||
149 | index[i] = (entry[i] >> 24) & 0xff; | ||
150 | reg += 4; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain, | ||
155 | int target_power) | ||
156 | { | ||
157 | int olpc_gain_delta = 0; | ||
158 | int alpha_therm, alpha_volt; | ||
159 | int therm_cal_value, volt_cal_value; | ||
160 | int therm_value, volt_value; | ||
161 | int thermal_gain_corr, voltage_gain_corr; | ||
162 | int desired_scale, desired_gain = 0; | ||
163 | u32 reg; | ||
164 | |||
165 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
166 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
167 | desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12, | ||
168 | AR_PHY_TPC_12_DESIRED_SCALE_HT40_5); | ||
169 | alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
170 | AR_PHY_TPC_19_ALPHA_THERM); | ||
171 | alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
172 | AR_PHY_TPC_19_ALPHA_VOLT); | ||
173 | therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
174 | AR_PHY_TPC_18_THERM_CAL_VALUE); | ||
175 | volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
176 | AR_PHY_TPC_18_VOLT_CAL_VALUE); | ||
177 | therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
178 | AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE); | ||
179 | volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
180 | AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE); | ||
181 | |||
182 | if (chain == 0) | ||
183 | reg = AR_PHY_TPC_11_B0; | ||
184 | else if (chain == 1) | ||
185 | reg = AR_PHY_TPC_11_B1; | ||
186 | else | ||
187 | reg = AR_PHY_TPC_11_B2; | ||
188 | |||
189 | olpc_gain_delta = REG_READ_FIELD(ah, reg, | ||
190 | AR_PHY_TPC_11_OLPC_GAIN_DELTA); | ||
191 | |||
192 | if (olpc_gain_delta >= 128) | ||
193 | olpc_gain_delta = olpc_gain_delta - 256; | ||
194 | |||
195 | thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) + | ||
196 | (256 / 2)) / 256; | ||
197 | voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) + | ||
198 | (128 / 2)) / 128; | ||
199 | desired_gain = target_power - olpc_gain_delta - thermal_gain_corr - | ||
200 | voltage_gain_corr + desired_scale; | ||
201 | |||
202 | return desired_gain; | ||
203 | } | ||
204 | |||
205 | static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index) | ||
206 | { | ||
207 | int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain; | ||
208 | int padrvgnA, padrvgnB, padrvgnC, padrvgnD; | ||
209 | u32 *gain_table_entries = ah->paprd_gain_table_entries; | ||
210 | |||
211 | selected_gain_entry = gain_table_entries[gain_index]; | ||
212 | txbb1dbgain = selected_gain_entry & 0x7; | ||
213 | txbb6dbgain = (selected_gain_entry >> 3) & 0x3; | ||
214 | txmxrgain = (selected_gain_entry >> 5) & 0xf; | ||
215 | padrvgnA = (selected_gain_entry >> 9) & 0xf; | ||
216 | padrvgnB = (selected_gain_entry >> 13) & 0xf; | ||
217 | padrvgnC = (selected_gain_entry >> 17) & 0xf; | ||
218 | padrvgnD = (selected_gain_entry >> 21) & 0x3; | ||
219 | |||
220 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
221 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain); | ||
222 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
223 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain); | ||
224 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
225 | AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain); | ||
226 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
227 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA); | ||
228 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
229 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB); | ||
230 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
231 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC); | ||
232 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
233 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD); | ||
234 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
235 | AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0); | ||
236 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
237 | AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0); | ||
238 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0); | ||
239 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0); | ||
240 | } | ||
241 | |||
242 | static inline int find_expn(int num) | ||
243 | { | ||
244 | return fls(num) - 1; | ||
245 | } | ||
246 | |||
247 | static inline int find_proper_scale(int expn, int N) | ||
248 | { | ||
249 | return (expn > N) ? expn - 10 : 0; | ||
250 | } | ||
251 | |||
252 | #define NUM_BIN 23 | ||
253 | |||
254 | static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | ||
255 | { | ||
256 | unsigned int thresh_accum_cnt; | ||
257 | int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1]; | ||
258 | int PA_in[NUM_BIN + 1]; | ||
259 | int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1]; | ||
260 | unsigned int B1_abs_max, B2_abs_max; | ||
261 | int max_index, scale_factor; | ||
262 | int y_est[NUM_BIN + 1]; | ||
263 | int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1]; | ||
264 | unsigned int x_tilde_abs; | ||
265 | int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad; | ||
266 | int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B; | ||
267 | int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2; | ||
268 | int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem; | ||
269 | int y5, y3, tmp; | ||
270 | int theta_low_bin = 0; | ||
271 | int i; | ||
272 | |||
273 | /* disregard any bin that contains <= 16 samples */ | ||
274 | thresh_accum_cnt = 16; | ||
275 | scale_factor = 5; | ||
276 | max_index = 0; | ||
277 | memset(theta, 0, sizeof(theta)); | ||
278 | memset(x_est, 0, sizeof(x_est)); | ||
279 | memset(Y, 0, sizeof(Y)); | ||
280 | memset(y_est, 0, sizeof(y_est)); | ||
281 | memset(x_tilde, 0, sizeof(x_tilde)); | ||
282 | |||
283 | for (i = 0; i < NUM_BIN; i++) { | ||
284 | s32 accum_cnt, accum_tx, accum_rx, accum_ang; | ||
285 | |||
286 | /* number of samples */ | ||
287 | accum_cnt = data_L[i] & 0xffff; | ||
288 | |||
289 | if (accum_cnt <= thresh_accum_cnt) | ||
290 | continue; | ||
291 | |||
292 | /* sum(tx amplitude) */ | ||
293 | accum_tx = ((data_L[i] >> 16) & 0xffff) | | ||
294 | ((data_U[i] & 0x7ff) << 16); | ||
295 | |||
296 | /* sum(rx amplitude distance to lower bin edge) */ | ||
297 | accum_rx = ((data_U[i] >> 11) & 0x1f) | | ||
298 | ((data_L[i + 23] & 0xffff) << 5); | ||
299 | |||
300 | /* sum(angles) */ | ||
301 | accum_ang = ((data_L[i + 23] >> 16) & 0xffff) | | ||
302 | ((data_U[i + 23] & 0x7ff) << 16); | ||
303 | |||
304 | accum_tx <<= scale_factor; | ||
305 | accum_rx <<= scale_factor; | ||
306 | x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >> | ||
307 | scale_factor; | ||
308 | |||
309 | Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> | ||
310 | scale_factor) + | ||
311 | (1 << scale_factor) * max_index + 16; | ||
312 | |||
313 | if (accum_ang >= (1 << 26)) | ||
314 | accum_ang -= 1 << 27; | ||
315 | |||
316 | theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) / | ||
317 | accum_cnt; | ||
318 | |||
319 | max_index++; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Find average theta of first 5 bin and all of those to same value. | ||
324 | * Curve is linear at that range. | ||
325 | */ | ||
326 | for (i = 1; i < 6; i++) | ||
327 | theta_low_bin += theta[i]; | ||
328 | |||
329 | theta_low_bin = theta_low_bin / 5; | ||
330 | for (i = 1; i < 6; i++) | ||
331 | theta[i] = theta_low_bin; | ||
332 | |||
333 | /* Set values at origin */ | ||
334 | theta[0] = theta_low_bin; | ||
335 | for (i = 0; i <= max_index; i++) | ||
336 | theta[i] -= theta_low_bin; | ||
337 | |||
338 | x_est[0] = 0; | ||
339 | Y[0] = 0; | ||
340 | scale_factor = 8; | ||
341 | |||
342 | /* low signal gain */ | ||
343 | if (x_est[6] == x_est[3]) | ||
344 | return false; | ||
345 | |||
346 | G_fxp = | ||
347 | (((Y[6] - Y[3]) * 1 << scale_factor) + | ||
348 | (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); | ||
349 | |||
350 | Y_intercept = | ||
351 | (G_fxp * (x_est[0] - x_est[3]) + | ||
352 | (1 << scale_factor)) / (1 << scale_factor) + Y[3]; | ||
353 | |||
354 | for (i = 0; i <= max_index; i++) | ||
355 | y_est[i] = Y[i] - Y_intercept; | ||
356 | |||
357 | for (i = 0; i <= 3; i++) { | ||
358 | y_est[i] = i * 32; | ||
359 | |||
360 | /* prevent division by zero */ | ||
361 | if (G_fxp == 0) | ||
362 | return false; | ||
363 | |||
364 | x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; | ||
365 | } | ||
366 | |||
367 | x_est_fxp1_nonlin = | ||
368 | x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + | ||
369 | G_fxp) / G_fxp; | ||
370 | |||
371 | order_x_by_y = | ||
372 | (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index]; | ||
373 | |||
374 | if (order_x_by_y == 0) | ||
375 | M = 10; | ||
376 | else if (order_x_by_y == 1) | ||
377 | M = 9; | ||
378 | else | ||
379 | M = 8; | ||
380 | |||
381 | I = (max_index > 15) ? 7 : max_index >> 1; | ||
382 | L = max_index - I; | ||
383 | scale_factor = 8; | ||
384 | sum_y_sqr = 0; | ||
385 | sum_y_quad = 0; | ||
386 | x_tilde_abs = 0; | ||
387 | |||
388 | for (i = 0; i <= L; i++) { | ||
389 | unsigned int y_sqr; | ||
390 | unsigned int y_quad; | ||
391 | unsigned int tmp_abs; | ||
392 | |||
393 | /* prevent division by zero */ | ||
394 | if (y_est[i + I] == 0) | ||
395 | return false; | ||
396 | |||
397 | x_est_fxp1_nonlin = | ||
398 | x_est[i + I] - ((1 << scale_factor) * y_est[i + I] + | ||
399 | G_fxp) / G_fxp; | ||
400 | |||
401 | x_tilde[i] = | ||
402 | (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i + | ||
403 | I]; | ||
404 | x_tilde[i] = | ||
405 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
406 | x_tilde[i] = | ||
407 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
408 | y_sqr = | ||
409 | (y_est[i + I] * y_est[i + I] + | ||
410 | (scale_factor * scale_factor)) / (scale_factor * | ||
411 | scale_factor); | ||
412 | tmp_abs = abs(x_tilde[i]); | ||
413 | if (tmp_abs > x_tilde_abs) | ||
414 | x_tilde_abs = tmp_abs; | ||
415 | |||
416 | y_quad = y_sqr * y_sqr; | ||
417 | sum_y_sqr = sum_y_sqr + y_sqr; | ||
418 | sum_y_quad = sum_y_quad + y_quad; | ||
419 | B1_tmp[i] = y_sqr * (L + 1); | ||
420 | B2_tmp[i] = y_sqr; | ||
421 | } | ||
422 | |||
423 | B1_abs_max = 0; | ||
424 | B2_abs_max = 0; | ||
425 | for (i = 0; i <= L; i++) { | ||
426 | int abs_val; | ||
427 | |||
428 | B1_tmp[i] -= sum_y_sqr; | ||
429 | B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i]; | ||
430 | |||
431 | abs_val = abs(B1_tmp[i]); | ||
432 | if (abs_val > B1_abs_max) | ||
433 | B1_abs_max = abs_val; | ||
434 | |||
435 | abs_val = abs(B2_tmp[i]); | ||
436 | if (abs_val > B2_abs_max) | ||
437 | B2_abs_max = abs_val; | ||
438 | } | ||
439 | |||
440 | Q_x = find_proper_scale(find_expn(x_tilde_abs), 10); | ||
441 | Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10); | ||
442 | Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10); | ||
443 | |||
444 | beta_raw = 0; | ||
445 | alpha_raw = 0; | ||
446 | for (i = 0; i <= L; i++) { | ||
447 | x_tilde[i] = x_tilde[i] / (1 << Q_x); | ||
448 | B1_tmp[i] = B1_tmp[i] / (1 << Q_B1); | ||
449 | B2_tmp[i] = B2_tmp[i] / (1 << Q_B2); | ||
450 | beta_raw = beta_raw + B1_tmp[i] * x_tilde[i]; | ||
451 | alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i]; | ||
452 | } | ||
453 | |||
454 | scale_B = | ||
455 | ((sum_y_quad / scale_factor) * (L + 1) - | ||
456 | (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor; | ||
457 | |||
458 | Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); | ||
459 | scale_B = scale_B / (1 << Q_scale_B); | ||
460 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
461 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
462 | beta_raw = beta_raw / (1 << Q_beta); | ||
463 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
464 | alpha = (alpha_raw << 10) / scale_B; | ||
465 | beta = (beta_raw << 10) / scale_B; | ||
466 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B; | ||
467 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B; | ||
468 | order1_5x = order_1 / 5; | ||
469 | order2_3x = order_2 / 3; | ||
470 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
471 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
472 | |||
473 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
474 | tmp = i * 32; | ||
475 | y5 = ((beta * tmp) >> 6) >> order1_5x; | ||
476 | y5 = (y5 * tmp) >> order1_5x; | ||
477 | y5 = (y5 * tmp) >> order1_5x; | ||
478 | y5 = (y5 * tmp) >> order1_5x; | ||
479 | y5 = (y5 * tmp) >> order1_5x; | ||
480 | y5 = y5 >> order1_5x_rem; | ||
481 | y3 = (alpha * tmp) >> order2_3x; | ||
482 | y3 = (y3 * tmp) >> order2_3x; | ||
483 | y3 = (y3 * tmp) >> order2_3x; | ||
484 | y3 = y3 >> order2_3x_rem; | ||
485 | PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp; | ||
486 | |||
487 | if (i >= 2) { | ||
488 | tmp = PA_in[i] - PA_in[i - 1]; | ||
489 | if (tmp < 0) | ||
490 | PA_in[i] = | ||
491 | PA_in[i - 1] + (PA_in[i - 1] - | ||
492 | PA_in[i - 2]); | ||
493 | } | ||
494 | |||
495 | PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400; | ||
496 | } | ||
497 | |||
498 | beta_raw = 0; | ||
499 | alpha_raw = 0; | ||
500 | |||
501 | for (i = 0; i <= L; i++) { | ||
502 | int theta_tilde = | ||
503 | ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I]; | ||
504 | theta_tilde = | ||
505 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
506 | theta_tilde = | ||
507 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
508 | beta_raw = beta_raw + B1_tmp[i] * theta_tilde; | ||
509 | alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde; | ||
510 | } | ||
511 | |||
512 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
513 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
514 | beta_raw = beta_raw / (1 << Q_beta); | ||
515 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
516 | |||
517 | alpha = (alpha_raw << 10) / scale_B; | ||
518 | beta = (beta_raw << 10) / scale_B; | ||
519 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5; | ||
520 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5; | ||
521 | order1_5x = order_1 / 5; | ||
522 | order2_3x = order_2 / 3; | ||
523 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
524 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
525 | |||
526 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
527 | int PA_angle; | ||
528 | |||
529 | /* pa_table[4] is calculated from PA_angle for i=5 */ | ||
530 | if (i == 4) | ||
531 | continue; | ||
532 | |||
533 | tmp = i * 32; | ||
534 | if (beta > 0) | ||
535 | y5 = (((beta * tmp - 64) >> 6) - | ||
536 | (1 << order1_5x)) / (1 << order1_5x); | ||
537 | else | ||
538 | y5 = ((((beta * tmp - 64) >> 6) + | ||
539 | (1 << order1_5x)) / (1 << order1_5x)); | ||
540 | |||
541 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
542 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
543 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
544 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
545 | y5 = y5 / (1 << order1_5x_rem); | ||
546 | |||
547 | if (beta > 0) | ||
548 | y3 = (alpha * tmp - | ||
549 | (1 << order2_3x)) / (1 << order2_3x); | ||
550 | else | ||
551 | y3 = (alpha * tmp + | ||
552 | (1 << order2_3x)) / (1 << order2_3x); | ||
553 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
554 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
555 | y3 = y3 / (1 << order2_3x_rem); | ||
556 | |||
557 | if (i < 4) { | ||
558 | PA_angle = 0; | ||
559 | } else { | ||
560 | PA_angle = y5 + y3; | ||
561 | if (PA_angle < -150) | ||
562 | PA_angle = -150; | ||
563 | else if (PA_angle > 150) | ||
564 | PA_angle = 150; | ||
565 | } | ||
566 | |||
567 | pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff); | ||
568 | if (i == 5) { | ||
569 | PA_angle = (PA_angle + 2) >> 1; | ||
570 | pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) + | ||
571 | (PA_angle & 0x7ff); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | *gain = G_fxp; | ||
576 | return true; | ||
577 | } | ||
578 | |||
579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
580 | struct ath9k_channel *chan, int chain) | ||
581 | { | ||
582 | u32 *paprd_table_val = chan->pa_table[chain]; | ||
583 | u32 small_signal_gain = chan->small_signal_gain[chain]; | ||
584 | u32 training_power; | ||
585 | u32 reg = 0; | ||
586 | int i; | ||
587 | |||
588 | training_power = | ||
589 | REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
590 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
591 | training_power -= 4; | ||
592 | |||
593 | if (chain == 0) | ||
594 | reg = AR_PHY_PAPRD_MEM_TAB_B0; | ||
595 | else if (chain == 1) | ||
596 | reg = AR_PHY_PAPRD_MEM_TAB_B1; | ||
597 | else if (chain == 2) | ||
598 | reg = AR_PHY_PAPRD_MEM_TAB_B2; | ||
599 | |||
600 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
601 | REG_WRITE(ah, reg, paprd_table_val[i]); | ||
602 | reg = reg + 4; | ||
603 | } | ||
604 | |||
605 | if (chain == 0) | ||
606 | reg = AR_PHY_PA_GAIN123_B0; | ||
607 | else if (chain == 1) | ||
608 | reg = AR_PHY_PA_GAIN123_B1; | ||
609 | else | ||
610 | reg = AR_PHY_PA_GAIN123_B2; | ||
611 | |||
612 | REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain); | ||
613 | |||
614 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0, | ||
615 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
616 | training_power); | ||
617 | |||
618 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, | ||
619 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
620 | training_power); | ||
621 | |||
622 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, | ||
623 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
624 | training_power); | ||
625 | } | ||
626 | EXPORT_SYMBOL(ar9003_paprd_populate_single_table); | ||
627 | |||
628 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | ||
629 | { | ||
630 | |||
631 | unsigned int i, desired_gain, gain_index; | ||
632 | unsigned int train_power; | ||
633 | |||
634 | train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
635 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
636 | |||
637 | train_power = train_power - 4; | ||
638 | |||
639 | desired_gain = ar9003_get_desired_gain(ah, chain, train_power); | ||
640 | |||
641 | gain_index = 0; | ||
642 | for (i = 0; i < 32; i++) { | ||
643 | if (ah->paprd_gain_table_index[i] >= desired_gain) | ||
644 | break; | ||
645 | gain_index++; | ||
646 | } | ||
647 | |||
648 | ar9003_tx_force_gain(ah, gain_index); | ||
649 | |||
650 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
651 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); | ||
656 | |||
657 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
658 | int chain) | ||
659 | { | ||
660 | u16 *small_signal_gain = &chan->small_signal_gain[chain]; | ||
661 | u32 *pa_table = chan->pa_table[chain]; | ||
662 | u32 *data_L, *data_U; | ||
663 | int i, status = 0; | ||
664 | u32 *buf; | ||
665 | u32 reg; | ||
666 | |||
667 | memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); | ||
668 | |||
669 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); | ||
670 | if (!buf) | ||
671 | return -ENOMEM; | ||
672 | |||
673 | data_L = &buf[0]; | ||
674 | data_U = &buf[48]; | ||
675 | |||
676 | REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
677 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
678 | |||
679 | reg = AR_PHY_CHAN_INFO_TAB_0; | ||
680 | for (i = 0; i < 48; i++) | ||
681 | data_L[i] = REG_READ(ah, reg + (i << 2)); | ||
682 | |||
683 | REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
684 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
685 | |||
686 | for (i = 0; i < 48; i++) | ||
687 | data_U[i] = REG_READ(ah, reg + (i << 2)); | ||
688 | |||
689 | if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) | ||
690 | status = -2; | ||
691 | |||
692 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
693 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
694 | |||
695 | kfree(buf); | ||
696 | |||
697 | return status; | ||
698 | } | ||
699 | EXPORT_SYMBOL(ar9003_paprd_create_curve); | ||
700 | |||
701 | int ar9003_paprd_init_table(struct ath_hw *ah) | ||
702 | { | ||
703 | ar9003_paprd_setup_single_table(ah); | ||
704 | ar9003_paprd_get_gain_table(ah); | ||
705 | return 0; | ||
706 | } | ||
707 | EXPORT_SYMBOL(ar9003_paprd_init_table); | ||
708 | |||
709 | bool ar9003_paprd_is_done(struct ath_hw *ah) | ||
710 | { | ||
711 | return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
712 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
713 | } | ||
714 | EXPORT_SYMBOL(ar9003_paprd_is_done); | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9d092168855b..d60472b4f773 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -158,6 +158,9 @@ | |||
158 | #define ATH9K_HW_RX_HP_QDEPTH 16 | 158 | #define ATH9K_HW_RX_HP_QDEPTH 16 |
159 | #define ATH9K_HW_RX_LP_QDEPTH 128 | 159 | #define ATH9K_HW_RX_LP_QDEPTH 128 |
160 | 160 | ||
161 | #define PAPRD_GAIN_TABLE_ENTRIES 32 | ||
162 | #define PAPRD_TABLE_SZ 24 | ||
163 | |||
161 | enum ath_ini_subsys { | 164 | enum ath_ini_subsys { |
162 | ATH_INI_PRE = 0, | 165 | ATH_INI_PRE = 0, |
163 | ATH_INI_CORE, | 166 | ATH_INI_CORE, |
@@ -361,6 +364,9 @@ struct ath9k_channel { | |||
361 | int8_t iCoff; | 364 | int8_t iCoff; |
362 | int8_t qCoff; | 365 | int8_t qCoff; |
363 | int16_t rawNoiseFloor; | 366 | int16_t rawNoiseFloor; |
367 | bool paprd_done; | ||
368 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | ||
369 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | ||
364 | }; | 370 | }; |
365 | 371 | ||
366 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 372 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -819,6 +825,9 @@ struct ath_hw { | |||
819 | 825 | ||
820 | u32 bb_watchdog_last_status; | 826 | u32 bb_watchdog_last_status; |
821 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ | 827 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ |
828 | |||
829 | u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; | ||
830 | u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; | ||
822 | }; | 831 | }; |
823 | 832 | ||
824 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 833 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) |
@@ -946,6 +955,15 @@ void ar9003_hw_set_nf_limits(struct ath_hw *ah); | |||
946 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); | 955 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); |
947 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | 956 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); |
948 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 957 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
958 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | ||
959 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
960 | struct ath9k_channel *chan, int chain); | ||
961 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
962 | int chain); | ||
963 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | ||
964 | int ar9003_paprd_init_table(struct ath_hw *ah); | ||
965 | bool ar9003_paprd_is_done(struct ath_hw *ah); | ||
966 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); | ||
949 | 967 | ||
950 | /* Hardware family op attach helpers */ | 968 | /* Hardware family op attach helpers */ |
951 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 969 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); |