]>
Commit | Line | Data |
---|---|---|
f1dc5600 | 1 | /* |
cee075a2 | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
f1dc5600 S |
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 | ||
c46917bb | 17 | #include "hw.h" |
641d9921 | 18 | #include "hw-ops.h" |
8fe65368 | 19 | #include "ar9002_phy.h" |
f1dc5600 | 20 | |
f1dc5600 S |
21 | /* We can tune this as we go by monitoring really low values */ |
22 | #define ATH9K_NF_TOO_LOW -60 | |
53bc7aa0 | 23 | #define AR9285_CLCAL_REDO_THRESH 1 |
f1dc5600 S |
24 | |
25 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | |
26 | * is incorrect and we should use the static NF value. Later we can try to | |
27 | * find out why they are reporting these values */ | |
28 | ||
cbe61d8a | 29 | static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) |
f1dc5600 S |
30 | { |
31 | if (nf > ATH9K_NF_TOO_LOW) { | |
c46917bb LR |
32 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
33 | "noise floor value detected (%d) is " | |
34 | "lower than what we think is a " | |
35 | "reasonable value (%d)\n", | |
36 | nf, ATH9K_NF_TOO_LOW); | |
f1dc5600 S |
37 | return false; |
38 | } | |
39 | return true; | |
40 | } | |
41 | ||
42 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | |
43 | { | |
44 | int16_t nfval; | |
45 | int16_t sort[ATH9K_NF_CAL_HIST_MAX]; | |
46 | int i, j; | |
47 | ||
48 | for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) | |
49 | sort[i] = nfCalBuffer[i]; | |
50 | ||
51 | for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { | |
52 | for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { | |
53 | if (sort[j] > sort[j - 1]) { | |
54 | nfval = sort[j]; | |
55 | sort[j] = sort[j - 1]; | |
56 | sort[j - 1] = nfval; | |
57 | } | |
58 | } | |
59 | } | |
60 | nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; | |
61 | ||
62 | return nfval; | |
63 | } | |
64 | ||
65 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |
66 | int16_t *nfarray) | |
67 | { | |
68 | int i; | |
69 | ||
70 | for (i = 0; i < NUM_NF_READINGS; i++) { | |
71 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | |
72 | ||
73 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) | |
74 | h[i].currIndex = 0; | |
75 | ||
76 | if (h[i].invalidNFcount > 0) { | |
77 | if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || | |
78 | nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { | |
79 | h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; | |
80 | } else { | |
81 | h[i].invalidNFcount--; | |
82 | h[i].privNF = nfarray[i]; | |
83 | } | |
84 | } else { | |
85 | h[i].privNF = | |
86 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | |
87 | } | |
88 | } | |
89 | return; | |
90 | } | |
91 | ||
cbe61d8a | 92 | static bool getNoiseFloorThresh(struct ath_hw *ah, |
76061abb | 93 | enum ieee80211_band band, |
f1dc5600 S |
94 | int16_t *nft) |
95 | { | |
76061abb LR |
96 | switch (band) { |
97 | case IEEE80211_BAND_5GHZ: | |
f74df6fb | 98 | *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); |
f1dc5600 | 99 | break; |
76061abb | 100 | case IEEE80211_BAND_2GHZ: |
f74df6fb | 101 | *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); |
f1dc5600 S |
102 | break; |
103 | default: | |
76061abb | 104 | BUG_ON(1); |
f1dc5600 S |
105 | return false; |
106 | } | |
107 | ||
108 | return true; | |
109 | } | |
110 | ||
cbe61d8a | 111 | static void ath9k_hw_setup_calibration(struct ath_hw *ah, |
cbfe9468 | 112 | struct ath9k_cal_list *currCal) |
f1dc5600 | 113 | { |
c46917bb LR |
114 | struct ath_common *common = ath9k_hw_common(ah); |
115 | ||
f1dc5600 S |
116 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), |
117 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, | |
118 | currCal->calData->calCountMax); | |
119 | ||
120 | switch (currCal->calData->calType) { | |
121 | case IQ_MISMATCH_CAL: | |
122 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | |
c46917bb LR |
123 | ath_print(common, ATH_DBG_CALIBRATE, |
124 | "starting IQ Mismatch Calibration\n"); | |
f1dc5600 S |
125 | break; |
126 | case ADC_GAIN_CAL: | |
127 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | |
c46917bb LR |
128 | ath_print(common, ATH_DBG_CALIBRATE, |
129 | "starting ADC Gain Calibration\n"); | |
f1dc5600 S |
130 | break; |
131 | case ADC_DC_CAL: | |
132 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | |
c46917bb LR |
133 | ath_print(common, ATH_DBG_CALIBRATE, |
134 | "starting ADC DC Calibration\n"); | |
f1dc5600 S |
135 | break; |
136 | case ADC_DC_INIT_CAL: | |
137 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | |
c46917bb LR |
138 | ath_print(common, ATH_DBG_CALIBRATE, |
139 | "starting Init ADC DC Calibration\n"); | |
f1dc5600 S |
140 | break; |
141 | } | |
142 | ||
143 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | |
144 | AR_PHY_TIMING_CTRL4_DO_CAL); | |
145 | } | |
146 | ||
cbe61d8a | 147 | static void ath9k_hw_reset_calibration(struct ath_hw *ah, |
cbfe9468 | 148 | struct ath9k_cal_list *currCal) |
f1dc5600 | 149 | { |
f1dc5600 S |
150 | int i; |
151 | ||
152 | ath9k_hw_setup_calibration(ah, currCal); | |
153 | ||
154 | currCal->calState = CAL_RUNNING; | |
155 | ||
156 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | |
2660b81a S |
157 | ah->meas0.sign[i] = 0; |
158 | ah->meas1.sign[i] = 0; | |
159 | ah->meas2.sign[i] = 0; | |
160 | ah->meas3.sign[i] = 0; | |
f1dc5600 S |
161 | } |
162 | ||
2660b81a | 163 | ah->cal_samples = 0; |
f1dc5600 S |
164 | } |
165 | ||
379f0440 | 166 | static bool ath9k_hw_per_calibration(struct ath_hw *ah, |
f1dc5600 S |
167 | struct ath9k_channel *ichan, |
168 | u8 rxchainmask, | |
cbfe9468 | 169 | struct ath9k_cal_list *currCal) |
f1dc5600 | 170 | { |
379f0440 | 171 | bool iscaldone = false; |
f1dc5600 S |
172 | |
173 | if (currCal->calState == CAL_RUNNING) { | |
174 | if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & | |
175 | AR_PHY_TIMING_CTRL4_DO_CAL)) { | |
176 | ||
177 | currCal->calData->calCollect(ah); | |
2660b81a | 178 | ah->cal_samples++; |
f1dc5600 | 179 | |
2660b81a | 180 | if (ah->cal_samples >= currCal->calData->calNumSamples) { |
f1dc5600 S |
181 | int i, numChains = 0; |
182 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | |
183 | if (rxchainmask & (1 << i)) | |
184 | numChains++; | |
185 | } | |
186 | ||
187 | currCal->calData->calPostProc(ah, numChains); | |
188 | ichan->CalValid |= currCal->calData->calType; | |
189 | currCal->calState = CAL_DONE; | |
379f0440 | 190 | iscaldone = true; |
f1dc5600 S |
191 | } else { |
192 | ath9k_hw_setup_calibration(ah, currCal); | |
193 | } | |
194 | } | |
195 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | |
196 | ath9k_hw_reset_calibration(ah, currCal); | |
197 | } | |
379f0440 S |
198 | |
199 | return iscaldone; | |
f1dc5600 S |
200 | } |
201 | ||
c9e27d94 | 202 | /* Assumes you are talking about the currently configured channel */ |
cbe61d8a | 203 | static bool ath9k_hw_iscal_supported(struct ath_hw *ah, |
cbfe9468 | 204 | enum ath9k_cal_types calType) |
f1dc5600 | 205 | { |
b002a4a9 | 206 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
f1dc5600 | 207 | |
2660b81a | 208 | switch (calType & ah->supp_cals) { |
c9e27d94 LR |
209 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ |
210 | return true; | |
f1dc5600 S |
211 | case ADC_GAIN_CAL: |
212 | case ADC_DC_CAL: | |
a451aa66 S |
213 | if (!(conf->channel->band == IEEE80211_BAND_2GHZ && |
214 | conf_is_ht20(conf))) | |
c9e27d94 | 215 | return true; |
f1dc5600 S |
216 | break; |
217 | } | |
c9e27d94 | 218 | return false; |
f1dc5600 S |
219 | } |
220 | ||
cbe61d8a | 221 | static void ath9k_hw_iqcal_collect(struct ath_hw *ah) |
f1dc5600 | 222 | { |
f1dc5600 S |
223 | int i; |
224 | ||
225 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | |
2660b81a | 226 | ah->totalPowerMeasI[i] += |
f1dc5600 | 227 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); |
2660b81a | 228 | ah->totalPowerMeasQ[i] += |
f1dc5600 | 229 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
2660b81a | 230 | ah->totalIqCorrMeas[i] += |
f1dc5600 | 231 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
c46917bb LR |
232 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
233 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | |
234 | ah->cal_samples, i, ah->totalPowerMeasI[i], | |
235 | ah->totalPowerMeasQ[i], | |
236 | ah->totalIqCorrMeas[i]); | |
f1dc5600 S |
237 | } |
238 | } | |
239 | ||
cbe61d8a | 240 | static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) |
f1dc5600 | 241 | { |
f1dc5600 S |
242 | int i; |
243 | ||
244 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | |
2660b81a | 245 | ah->totalAdcIOddPhase[i] += |
f1dc5600 | 246 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); |
2660b81a | 247 | ah->totalAdcIEvenPhase[i] += |
f1dc5600 | 248 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
2660b81a | 249 | ah->totalAdcQOddPhase[i] += |
f1dc5600 | 250 | REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
2660b81a | 251 | ah->totalAdcQEvenPhase[i] += |
f1dc5600 S |
252 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
253 | ||
c46917bb LR |
254 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
255 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | |
256 | "oddq=0x%08x; evenq=0x%08x;\n", | |
257 | ah->cal_samples, i, | |
258 | ah->totalAdcIOddPhase[i], | |
259 | ah->totalAdcIEvenPhase[i], | |
260 | ah->totalAdcQOddPhase[i], | |
261 | ah->totalAdcQEvenPhase[i]); | |
f1dc5600 S |
262 | } |
263 | } | |
264 | ||
cbe61d8a | 265 | static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) |
f1dc5600 | 266 | { |
f1dc5600 S |
267 | int i; |
268 | ||
269 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | |
2660b81a | 270 | ah->totalAdcDcOffsetIOddPhase[i] += |
f1dc5600 | 271 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); |
2660b81a | 272 | ah->totalAdcDcOffsetIEvenPhase[i] += |
f1dc5600 | 273 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
2660b81a | 274 | ah->totalAdcDcOffsetQOddPhase[i] += |
f1dc5600 | 275 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
2660b81a | 276 | ah->totalAdcDcOffsetQEvenPhase[i] += |
f1dc5600 S |
277 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
278 | ||
c46917bb LR |
279 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
280 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | |
281 | "oddq=0x%08x; evenq=0x%08x;\n", | |
282 | ah->cal_samples, i, | |
283 | ah->totalAdcDcOffsetIOddPhase[i], | |
284 | ah->totalAdcDcOffsetIEvenPhase[i], | |
285 | ah->totalAdcDcOffsetQOddPhase[i], | |
286 | ah->totalAdcDcOffsetQEvenPhase[i]); | |
f1dc5600 S |
287 | } |
288 | } | |
289 | ||
cbe61d8a | 290 | static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) |
f1dc5600 | 291 | { |
c46917bb | 292 | struct ath_common *common = ath9k_hw_common(ah); |
f1dc5600 S |
293 | u32 powerMeasQ, powerMeasI, iqCorrMeas; |
294 | u32 qCoffDenom, iCoffDenom; | |
295 | int32_t qCoff, iCoff; | |
296 | int iqCorrNeg, i; | |
297 | ||
298 | for (i = 0; i < numChains; i++) { | |
2660b81a S |
299 | powerMeasI = ah->totalPowerMeasI[i]; |
300 | powerMeasQ = ah->totalPowerMeasQ[i]; | |
301 | iqCorrMeas = ah->totalIqCorrMeas[i]; | |
f1dc5600 | 302 | |
c46917bb LR |
303 | ath_print(common, ATH_DBG_CALIBRATE, |
304 | "Starting IQ Cal and Correction for Chain %d\n", | |
305 | i); | |
f1dc5600 | 306 | |
c46917bb LR |
307 | ath_print(common, ATH_DBG_CALIBRATE, |
308 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | |
309 | i, ah->totalIqCorrMeas[i]); | |
f1dc5600 S |
310 | |
311 | iqCorrNeg = 0; | |
312 | ||
313 | if (iqCorrMeas > 0x80000000) { | |
314 | iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; | |
315 | iqCorrNeg = 1; | |
316 | } | |
317 | ||
c46917bb LR |
318 | ath_print(common, ATH_DBG_CALIBRATE, |
319 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | |
320 | ath_print(common, ATH_DBG_CALIBRATE, | |
321 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | |
322 | ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | |
323 | iqCorrNeg); | |
f1dc5600 S |
324 | |
325 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | |
326 | qCoffDenom = powerMeasQ / 64; | |
327 | ||
0b98eaaa VN |
328 | if ((powerMeasQ != 0) && (iCoffDenom != 0) && |
329 | (qCoffDenom != 0)) { | |
f1dc5600 S |
330 | iCoff = iqCorrMeas / iCoffDenom; |
331 | qCoff = powerMeasI / qCoffDenom - 64; | |
c46917bb LR |
332 | ath_print(common, ATH_DBG_CALIBRATE, |
333 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | |
334 | ath_print(common, ATH_DBG_CALIBRATE, | |
335 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | |
f1dc5600 S |
336 | |
337 | iCoff = iCoff & 0x3f; | |
c46917bb LR |
338 | ath_print(common, ATH_DBG_CALIBRATE, |
339 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | |
f1dc5600 S |
340 | if (iqCorrNeg == 0x0) |
341 | iCoff = 0x40 - iCoff; | |
342 | ||
343 | if (qCoff > 15) | |
344 | qCoff = 15; | |
345 | else if (qCoff <= -16) | |
346 | qCoff = 16; | |
347 | ||
c46917bb LR |
348 | ath_print(common, ATH_DBG_CALIBRATE, |
349 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | |
350 | i, iCoff, qCoff); | |
f1dc5600 S |
351 | |
352 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | |
353 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | |
354 | iCoff); | |
355 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | |
356 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | |
357 | qCoff); | |
c46917bb LR |
358 | ath_print(common, ATH_DBG_CALIBRATE, |
359 | "IQ Cal and Correction done for Chain %d\n", | |
360 | i); | |
f1dc5600 S |
361 | } |
362 | } | |
363 | ||
364 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | |
365 | AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); | |
366 | } | |
367 | ||
cbe61d8a | 368 | static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) |
f1dc5600 | 369 | { |
c46917bb | 370 | struct ath_common *common = ath9k_hw_common(ah); |
f1dc5600 S |
371 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; |
372 | u32 qGainMismatch, iGainMismatch, val, i; | |
373 | ||
374 | for (i = 0; i < numChains; i++) { | |
2660b81a S |
375 | iOddMeasOffset = ah->totalAdcIOddPhase[i]; |
376 | iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; | |
377 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; | |
378 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; | |
f1dc5600 | 379 | |
c46917bb LR |
380 | ath_print(common, ATH_DBG_CALIBRATE, |
381 | "Starting ADC Gain Cal for Chain %d\n", i); | |
382 | ||
383 | ath_print(common, ATH_DBG_CALIBRATE, | |
384 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | |
385 | iOddMeasOffset); | |
386 | ath_print(common, ATH_DBG_CALIBRATE, | |
387 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | |
388 | iEvenMeasOffset); | |
389 | ath_print(common, ATH_DBG_CALIBRATE, | |
390 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | |
391 | qOddMeasOffset); | |
392 | ath_print(common, ATH_DBG_CALIBRATE, | |
393 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | |
394 | qEvenMeasOffset); | |
f1dc5600 S |
395 | |
396 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | |
397 | iGainMismatch = | |
398 | ((iEvenMeasOffset * 32) / | |
399 | iOddMeasOffset) & 0x3f; | |
400 | qGainMismatch = | |
401 | ((qOddMeasOffset * 32) / | |
402 | qEvenMeasOffset) & 0x3f; | |
403 | ||
c46917bb LR |
404 | ath_print(common, ATH_DBG_CALIBRATE, |
405 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | |
406 | iGainMismatch); | |
407 | ath_print(common, ATH_DBG_CALIBRATE, | |
408 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | |
409 | qGainMismatch); | |
f1dc5600 S |
410 | |
411 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | |
412 | val &= 0xfffff000; | |
413 | val |= (qGainMismatch) | (iGainMismatch << 6); | |
414 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | |
415 | ||
c46917bb LR |
416 | ath_print(common, ATH_DBG_CALIBRATE, |
417 | "ADC Gain Cal done for Chain %d\n", i); | |
f1dc5600 S |
418 | } |
419 | } | |
420 | ||
421 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | |
422 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | |
423 | AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); | |
424 | } | |
425 | ||
cbe61d8a | 426 | static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) |
f1dc5600 | 427 | { |
c46917bb | 428 | struct ath_common *common = ath9k_hw_common(ah); |
f1dc5600 S |
429 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; |
430 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; | |
cbfe9468 | 431 | const struct ath9k_percal_data *calData = |
2660b81a | 432 | ah->cal_list_curr->calData; |
f1dc5600 S |
433 | u32 numSamples = |
434 | (1 << (calData->calCountMax + 5)) * calData->calNumSamples; | |
435 | ||
436 | for (i = 0; i < numChains; i++) { | |
2660b81a S |
437 | iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; |
438 | iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; | |
439 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; | |
440 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; | |
f1dc5600 | 441 | |
c46917bb LR |
442 | ath_print(common, ATH_DBG_CALIBRATE, |
443 | "Starting ADC DC Offset Cal for Chain %d\n", i); | |
444 | ||
445 | ath_print(common, ATH_DBG_CALIBRATE, | |
446 | "Chn %d pwr_meas_odd_i = %d\n", i, | |
447 | iOddMeasOffset); | |
448 | ath_print(common, ATH_DBG_CALIBRATE, | |
449 | "Chn %d pwr_meas_even_i = %d\n", i, | |
450 | iEvenMeasOffset); | |
451 | ath_print(common, ATH_DBG_CALIBRATE, | |
452 | "Chn %d pwr_meas_odd_q = %d\n", i, | |
453 | qOddMeasOffset); | |
454 | ath_print(common, ATH_DBG_CALIBRATE, | |
455 | "Chn %d pwr_meas_even_q = %d\n", i, | |
456 | qEvenMeasOffset); | |
f1dc5600 S |
457 | |
458 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | |
459 | numSamples) & 0x1ff; | |
460 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | |
461 | numSamples) & 0x1ff; | |
462 | ||
c46917bb LR |
463 | ath_print(common, ATH_DBG_CALIBRATE, |
464 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | |
465 | iDcMismatch); | |
466 | ath_print(common, ATH_DBG_CALIBRATE, | |
467 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | |
468 | qDcMismatch); | |
f1dc5600 S |
469 | |
470 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | |
471 | val &= 0xc0000fff; | |
472 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | |
473 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | |
474 | ||
c46917bb LR |
475 | ath_print(common, ATH_DBG_CALIBRATE, |
476 | "ADC DC Offset Cal done for Chain %d\n", i); | |
f1dc5600 S |
477 | } |
478 | ||
479 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | |
480 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | |
481 | AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); | |
482 | } | |
483 | ||
c9e27d94 | 484 | /* This is done for the currently configured channel */ |
cbe61d8a | 485 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
f1dc5600 | 486 | { |
c46917bb LR |
487 | struct ath_common *common = ath9k_hw_common(ah); |
488 | struct ieee80211_conf *conf = &common->hw->conf; | |
cbfe9468 | 489 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
f1dc5600 | 490 | |
2660b81a | 491 | if (!ah->curchan) |
c9e27d94 | 492 | return true; |
f1dc5600 S |
493 | |
494 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) | |
c9e27d94 | 495 | return true; |
f1dc5600 S |
496 | |
497 | if (currCal == NULL) | |
c9e27d94 | 498 | return true; |
f1dc5600 S |
499 | |
500 | if (currCal->calState != CAL_DONE) { | |
c46917bb LR |
501 | ath_print(common, ATH_DBG_CALIBRATE, |
502 | "Calibration state incorrect, %d\n", | |
503 | currCal->calState); | |
c9e27d94 | 504 | return true; |
f1dc5600 S |
505 | } |
506 | ||
c9e27d94 LR |
507 | if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) |
508 | return true; | |
f1dc5600 | 509 | |
c46917bb LR |
510 | ath_print(common, ATH_DBG_CALIBRATE, |
511 | "Resetting Cal %d state for channel %u\n", | |
512 | currCal->calData->calType, conf->channel->center_freq); | |
f1dc5600 | 513 | |
2660b81a | 514 | ah->curchan->CalValid &= ~currCal->calData->calType; |
f1dc5600 S |
515 | currCal->calState = CAL_WAITING; |
516 | ||
c9e27d94 | 517 | return false; |
f1dc5600 | 518 | } |
7322fd19 | 519 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); |
f1dc5600 | 520 | |
cbe61d8a | 521 | void ath9k_hw_start_nfcal(struct ath_hw *ah) |
f1dc5600 S |
522 | { |
523 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | |
524 | AR_PHY_AGC_CONTROL_ENABLE_NF); | |
525 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | |
526 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | |
527 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | |
528 | } | |
529 | ||
cbe61d8a | 530 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) |
f1dc5600 S |
531 | { |
532 | struct ath9k_nfcal_hist *h; | |
533 | int i, j; | |
534 | int32_t val; | |
535 | const u32 ar5416_cca_regs[6] = { | |
536 | AR_PHY_CCA, | |
537 | AR_PHY_CH1_CCA, | |
538 | AR_PHY_CH2_CCA, | |
539 | AR_PHY_EXT_CCA, | |
540 | AR_PHY_CH1_EXT_CCA, | |
541 | AR_PHY_CH2_EXT_CCA | |
542 | }; | |
ce143bb0 | 543 | u8 chainmask, rx_chain_status; |
f1dc5600 | 544 | |
ce143bb0 | 545 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); |
6398dc03 | 546 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
5dad40c1 | 547 | chainmask = 0x9; |
ce143bb0 SB |
548 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { |
549 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) | |
550 | chainmask = 0x1B; | |
551 | else | |
552 | chainmask = 0x09; | |
553 | } else { | |
554 | if (rx_chain_status & 0x4) | |
555 | chainmask = 0x3F; | |
556 | else if (rx_chain_status & 0x2) | |
557 | chainmask = 0x1B; | |
558 | else | |
559 | chainmask = 0x09; | |
560 | } | |
f1dc5600 | 561 | |
f1dc5600 | 562 | h = ah->nfCalHist; |
f1dc5600 S |
563 | |
564 | for (i = 0; i < NUM_NF_READINGS; i++) { | |
565 | if (chainmask & (1 << i)) { | |
566 | val = REG_READ(ah, ar5416_cca_regs[i]); | |
567 | val &= 0xFFFFFE00; | |
568 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | |
569 | REG_WRITE(ah, ar5416_cca_regs[i], val); | |
570 | } | |
571 | } | |
572 | ||
573 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | |
574 | AR_PHY_AGC_CONTROL_ENABLE_NF); | |
575 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | |
576 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | |
577 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | |
578 | ||
63a75b91 | 579 | for (j = 0; j < 5; j++) { |
f1dc5600 S |
580 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & |
581 | AR_PHY_AGC_CONTROL_NF) == 0) | |
582 | break; | |
63a75b91 | 583 | udelay(50); |
f1dc5600 S |
584 | } |
585 | ||
586 | for (i = 0; i < NUM_NF_READINGS; i++) { | |
587 | if (chainmask & (1 << i)) { | |
588 | val = REG_READ(ah, ar5416_cca_regs[i]); | |
589 | val &= 0xFFFFFE00; | |
590 | val |= (((u32) (-50) << 1) & 0x1ff); | |
591 | REG_WRITE(ah, ar5416_cca_regs[i], val); | |
592 | } | |
593 | } | |
594 | } | |
595 | ||
cbe61d8a | 596 | int16_t ath9k_hw_getnf(struct ath_hw *ah, |
f1dc5600 S |
597 | struct ath9k_channel *chan) |
598 | { | |
c46917bb | 599 | struct ath_common *common = ath9k_hw_common(ah); |
f1dc5600 S |
600 | int16_t nf, nfThresh; |
601 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; | |
602 | struct ath9k_nfcal_hist *h; | |
76061abb | 603 | struct ieee80211_channel *c = chan->chan; |
f1dc5600 S |
604 | |
605 | chan->channelFlags &= (~CHANNEL_CW_INT); | |
606 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | |
c46917bb LR |
607 | ath_print(common, ATH_DBG_CALIBRATE, |
608 | "NF did not complete in calibration window\n"); | |
f1dc5600 S |
609 | nf = 0; |
610 | chan->rawNoiseFloor = nf; | |
611 | return chan->rawNoiseFloor; | |
612 | } else { | |
613 | ath9k_hw_do_getnf(ah, nfarray); | |
614 | nf = nfarray[0]; | |
76061abb | 615 | if (getNoiseFloorThresh(ah, c->band, &nfThresh) |
f1dc5600 | 616 | && nf > nfThresh) { |
c46917bb LR |
617 | ath_print(common, ATH_DBG_CALIBRATE, |
618 | "noise floor failed detected; " | |
619 | "detected %d, threshold %d\n", | |
620 | nf, nfThresh); | |
f1dc5600 S |
621 | chan->channelFlags |= CHANNEL_CW_INT; |
622 | } | |
623 | } | |
624 | ||
f1dc5600 | 625 | h = ah->nfCalHist; |
f1dc5600 S |
626 | |
627 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | |
628 | chan->rawNoiseFloor = h[0].privNF; | |
629 | ||
630 | return chan->rawNoiseFloor; | |
631 | } | |
632 | ||
cbe61d8a | 633 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) |
f1dc5600 S |
634 | { |
635 | int i, j; | |
a59b5a5e SB |
636 | s16 noise_floor; |
637 | ||
638 | if (AR_SREV_9280(ah)) | |
639 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | |
6398dc03 | 640 | else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
a59b5a5e | 641 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; |
6170cd5c VN |
642 | else if (AR_SREV_9287(ah)) |
643 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; | |
a59b5a5e SB |
644 | else |
645 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; | |
f1dc5600 S |
646 | |
647 | for (i = 0; i < NUM_NF_READINGS; i++) { | |
648 | ah->nfCalHist[i].currIndex = 0; | |
a59b5a5e | 649 | ah->nfCalHist[i].privNF = noise_floor; |
f1dc5600 S |
650 | ah->nfCalHist[i].invalidNFcount = |
651 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | |
652 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | |
a59b5a5e | 653 | ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; |
f1dc5600 S |
654 | } |
655 | } | |
f1dc5600 S |
656 | } |
657 | ||
cbe61d8a | 658 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) |
f1dc5600 | 659 | { |
f1dc5600 S |
660 | s16 nf; |
661 | ||
5f8e077c | 662 | if (chan->rawNoiseFloor == 0) |
e56db718 LR |
663 | nf = -96; |
664 | else | |
5f8e077c | 665 | nf = chan->rawNoiseFloor; |
f1dc5600 S |
666 | |
667 | if (!ath9k_hw_nf_in_range(ah, nf)) | |
668 | nf = ATH_DEFAULT_NOISE_FLOOR; | |
669 | ||
670 | return nf; | |
671 | } | |
7322fd19 | 672 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
f1dc5600 | 673 | |
becdbc54 | 674 | static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) |
8bd1d07f | 675 | { |
0b98eaaa VN |
676 | u32 rddata; |
677 | int32_t delta, currPDADC, slope; | |
8bd1d07f SB |
678 | |
679 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | |
8bd1d07f SB |
680 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); |
681 | ||
0b98eaaa VN |
682 | if (ah->initPDADC == 0 || currPDADC == 0) { |
683 | /* | |
684 | * Zero value indicates that no frames have been transmitted yet, | |
685 | * can't do temperature compensation until frames are transmitted. | |
686 | */ | |
687 | return; | |
688 | } else { | |
689 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | |
690 | ||
691 | if (slope == 0) { /* to avoid divide by zero case */ | |
692 | delta = 0; | |
693 | } else { | |
694 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | |
695 | } | |
696 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | |
697 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | |
698 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | |
699 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | |
700 | } | |
701 | } | |
702 | ||
2b5facfe | 703 | static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) |
0b98eaaa VN |
704 | { |
705 | u32 rddata, i; | |
706 | int delta, currPDADC, regval; | |
8bd1d07f | 707 | |
2b5facfe LR |
708 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); |
709 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | |
0b98eaaa | 710 | |
2b5facfe LR |
711 | if (ah->initPDADC == 0 || currPDADC == 0) |
712 | return; | |
80b99932 | 713 | |
2b5facfe LR |
714 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) |
715 | delta = (currPDADC - ah->initPDADC + 4) / 8; | |
716 | else | |
717 | delta = (currPDADC - ah->initPDADC + 5) / 10; | |
718 | ||
719 | if (delta != ah->PDADCdelta) { | |
720 | ah->PDADCdelta = delta; | |
721 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | |
722 | regval = ah->originalGain[i] - delta; | |
723 | if (regval < 0) | |
724 | regval = 0; | |
725 | ||
726 | REG_RMW_FIELD(ah, | |
727 | AR_PHY_TX_GAIN_TBL1 + i * 4, | |
728 | AR_PHY_TX_GAIN, regval); | |
8bd1d07f SB |
729 | } |
730 | } | |
731 | } | |
732 | ||
37c3e8b9 | 733 | static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
d7e7d229 LR |
734 | { |
735 | u32 regVal; | |
736 | unsigned int i; | |
737 | u32 regList [][2] = { | |
738 | { 0x786c, 0 }, | |
739 | { 0x7854, 0 }, | |
740 | { 0x7820, 0 }, | |
741 | { 0x7824, 0 }, | |
742 | { 0x7868, 0 }, | |
743 | { 0x783c, 0 }, | |
744 | { 0x7838, 0 } , | |
745 | { 0x7828, 0 } , | |
746 | }; | |
747 | ||
748 | for (i = 0; i < ARRAY_SIZE(regList); i++) | |
749 | regList[i][1] = REG_READ(ah, regList[i][0]); | |
750 | ||
751 | regVal = REG_READ(ah, 0x7834); | |
752 | regVal &= (~(0x1)); | |
753 | REG_WRITE(ah, 0x7834, regVal); | |
754 | regVal = REG_READ(ah, 0x9808); | |
755 | regVal |= (0x1 << 27); | |
756 | REG_WRITE(ah, 0x9808, regVal); | |
757 | ||
758 | /* 786c,b23,1, pwddac=1 */ | |
759 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | |
760 | /* 7854, b5,1, pdrxtxbb=1 */ | |
761 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | |
762 | /* 7854, b7,1, pdv2i=1 */ | |
763 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | |
764 | /* 7854, b8,1, pddacinterface=1 */ | |
765 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | |
766 | /* 7824,b12,0, offcal=0 */ | |
767 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | |
768 | /* 7838, b1,0, pwddb=0 */ | |
769 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | |
770 | /* 7820,b11,0, enpacal=0 */ | |
771 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | |
772 | /* 7820,b25,1, pdpadrv1=0 */ | |
773 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); | |
774 | /* 7820,b24,0, pdpadrv2=0 */ | |
775 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); | |
776 | /* 7820,b23,0, pdpaout=0 */ | |
777 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | |
778 | /* 783c,b14-16,7, padrvgn2tab_0=7 */ | |
779 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | |
780 | /* | |
781 | * 7838,b29-31,0, padrvgn1tab_0=0 | |
782 | * does not matter since we turn it off | |
783 | */ | |
784 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | |
785 | ||
786 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); | |
787 | ||
788 | /* Set: | |
789 | * localmode=1,bmode=1,bmoderxtx=1,synthon=1, | |
790 | * txon=1,paon=1,oscon=1,synthon_force=1 | |
791 | */ | |
792 | REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); | |
793 | udelay(30); | |
794 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); | |
795 | ||
796 | /* find off_6_1; */ | |
1d9c185d | 797 | for (i = 6; i > 0; i--) { |
d7e7d229 LR |
798 | regVal = REG_READ(ah, 0x7834); |
799 | regVal |= (1 << (20 + i)); | |
800 | REG_WRITE(ah, 0x7834, regVal); | |
801 | udelay(1); | |
802 | //regVal = REG_READ(ah, 0x7834); | |
803 | regVal &= (~(0x1 << (20 + i))); | |
804 | regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) | |
805 | << (20 + i)); | |
806 | REG_WRITE(ah, 0x7834, regVal); | |
807 | } | |
808 | ||
6226811f LR |
809 | regVal = (regVal >>20) & 0x7f; |
810 | ||
811 | /* Update PA cal info */ | |
812 | if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { | |
813 | if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) | |
814 | ah->pacal_info.max_skipcount = | |
815 | 2 * ah->pacal_info.max_skipcount; | |
816 | ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; | |
817 | } else { | |
818 | ah->pacal_info.max_skipcount = 1; | |
819 | ah->pacal_info.skipcount = 0; | |
820 | ah->pacal_info.prev_offset = regVal; | |
821 | } | |
d7e7d229 LR |
822 | |
823 | regVal = REG_READ(ah, 0x7834); | |
824 | regVal |= 0x1; | |
825 | REG_WRITE(ah, 0x7834, regVal); | |
826 | regVal = REG_READ(ah, 0x9808); | |
827 | regVal &= (~(0x1 << 27)); | |
828 | REG_WRITE(ah, 0x9808, regVal); | |
829 | ||
830 | for (i = 0; i < ARRAY_SIZE(regList); i++) | |
831 | REG_WRITE(ah, regList[i][0], regList[i][1]); | |
832 | } | |
833 | ||
37c3e8b9 | 834 | static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
e7594072 | 835 | { |
c46917bb | 836 | struct ath_common *common = ath9k_hw_common(ah); |
e7594072 SB |
837 | u32 regVal; |
838 | int i, offset, offs_6_1, offs_0; | |
839 | u32 ccomp_org, reg_field; | |
840 | u32 regList[][2] = { | |
841 | { 0x786c, 0 }, | |
842 | { 0x7854, 0 }, | |
843 | { 0x7820, 0 }, | |
844 | { 0x7824, 0 }, | |
845 | { 0x7868, 0 }, | |
846 | { 0x783c, 0 }, | |
847 | { 0x7838, 0 }, | |
848 | }; | |
849 | ||
c46917bb | 850 | ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); |
a13883b0 | 851 | |
20caf0dd S |
852 | /* PA CAL is not needed for high power solution */ |
853 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == | |
854 | AR5416_EEP_TXGAIN_HIGH_POWER) | |
855 | return; | |
856 | ||
e7594072 SB |
857 | if (AR_SREV_9285_11(ah)) { |
858 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | |
859 | udelay(10); | |
860 | } | |
861 | ||
862 | for (i = 0; i < ARRAY_SIZE(regList); i++) | |
863 | regList[i][1] = REG_READ(ah, regList[i][0]); | |
864 | ||
865 | regVal = REG_READ(ah, 0x7834); | |
866 | regVal &= (~(0x1)); | |
867 | REG_WRITE(ah, 0x7834, regVal); | |
868 | regVal = REG_READ(ah, 0x9808); | |
869 | regVal |= (0x1 << 27); | |
870 | REG_WRITE(ah, 0x9808, regVal); | |
871 | ||
872 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | |
873 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | |
874 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | |
875 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | |
876 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | |
877 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | |
878 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | |
0abb0968 | 879 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); |
e7594072 SB |
880 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); |
881 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | |
882 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | |
883 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | |
884 | ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); | |
0abb0968 | 885 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); |
e7594072 SB |
886 | |
887 | REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); | |
888 | udelay(30); | |
889 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); | |
890 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); | |
891 | ||
892 | for (i = 6; i > 0; i--) { | |
893 | regVal = REG_READ(ah, 0x7834); | |
894 | regVal |= (1 << (19 + i)); | |
895 | REG_WRITE(ah, 0x7834, regVal); | |
896 | udelay(1); | |
edbf51f6 | 897 | regVal = REG_READ(ah, 0x7834); |
e7594072 SB |
898 | regVal &= (~(0x1 << (19 + i))); |
899 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); | |
900 | regVal |= (reg_field << (19 + i)); | |
901 | REG_WRITE(ah, 0x7834, regVal); | |
902 | } | |
903 | ||
904 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); | |
905 | udelay(1); | |
906 | reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); | |
907 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); | |
908 | offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); | |
909 | offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); | |
910 | ||
911 | offset = (offs_6_1<<1) | offs_0; | |
912 | offset = offset - 0; | |
913 | offs_6_1 = offset>>1; | |
914 | offs_0 = offset & 1; | |
915 | ||
a13883b0 S |
916 | if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { |
917 | if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) | |
918 | ah->pacal_info.max_skipcount = | |
919 | 2 * ah->pacal_info.max_skipcount; | |
920 | ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; | |
921 | } else { | |
922 | ah->pacal_info.max_skipcount = 1; | |
923 | ah->pacal_info.skipcount = 0; | |
924 | ah->pacal_info.prev_offset = offset; | |
925 | } | |
926 | ||
e7594072 SB |
927 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); |
928 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); | |
929 | ||
930 | regVal = REG_READ(ah, 0x7834); | |
931 | regVal |= 0x1; | |
932 | REG_WRITE(ah, 0x7834, regVal); | |
933 | regVal = REG_READ(ah, 0x9808); | |
934 | regVal &= (~(0x1 << 27)); | |
935 | REG_WRITE(ah, 0x9808, regVal); | |
936 | ||
937 | for (i = 0; i < ARRAY_SIZE(regList); i++) | |
938 | REG_WRITE(ah, regList[i][0], regList[i][1]); | |
939 | ||
940 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); | |
941 | ||
942 | if (AR_SREV_9285_11(ah)) | |
943 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | |
944 | ||
945 | } | |
946 | ||
4d001d18 LR |
947 | static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
948 | { | |
949 | if (AR_SREV_9271(ah)) { | |
950 | if (is_reset || !ah->pacal_info.skipcount) | |
37c3e8b9 | 951 | ar9271_hw_pa_cal(ah, is_reset); |
4d001d18 LR |
952 | else |
953 | ah->pacal_info.skipcount--; | |
954 | } else if (AR_SREV_9285_11_OR_LATER(ah)) { | |
955 | if (is_reset || !ah->pacal_info.skipcount) | |
37c3e8b9 | 956 | ar9285_hw_pa_cal(ah, is_reset); |
4d001d18 LR |
957 | else |
958 | ah->pacal_info.skipcount--; | |
959 | } | |
960 | } | |
961 | ||
e83a1134 LR |
962 | static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) |
963 | { | |
af6757e9 LR |
964 | if (OLC_FOR_AR9287_10_LATER) |
965 | ar9287_hw_olc_temp_compensation(ah); | |
966 | else if (OLC_FOR_AR9280_20_LATER) | |
967 | ar9280_hw_olc_temp_compensation(ah); | |
e83a1134 LR |
968 | } |
969 | ||
4e845168 | 970 | bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, |
379f0440 | 971 | u8 rxchainmask, bool longcal) |
4e845168 | 972 | { |
379f0440 | 973 | bool iscaldone = true; |
cbfe9468 | 974 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
4e845168 | 975 | |
4e845168 SB |
976 | if (currCal && |
977 | (currCal->calState == CAL_RUNNING || | |
978 | currCal->calState == CAL_WAITING)) { | |
379f0440 S |
979 | iscaldone = ath9k_hw_per_calibration(ah, chan, |
980 | rxchainmask, currCal); | |
981 | if (iscaldone) { | |
4e845168 SB |
982 | ah->cal_list_curr = currCal = currCal->calNext; |
983 | ||
984 | if (currCal->calState == CAL_WAITING) { | |
379f0440 | 985 | iscaldone = false; |
4e845168 SB |
986 | ath9k_hw_reset_calibration(ah, currCal); |
987 | } | |
988 | } | |
989 | } | |
990 | ||
d7e7d229 | 991 | /* Do NF cal only at longer intervals */ |
4e845168 | 992 | if (longcal) { |
d7e7d229 | 993 | /* Do periodic PAOffset Cal */ |
4d001d18 | 994 | ar9002_hw_pa_cal(ah, false); |
e83a1134 | 995 | ar9002_hw_olc_temp_compensation(ah); |
d7e7d229 LR |
996 | |
997 | /* Get the value from the previous NF cal and update history buffer */ | |
4e845168 | 998 | ath9k_hw_getnf(ah, chan); |
d7e7d229 LR |
999 | |
1000 | /* | |
1001 | * Load the NF from history buffer of the current channel. | |
1002 | * NF is slow time-variant, so it is OK to use a historical value. | |
1003 | */ | |
4e845168 | 1004 | ath9k_hw_loadnf(ah, ah->curchan); |
d7e7d229 | 1005 | |
4e845168 | 1006 | ath9k_hw_start_nfcal(ah); |
4e845168 SB |
1007 | } |
1008 | ||
379f0440 | 1009 | return iscaldone; |
4e845168 | 1010 | } |
7322fd19 | 1011 | EXPORT_SYMBOL(ath9k_hw_calibrate); |
4e845168 | 1012 | |
b57df129 | 1013 | /* Carrier leakage Calibration fix */ |
53bc7aa0 | 1014 | static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
4e845168 | 1015 | { |
c46917bb LR |
1016 | struct ath_common *common = ath9k_hw_common(ah); |
1017 | ||
4e845168 | 1018 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); |
db2f63f6 | 1019 | if (IS_CHAN_HT20(chan)) { |
4e845168 SB |
1020 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); |
1021 | REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | |
1022 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | |
1023 | AR_PHY_AGC_CONTROL_FLTR_CAL); | |
1024 | REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | |
1025 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | |
1026 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | |
1027 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | |
c46917bb LR |
1028 | ath_print(common, ATH_DBG_CALIBRATE, "offset " |
1029 | "calibration failed to complete in " | |
1030 | "1ms; noisy ??\n"); | |
4e845168 SB |
1031 | return false; |
1032 | } | |
1033 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | |
1034 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | |
1035 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | |
1036 | } | |
1037 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | |
1038 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | |
1039 | REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | |
1040 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | |
1041 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | |
1042 | 0, AH_WAIT_TIMEOUT)) { | |
c46917bb LR |
1043 | ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " |
1044 | "failed to complete in 1ms; noisy ??\n"); | |
4e845168 SB |
1045 | return false; |
1046 | } | |
1047 | ||
1048 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | |
1049 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | |
1050 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | |
1051 | ||
1052 | return true; | |
1053 | } | |
1054 | ||
53bc7aa0 VN |
1055 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) |
1056 | { | |
1057 | int i; | |
1058 | u_int32_t txgain_max; | |
1059 | u_int32_t clc_gain, gain_mask = 0, clc_num = 0; | |
1060 | u_int32_t reg_clc_I0, reg_clc_Q0; | |
1061 | u_int32_t i0_num = 0; | |
1062 | u_int32_t q0_num = 0; | |
1063 | u_int32_t total_num = 0; | |
1064 | u_int32_t reg_rf2g5_org; | |
1065 | bool retv = true; | |
1066 | ||
1067 | if (!(ar9285_cl_cal(ah, chan))) | |
1068 | return false; | |
1069 | ||
1070 | txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), | |
1071 | AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); | |
1072 | ||
1073 | for (i = 0; i < (txgain_max+1); i++) { | |
1074 | clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & | |
1075 | AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; | |
1076 | if (!(gain_mask & (1 << clc_gain))) { | |
1077 | gain_mask |= (1 << clc_gain); | |
1078 | clc_num++; | |
1079 | } | |
1080 | } | |
1081 | ||
1082 | for (i = 0; i < clc_num; i++) { | |
1083 | reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | |
1084 | & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; | |
1085 | reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | |
1086 | & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; | |
1087 | if (reg_clc_I0 == 0) | |
1088 | i0_num++; | |
1089 | ||
1090 | if (reg_clc_Q0 == 0) | |
1091 | q0_num++; | |
1092 | } | |
1093 | total_num = i0_num + q0_num; | |
1094 | if (total_num > AR9285_CLCAL_REDO_THRESH) { | |
1095 | reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); | |
1096 | if (AR_SREV_9285E_20(ah)) { | |
1097 | REG_WRITE(ah, AR9285_RF2G5, | |
1098 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | |
1099 | AR9285_RF2G5_IC50TX_XE_SET); | |
1100 | } else { | |
1101 | REG_WRITE(ah, AR9285_RF2G5, | |
1102 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | |
1103 | AR9285_RF2G5_IC50TX_SET); | |
1104 | } | |
1105 | retv = ar9285_cl_cal(ah, chan); | |
1106 | REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); | |
1107 | } | |
1108 | return retv; | |
1109 | } | |
1110 | ||
04d19ddd | 1111 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
f1dc5600 | 1112 | { |
c46917bb LR |
1113 | struct ath_common *common = ath9k_hw_common(ah); |
1114 | ||
b57df129 | 1115 | if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { |
4e845168 SB |
1116 | if (!ar9285_clc(ah, chan)) |
1117 | return false; | |
04d19ddd S |
1118 | } else { |
1119 | if (AR_SREV_9280_10_OR_LATER(ah)) { | |
ac88b6ec VN |
1120 | if (!AR_SREV_9287_10_OR_LATER(ah)) |
1121 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, | |
1122 | AR_PHY_ADC_CTL_OFF_PWDADC); | |
1123 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | |
1124 | AR_PHY_AGC_CONTROL_FLTR_CAL); | |
04d19ddd | 1125 | } |
edf7c060 | 1126 | |
04d19ddd | 1127 | /* Calibrate the AGC */ |
edf7c060 | 1128 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
04d19ddd S |
1129 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
1130 | AR_PHY_AGC_CONTROL_CAL); | |
edf7c060 | 1131 | |
04d19ddd S |
1132 | /* Poll for offset calibration complete */ |
1133 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | |
1134 | 0, AH_WAIT_TIMEOUT)) { | |
c46917bb LR |
1135 | ath_print(common, ATH_DBG_CALIBRATE, |
1136 | "offset calibration failed to " | |
1137 | "complete in 1ms; noisy environment?\n"); | |
edf7c060 S |
1138 | return false; |
1139 | } | |
1140 | ||
04d19ddd | 1141 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
ac88b6ec VN |
1142 | if (!AR_SREV_9287_10_OR_LATER(ah)) |
1143 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, | |
1144 | AR_PHY_ADC_CTL_OFF_PWDADC); | |
1145 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | |
1146 | AR_PHY_AGC_CONTROL_FLTR_CAL); | |
04d19ddd | 1147 | } |
edf7c060 S |
1148 | } |
1149 | ||
1150 | /* Do PA Calibration */ | |
4d001d18 | 1151 | ar9002_hw_pa_cal(ah, true); |
e7594072 | 1152 | |
04d19ddd | 1153 | /* Do NF Calibration after DC offset and other calibrations */ |
f1dc5600 | 1154 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
04d19ddd | 1155 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); |
f1dc5600 | 1156 | |
2660b81a | 1157 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
f1dc5600 | 1158 | |
04d19ddd | 1159 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ |
f1dc5600 | 1160 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { |
c9e27d94 | 1161 | if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { |
2660b81a S |
1162 | INIT_CAL(&ah->adcgain_caldata); |
1163 | INSERT_CAL(ah, &ah->adcgain_caldata); | |
c46917bb LR |
1164 | ath_print(common, ATH_DBG_CALIBRATE, |
1165 | "enabling ADC Gain Calibration.\n"); | |
f1dc5600 | 1166 | } |
c9e27d94 | 1167 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { |
2660b81a S |
1168 | INIT_CAL(&ah->adcdc_caldata); |
1169 | INSERT_CAL(ah, &ah->adcdc_caldata); | |
c46917bb LR |
1170 | ath_print(common, ATH_DBG_CALIBRATE, |
1171 | "enabling ADC DC Calibration.\n"); | |
f1dc5600 | 1172 | } |
c9e27d94 | 1173 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { |
2660b81a S |
1174 | INIT_CAL(&ah->iq_caldata); |
1175 | INSERT_CAL(ah, &ah->iq_caldata); | |
c46917bb LR |
1176 | ath_print(common, ATH_DBG_CALIBRATE, |
1177 | "enabling IQ Calibration.\n"); | |
f1dc5600 S |
1178 | } |
1179 | ||
2660b81a | 1180 | ah->cal_list_curr = ah->cal_list; |
f1dc5600 | 1181 | |
2660b81a S |
1182 | if (ah->cal_list_curr) |
1183 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | |
f1dc5600 S |
1184 | } |
1185 | ||
5f8e077c | 1186 | chan->CalValid = 0; |
f1dc5600 S |
1187 | |
1188 | return true; | |
1189 | } | |
1190 | ||
cbfe9468 | 1191 | const struct ath9k_percal_data iq_cal_multi_sample = { |
f1dc5600 S |
1192 | IQ_MISMATCH_CAL, |
1193 | MAX_CAL_SAMPLES, | |
1194 | PER_MIN_LOG_COUNT, | |
1195 | ath9k_hw_iqcal_collect, | |
1196 | ath9k_hw_iqcalibrate | |
1197 | }; | |
cbfe9468 | 1198 | const struct ath9k_percal_data iq_cal_single_sample = { |
f1dc5600 S |
1199 | IQ_MISMATCH_CAL, |
1200 | MIN_CAL_SAMPLES, | |
1201 | PER_MAX_LOG_COUNT, | |
1202 | ath9k_hw_iqcal_collect, | |
1203 | ath9k_hw_iqcalibrate | |
1204 | }; | |
cbfe9468 | 1205 | const struct ath9k_percal_data adc_gain_cal_multi_sample = { |
f1dc5600 S |
1206 | ADC_GAIN_CAL, |
1207 | MAX_CAL_SAMPLES, | |
1208 | PER_MIN_LOG_COUNT, | |
1209 | ath9k_hw_adc_gaincal_collect, | |
1210 | ath9k_hw_adc_gaincal_calibrate | |
1211 | }; | |
cbfe9468 | 1212 | const struct ath9k_percal_data adc_gain_cal_single_sample = { |
f1dc5600 S |
1213 | ADC_GAIN_CAL, |
1214 | MIN_CAL_SAMPLES, | |
1215 | PER_MAX_LOG_COUNT, | |
1216 | ath9k_hw_adc_gaincal_collect, | |
1217 | ath9k_hw_adc_gaincal_calibrate | |
1218 | }; | |
cbfe9468 | 1219 | const struct ath9k_percal_data adc_dc_cal_multi_sample = { |
f1dc5600 S |
1220 | ADC_DC_CAL, |
1221 | MAX_CAL_SAMPLES, | |
1222 | PER_MIN_LOG_COUNT, | |
1223 | ath9k_hw_adc_dccal_collect, | |
1224 | ath9k_hw_adc_dccal_calibrate | |
1225 | }; | |
cbfe9468 | 1226 | const struct ath9k_percal_data adc_dc_cal_single_sample = { |
f1dc5600 S |
1227 | ADC_DC_CAL, |
1228 | MIN_CAL_SAMPLES, | |
1229 | PER_MAX_LOG_COUNT, | |
1230 | ath9k_hw_adc_dccal_collect, | |
1231 | ath9k_hw_adc_dccal_calibrate | |
1232 | }; | |
cbfe9468 | 1233 | const struct ath9k_percal_data adc_init_dc_cal = { |
f1dc5600 S |
1234 | ADC_DC_INIT_CAL, |
1235 | MIN_CAL_SAMPLES, | |
1236 | INIT_LOG_COUNT, | |
1237 | ath9k_hw_adc_dccal_collect, | |
1238 | ath9k_hw_adc_dccal_calibrate | |
1239 | }; |