aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/calib.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-04-15 17:39:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-16 15:43:31 -0400
commit795f5e2ca672727a96bacf97075976cfe1249fcf (patch)
tree194a0f9920377520a1591638eacab205db365dbe /drivers/net/wireless/ath/ath9k/calib.c
parent0df13da4555320f6dc9b901fd5f22cf54065c708 (diff)
ath9k_hw: split calib code by hardware families
Calibration code touches phy registers and since these change the calibration code needs to be abstracted. Noise floor calibration is the only thing remaining but since the remaining calls only touch the AR_PHY_AGC_CONTROL register we'll just define that register conditionally, that will be done separately. The goal is to remove the dependency of ar9002_phy.h on calib.c This also adds stubs to be filled for AR9003 calibration code. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/calib.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c928
1 files changed, 4 insertions, 924 deletions
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index aa724c26340..085e1264fbe 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -18,9 +18,10 @@
18#include "hw-ops.h" 18#include "hw-ops.h"
19#include "ar9002_phy.h" 19#include "ar9002_phy.h"
20 20
21/* Common calibration code */
22
21/* We can tune this as we go by monitoring really low values */ 23/* We can tune this as we go by monitoring really low values */
22#define ATH9K_NF_TOO_LOW -60 24#define ATH9K_NF_TOO_LOW -60
23#define AR9285_CLCAL_REDO_THRESH 1
24 25
25/* AR5416 may return very high value (like -31 dBm), in those cases the nf 26/* 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 * is incorrect and we should use the static NF value. Later we can try to
@@ -108,44 +109,8 @@ static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
108 return true; 109 return true;
109} 110}
110 111
111static void ath9k_hw_setup_calibration(struct ath_hw *ah, 112void ath9k_hw_reset_calibration(struct ath_hw *ah,
112 struct ath9k_cal_list *currCal) 113 struct ath9k_cal_list *currCal)
113{
114 struct ath_common *common = ath9k_hw_common(ah);
115
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);
123 ath_print(common, ATH_DBG_CALIBRATE,
124 "starting IQ Mismatch Calibration\n");
125 break;
126 case ADC_GAIN_CAL:
127 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
128 ath_print(common, ATH_DBG_CALIBRATE,
129 "starting ADC Gain Calibration\n");
130 break;
131 case ADC_DC_CAL:
132 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
133 ath_print(common, ATH_DBG_CALIBRATE,
134 "starting ADC DC Calibration\n");
135 break;
136 case ADC_DC_INIT_CAL:
137 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
138 ath_print(common, ATH_DBG_CALIBRATE,
139 "starting Init ADC DC Calibration\n");
140 break;
141 }
142
143 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
144 AR_PHY_TIMING_CTRL4_DO_CAL);
145}
146
147static void ath9k_hw_reset_calibration(struct ath_hw *ah,
148 struct ath9k_cal_list *currCal)
149{ 114{
150 int i; 115 int i;
151 116
@@ -163,324 +128,6 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah,
163 ah->cal_samples = 0; 128 ah->cal_samples = 0;
164} 129}
165 130
166static bool ath9k_hw_per_calibration(struct ath_hw *ah,
167 struct ath9k_channel *ichan,
168 u8 rxchainmask,
169 struct ath9k_cal_list *currCal)
170{
171 bool iscaldone = false;
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);
178 ah->cal_samples++;
179
180 if (ah->cal_samples >= currCal->calData->calNumSamples) {
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;
190 iscaldone = true;
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 }
198
199 return iscaldone;
200}
201
202/* Assumes you are talking about the currently configured channel */
203static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
204 enum ath9k_cal_types calType)
205{
206 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
207
208 switch (calType & ah->supp_cals) {
209 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
210 return true;
211 case ADC_GAIN_CAL:
212 case ADC_DC_CAL:
213 if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
214 conf_is_ht20(conf)))
215 return true;
216 break;
217 }
218 return false;
219}
220
221static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
222{
223 int i;
224
225 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
226 ah->totalPowerMeasI[i] +=
227 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
228 ah->totalPowerMeasQ[i] +=
229 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
230 ah->totalIqCorrMeas[i] +=
231 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
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]);
237 }
238}
239
240static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
241{
242 int i;
243
244 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
245 ah->totalAdcIOddPhase[i] +=
246 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
247 ah->totalAdcIEvenPhase[i] +=
248 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
249 ah->totalAdcQOddPhase[i] +=
250 REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
251 ah->totalAdcQEvenPhase[i] +=
252 REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
253
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]);
262 }
263}
264
265static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
266{
267 int i;
268
269 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
270 ah->totalAdcDcOffsetIOddPhase[i] +=
271 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
272 ah->totalAdcDcOffsetIEvenPhase[i] +=
273 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
274 ah->totalAdcDcOffsetQOddPhase[i] +=
275 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
276 ah->totalAdcDcOffsetQEvenPhase[i] +=
277 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
278
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]);
287 }
288}
289
290static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
291{
292 struct ath_common *common = ath9k_hw_common(ah);
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++) {
299 powerMeasI = ah->totalPowerMeasI[i];
300 powerMeasQ = ah->totalPowerMeasQ[i];
301 iqCorrMeas = ah->totalIqCorrMeas[i];
302
303 ath_print(common, ATH_DBG_CALIBRATE,
304 "Starting IQ Cal and Correction for Chain %d\n",
305 i);
306
307 ath_print(common, ATH_DBG_CALIBRATE,
308 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
309 i, ah->totalIqCorrMeas[i]);
310
311 iqCorrNeg = 0;
312
313 if (iqCorrMeas > 0x80000000) {
314 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
315 iqCorrNeg = 1;
316 }
317
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);
324
325 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
326 qCoffDenom = powerMeasQ / 64;
327
328 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
329 (qCoffDenom != 0)) {
330 iCoff = iqCorrMeas / iCoffDenom;
331 qCoff = powerMeasI / qCoffDenom - 64;
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);
336
337 iCoff = iCoff & 0x3f;
338 ath_print(common, ATH_DBG_CALIBRATE,
339 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
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
348 ath_print(common, ATH_DBG_CALIBRATE,
349 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
350 i, iCoff, qCoff);
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);
358 ath_print(common, ATH_DBG_CALIBRATE,
359 "IQ Cal and Correction done for Chain %d\n",
360 i);
361 }
362 }
363
364 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
365 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
366}
367
368static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
369{
370 struct ath_common *common = ath9k_hw_common(ah);
371 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
372 u32 qGainMismatch, iGainMismatch, val, i;
373
374 for (i = 0; i < numChains; i++) {
375 iOddMeasOffset = ah->totalAdcIOddPhase[i];
376 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
377 qOddMeasOffset = ah->totalAdcQOddPhase[i];
378 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
379
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);
395
396 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
397 iGainMismatch =
398 ((iEvenMeasOffset * 32) /
399 iOddMeasOffset) & 0x3f;
400 qGainMismatch =
401 ((qOddMeasOffset * 32) /
402 qEvenMeasOffset) & 0x3f;
403
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);
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
416 ath_print(common, ATH_DBG_CALIBRATE,
417 "ADC Gain Cal done for Chain %d\n", i);
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
426static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
427{
428 struct ath_common *common = ath9k_hw_common(ah);
429 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
430 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
431 const struct ath9k_percal_data *calData =
432 ah->cal_list_curr->calData;
433 u32 numSamples =
434 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
435
436 for (i = 0; i < numChains; i++) {
437 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
438 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
439 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
440 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
441
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);
457
458 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
459 numSamples) & 0x1ff;
460 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
461 numSamples) & 0x1ff;
462
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);
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
475 ath_print(common, ATH_DBG_CALIBRATE,
476 "ADC DC Offset Cal done for Chain %d\n", i);
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
484/* This is done for the currently configured channel */ 131/* This is done for the currently configured channel */
485bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 132bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
486{ 133{
@@ -670,570 +317,3 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
670 return nf; 317 return nf;
671} 318}
672EXPORT_SYMBOL(ath9k_hw_getchan_noise); 319EXPORT_SYMBOL(ath9k_hw_getchan_noise);
673
674static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
675{
676 u32 rddata;
677 int32_t delta, currPDADC, slope;
678
679 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
680 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
681
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
703static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
704{
705 u32 rddata, i;
706 int delta, currPDADC, regval;
707
708 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
709 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
710
711 if (ah->initPDADC == 0 || currPDADC == 0)
712 return;
713
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);
729 }
730 }
731}
732
733static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
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; */
797 for (i = 6; i > 0; i--) {
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
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 }
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
834static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
835{
836 struct ath_common *common = ath9k_hw_common(ah);
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
850 ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
851
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
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);
879 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
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);
885 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
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);
897 regVal = REG_READ(ah, 0x7834);
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
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
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
947static 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)
951 ar9271_hw_pa_cal(ah, is_reset);
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)
956 ar9285_hw_pa_cal(ah, is_reset);
957 else
958 ah->pacal_info.skipcount--;
959 }
960}
961
962static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
963{
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);
968}
969
970bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
971 u8 rxchainmask, bool longcal)
972{
973 bool iscaldone = true;
974 struct ath9k_cal_list *currCal = ah->cal_list_curr;
975
976 if (currCal &&
977 (currCal->calState == CAL_RUNNING ||
978 currCal->calState == CAL_WAITING)) {
979 iscaldone = ath9k_hw_per_calibration(ah, chan,
980 rxchainmask, currCal);
981 if (iscaldone) {
982 ah->cal_list_curr = currCal = currCal->calNext;
983
984 if (currCal->calState == CAL_WAITING) {
985 iscaldone = false;
986 ath9k_hw_reset_calibration(ah, currCal);
987 }
988 }
989 }
990
991 /* Do NF cal only at longer intervals */
992 if (longcal) {
993 /* Do periodic PAOffset Cal */
994 ar9002_hw_pa_cal(ah, false);
995 ar9002_hw_olc_temp_compensation(ah);
996
997 /* Get the value from the previous NF cal and update history buffer */
998 ath9k_hw_getnf(ah, chan);
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 */
1004 ath9k_hw_loadnf(ah, ah->curchan);
1005
1006 ath9k_hw_start_nfcal(ah);
1007 }
1008
1009 return iscaldone;
1010}
1011EXPORT_SYMBOL(ath9k_hw_calibrate);
1012
1013/* Carrier leakage Calibration fix */
1014static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
1015{
1016 struct ath_common *common = ath9k_hw_common(ah);
1017
1018 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1019 if (IS_CHAN_HT20(chan)) {
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)) {
1028 ath_print(common, ATH_DBG_CALIBRATE, "offset "
1029 "calibration failed to complete in "
1030 "1ms; noisy ??\n");
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)) {
1043 ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
1044 "failed to complete in 1ms; noisy ??\n");
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
1055static 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
1111bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
1112{
1113 struct ath_common *common = ath9k_hw_common(ah);
1114
1115 if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
1116 if (!ar9285_clc(ah, chan))
1117 return false;
1118 } else {
1119 if (AR_SREV_9280_10_OR_LATER(ah)) {
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);
1125 }
1126
1127 /* Calibrate the AGC */
1128 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1129 REG_READ(ah, AR_PHY_AGC_CONTROL) |
1130 AR_PHY_AGC_CONTROL_CAL);
1131
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)) {
1135 ath_print(common, ATH_DBG_CALIBRATE,
1136 "offset calibration failed to "
1137 "complete in 1ms; noisy environment?\n");
1138 return false;
1139 }
1140
1141 if (AR_SREV_9280_10_OR_LATER(ah)) {
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);
1147 }
1148 }
1149
1150 /* Do PA Calibration */
1151 ar9002_hw_pa_cal(ah, true);
1152
1153 /* Do NF Calibration after DC offset and other calibrations */
1154 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1155 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
1156
1157 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
1158
1159 /* Enable IQ, ADC Gain and ADC DC offset CALs */
1160 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
1161 if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
1162 INIT_CAL(&ah->adcgain_caldata);
1163 INSERT_CAL(ah, &ah->adcgain_caldata);
1164 ath_print(common, ATH_DBG_CALIBRATE,
1165 "enabling ADC Gain Calibration.\n");
1166 }
1167 if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
1168 INIT_CAL(&ah->adcdc_caldata);
1169 INSERT_CAL(ah, &ah->adcdc_caldata);
1170 ath_print(common, ATH_DBG_CALIBRATE,
1171 "enabling ADC DC Calibration.\n");
1172 }
1173 if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
1174 INIT_CAL(&ah->iq_caldata);
1175 INSERT_CAL(ah, &ah->iq_caldata);
1176 ath_print(common, ATH_DBG_CALIBRATE,
1177 "enabling IQ Calibration.\n");
1178 }
1179
1180 ah->cal_list_curr = ah->cal_list;
1181
1182 if (ah->cal_list_curr)
1183 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1184 }
1185
1186 chan->CalValid = 0;
1187
1188 return true;
1189}
1190
1191const struct ath9k_percal_data iq_cal_multi_sample = {
1192 IQ_MISMATCH_CAL,
1193 MAX_CAL_SAMPLES,
1194 PER_MIN_LOG_COUNT,
1195 ath9k_hw_iqcal_collect,
1196 ath9k_hw_iqcalibrate
1197};
1198const struct ath9k_percal_data iq_cal_single_sample = {
1199 IQ_MISMATCH_CAL,
1200 MIN_CAL_SAMPLES,
1201 PER_MAX_LOG_COUNT,
1202 ath9k_hw_iqcal_collect,
1203 ath9k_hw_iqcalibrate
1204};
1205const struct ath9k_percal_data adc_gain_cal_multi_sample = {
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};
1212const struct ath9k_percal_data adc_gain_cal_single_sample = {
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};
1219const struct ath9k_percal_data adc_dc_cal_multi_sample = {
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};
1226const struct ath9k_percal_data adc_dc_cal_single_sample = {
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};
1233const struct ath9k_percal_data adc_init_dc_cal = {
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};