1/* 2 * Copyright (c) 2008-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 "hw-ops.h" 19#include "ar9002_phy.h" 20 21#define AR9285_CLCAL_REDO_THRESH 1 22 23static void ar9002_hw_setup_calibration(struct ath_hw *ah, 24 struct ath9k_cal_list *currCal) 25{ 26 struct ath_common *common = ath9k_hw_common(ah); 27 28 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), 29 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, 30 currCal->calData->calCountMax); 31 32 switch (currCal->calData->calType) { 33 case IQ_MISMATCH_CAL: 34 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); 35 ath_print(common, ATH_DBG_CALIBRATE, 36 "starting IQ Mismatch Calibration\n"); 37 break; 38 case ADC_GAIN_CAL: 39 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); 40 ath_print(common, ATH_DBG_CALIBRATE, 41 "starting ADC Gain Calibration\n"); 42 break; 43 case ADC_DC_CAL: 44 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); 45 ath_print(common, ATH_DBG_CALIBRATE, 46 "starting ADC DC Calibration\n"); 47 break; 48 case ADC_DC_INIT_CAL: 49 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); 50 ath_print(common, ATH_DBG_CALIBRATE, 51 "starting Init ADC DC Calibration\n"); 52 break; 53 case TEMP_COMP_CAL: 54 break; /* Not supported */ 55 } 56 57 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 58 AR_PHY_TIMING_CTRL4_DO_CAL); 59} 60 61static bool ar9002_hw_per_calibration(struct ath_hw *ah, 62 struct ath9k_channel *ichan, 63 u8 rxchainmask, 64 struct ath9k_cal_list *currCal) 65{ 66 struct ath9k_hw_cal_data *caldata = ah->caldata; 67 bool iscaldone = false; 68 69 if (currCal->calState == CAL_RUNNING) { 70 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & 71 AR_PHY_TIMING_CTRL4_DO_CAL)) { 72 73 currCal->calData->calCollect(ah); 74 ah->cal_samples++; 75 76 if (ah->cal_samples >= 77 currCal->calData->calNumSamples) { 78 int i, numChains = 0; 79 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 80 if (rxchainmask & (1 << i)) 81 numChains++; 82 } 83 84 currCal->calData->calPostProc(ah, numChains); 85 caldata->CalValid |= currCal->calData->calType; 86 currCal->calState = CAL_DONE; 87 iscaldone = true; 88 } else { 89 ar9002_hw_setup_calibration(ah, currCal); 90 } 91 } 92 } else if (!(caldata->CalValid & currCal->calData->calType)) { 93 ath9k_hw_reset_calibration(ah, currCal); 94 } 95 96 return iscaldone; 97} 98 99/* Assumes you are talking about the currently configured channel */ 100static bool ar9002_hw_iscal_supported(struct ath_hw *ah, 101 enum ath9k_cal_types calType) 102{ 103 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 104 105 switch (calType & ah->supp_cals) { 106 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ 107 return true; 108 case ADC_GAIN_CAL: 109 case ADC_DC_CAL: 110 if (!(conf->channel->band == IEEE80211_BAND_2GHZ && 111 conf_is_ht20(conf))) 112 return true; 113 break; 114 } 115 return false; 116} 117 118static void ar9002_hw_iqcal_collect(struct ath_hw *ah) 119{ 120 int i; 121 122 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 123 ah->totalPowerMeasI[i] += 124 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 125 ah->totalPowerMeasQ[i] += 126 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 127 ah->totalIqCorrMeas[i] += 128 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 129 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 130 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", 131 ah->cal_samples, i, ah->totalPowerMeasI[i], 132 ah->totalPowerMeasQ[i], 133 ah->totalIqCorrMeas[i]); 134 } 135} 136 137static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) 138{ 139 int i; 140 141 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 142 ah->totalAdcIOddPhase[i] += 143 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 144 ah->totalAdcIEvenPhase[i] += 145 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 146 ah->totalAdcQOddPhase[i] += 147 REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 148 ah->totalAdcQEvenPhase[i] += 149 REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 150 151 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 152 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 153 "oddq=0x%08x; evenq=0x%08x;\n", 154 ah->cal_samples, i, 155 ah->totalAdcIOddPhase[i], 156 ah->totalAdcIEvenPhase[i], 157 ah->totalAdcQOddPhase[i], 158 ah->totalAdcQEvenPhase[i]); 159 } 160} 161 162static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) 163{ 164 int i; 165 166 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 167 ah->totalAdcDcOffsetIOddPhase[i] += 168 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 169 ah->totalAdcDcOffsetIEvenPhase[i] += 170 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 171 ah->totalAdcDcOffsetQOddPhase[i] += 172 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 173 ah->totalAdcDcOffsetQEvenPhase[i] += 174 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 175 176 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 177 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 178 "oddq=0x%08x; evenq=0x%08x;\n", 179 ah->cal_samples, i, 180 ah->totalAdcDcOffsetIOddPhase[i], 181 ah->totalAdcDcOffsetIEvenPhase[i], 182 ah->totalAdcDcOffsetQOddPhase[i], 183 ah->totalAdcDcOffsetQEvenPhase[i]); 184 } 185} 186 187static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) 188{ 189 struct ath_common *common = ath9k_hw_common(ah); 190 u32 powerMeasQ, powerMeasI, iqCorrMeas; 191 u32 qCoffDenom, iCoffDenom; 192 int32_t qCoff, iCoff; 193 int iqCorrNeg, i; 194 195 for (i = 0; i < numChains; i++) { 196 powerMeasI = ah->totalPowerMeasI[i]; 197 powerMeasQ = ah->totalPowerMeasQ[i]; 198 iqCorrMeas = ah->totalIqCorrMeas[i]; 199 200 ath_print(common, ATH_DBG_CALIBRATE, 201 "Starting IQ Cal and Correction for Chain %d\n", 202 i); 203 204 ath_print(common, ATH_DBG_CALIBRATE, 205 "Orignal: Chn %diq_corr_meas = 0x%08x\n", 206 i, ah->totalIqCorrMeas[i]); 207 208 iqCorrNeg = 0; 209 210 if (iqCorrMeas > 0x80000000) { 211 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; 212 iqCorrNeg = 1; 213 } 214 215 ath_print(common, ATH_DBG_CALIBRATE, 216 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); 217 ath_print(common, ATH_DBG_CALIBRATE, 218 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); 219 ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", 220 iqCorrNeg); 221 222 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; 223 qCoffDenom = powerMeasQ / 64; 224 225 if ((powerMeasQ != 0) && (iCoffDenom != 0) && 226 (qCoffDenom != 0)) { 227 iCoff = iqCorrMeas / iCoffDenom; 228 qCoff = powerMeasI / qCoffDenom - 64; 229 ath_print(common, ATH_DBG_CALIBRATE, 230 "Chn %d iCoff = 0x%08x\n", i, iCoff); 231 ath_print(common, ATH_DBG_CALIBRATE, 232 "Chn %d qCoff = 0x%08x\n", i, qCoff); 233 234 iCoff = iCoff & 0x3f; 235 ath_print(common, ATH_DBG_CALIBRATE, 236 "New: Chn %d iCoff = 0x%08x\n", i, iCoff); 237 if (iqCorrNeg == 0x0) 238 iCoff = 0x40 - iCoff; 239 240 if (qCoff > 15) 241 qCoff = 15; 242 else if (qCoff <= -16) 243 qCoff = -16; 244 245 ath_print(common, ATH_DBG_CALIBRATE, 246 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", 247 i, iCoff, qCoff); 248 249 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 250 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, 251 iCoff); 252 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 253 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, 254 qCoff); 255 ath_print(common, ATH_DBG_CALIBRATE, 256 "IQ Cal and Correction done for Chain %d\n", 257 i); 258 } 259 } 260 261 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 262 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); 263} 264 265static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) 266{ 267 struct ath_common *common = ath9k_hw_common(ah); 268 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; 269 u32 qGainMismatch, iGainMismatch, val, i; 270 271 for (i = 0; i < numChains; i++) { 272 iOddMeasOffset = ah->totalAdcIOddPhase[i]; 273 iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; 274 qOddMeasOffset = ah->totalAdcQOddPhase[i]; 275 qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; 276 277 ath_print(common, ATH_DBG_CALIBRATE, 278 "Starting ADC Gain Cal for Chain %d\n", i); 279 280 ath_print(common, ATH_DBG_CALIBRATE, 281 "Chn %d pwr_meas_odd_i = 0x%08x\n", i, 282 iOddMeasOffset); 283 ath_print(common, ATH_DBG_CALIBRATE, 284 "Chn %d pwr_meas_even_i = 0x%08x\n", i, 285 iEvenMeasOffset); 286 ath_print(common, ATH_DBG_CALIBRATE, 287 "Chn %d pwr_meas_odd_q = 0x%08x\n", i, 288 qOddMeasOffset); 289 ath_print(common, ATH_DBG_CALIBRATE, 290 "Chn %d pwr_meas_even_q = 0x%08x\n", i, 291 qEvenMeasOffset); 292 293 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { 294 iGainMismatch = 295 ((iEvenMeasOffset * 32) / 296 iOddMeasOffset) & 0x3f; 297 qGainMismatch = 298 ((qOddMeasOffset * 32) / 299 qEvenMeasOffset) & 0x3f; 300 301 ath_print(common, ATH_DBG_CALIBRATE, 302 "Chn %d gain_mismatch_i = 0x%08x\n", i, 303 iGainMismatch); 304 ath_print(common, ATH_DBG_CALIBRATE, 305 "Chn %d gain_mismatch_q = 0x%08x\n", i, 306 qGainMismatch); 307 308 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 309 val &= 0xfffff000; 310 val |= (qGainMismatch) | (iGainMismatch << 6); 311 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 312 313 ath_print(common, ATH_DBG_CALIBRATE, 314 "ADC Gain Cal done for Chain %d\n", i); 315 } 316 } 317 318 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 319 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 320 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); 321} 322 323static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) 324{ 325 struct ath_common *common = ath9k_hw_common(ah); 326 u32 iOddMeasOffset, iEvenMeasOffset, val, i; 327 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; 328 const struct ath9k_percal_data *calData = 329 ah->cal_list_curr->calData; 330 u32 numSamples = 331 (1 << (calData->calCountMax + 5)) * calData->calNumSamples; 332 333 for (i = 0; i < numChains; i++) { 334 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; 335 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; 336 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; 337 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; 338 339 ath_print(common, ATH_DBG_CALIBRATE, 340 "Starting ADC DC Offset Cal for Chain %d\n", i); 341 342 ath_print(common, ATH_DBG_CALIBRATE, 343 "Chn %d pwr_meas_odd_i = %d\n", i, 344 iOddMeasOffset); 345 ath_print(common, ATH_DBG_CALIBRATE, 346 "Chn %d pwr_meas_even_i = %d\n", i, 347 iEvenMeasOffset); 348 ath_print(common, ATH_DBG_CALIBRATE, 349 "Chn %d pwr_meas_odd_q = %d\n", i, 350 qOddMeasOffset); 351 ath_print(common, ATH_DBG_CALIBRATE, 352 "Chn %d pwr_meas_even_q = %d\n", i, 353 qEvenMeasOffset); 354 355 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / 356 numSamples) & 0x1ff; 357 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / 358 numSamples) & 0x1ff; 359 360 ath_print(common, ATH_DBG_CALIBRATE, 361 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, 362 iDcMismatch); 363 ath_print(common, ATH_DBG_CALIBRATE, 364 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, 365 qDcMismatch); 366 367 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 368 val &= 0xc0000fff; 369 val |= (qDcMismatch << 12) | (iDcMismatch << 21); 370 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 371 372 ath_print(common, ATH_DBG_CALIBRATE, 373 "ADC DC Offset Cal done for Chain %d\n", i); 374 } 375 376 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 377 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 378 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); 379} 380 381static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) 382{ 383 u32 rddata; 384 int32_t delta, currPDADC, slope; 385 386 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 387 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 388 389 if (ah->initPDADC == 0 || currPDADC == 0) { 390 /* 391 * Zero value indicates that no frames have been transmitted 392 * yet, can't do temperature compensation until frames are 393 * transmitted. 394 */ 395 return; 396 } else { 397 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); 398 399 if (slope == 0) { /* to avoid divide by zero case */ 400 delta = 0; 401 } else { 402 delta = ((currPDADC - ah->initPDADC)*4) / slope; 403 } 404 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, 405 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 406 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, 407 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 408 } 409} 410 411static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) 412{ 413 u32 rddata, i; 414 int delta, currPDADC, regval; 415 416 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 417 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 418 419 if (ah->initPDADC == 0 || currPDADC == 0) 420 return; 421 422 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) 423 delta = (currPDADC - ah->initPDADC + 4) / 8; 424 else 425 delta = (currPDADC - ah->initPDADC + 5) / 10; 426 427 if (delta != ah->PDADCdelta) { 428 ah->PDADCdelta = delta; 429 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { 430 regval = ah->originalGain[i] - delta; 431 if (regval < 0) 432 regval = 0; 433 434 REG_RMW_FIELD(ah, 435 AR_PHY_TX_GAIN_TBL1 + i * 4, 436 AR_PHY_TX_GAIN, regval); 437 } 438 } 439} 440 441static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) 442{ 443 u32 regVal; 444 unsigned int i; 445 u32 regList[][2] = { 446 { 0x786c, 0 }, 447 { 0x7854, 0 }, 448 { 0x7820, 0 }, 449 { 0x7824, 0 }, 450 { 0x7868, 0 }, 451 { 0x783c, 0 }, 452 { 0x7838, 0 } , 453 { 0x7828, 0 } , 454 }; 455 456 for (i = 0; i < ARRAY_SIZE(regList); i++) 457 regList[i][1] = REG_READ(ah, regList[i][0]); 458 459 regVal = REG_READ(ah, 0x7834); 460 regVal &= (~(0x1)); 461 REG_WRITE(ah, 0x7834, regVal); 462 regVal = REG_READ(ah, 0x9808); 463 regVal |= (0x1 << 27); 464 REG_WRITE(ah, 0x9808, regVal); 465 466 /* 786c,b23,1, pwddac=1 */ 467 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 468 /* 7854, b5,1, pdrxtxbb=1 */ 469 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 470 /* 7854, b7,1, pdv2i=1 */ 471 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 472 /* 7854, b8,1, pddacinterface=1 */ 473 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 474 /* 7824,b12,0, offcal=0 */ 475 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 476 /* 7838, b1,0, pwddb=0 */ 477 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 478 /* 7820,b11,0, enpacal=0 */ 479 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 480 /* 7820,b25,1, pdpadrv1=0 */ 481 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 482 /* 7820,b24,0, pdpadrv2=0 */ 483 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 484 /* 7820,b23,0, pdpaout=0 */ 485 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 486 /* 783c,b14-16,7, padrvgn2tab_0=7 */ 487 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 488 /* 489 * 7838,b29-31,0, padrvgn1tab_0=0 490 * does not matter since we turn it off 491 */ 492 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 493 494 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); 495 496 /* Set: 497 * localmode=1,bmode=1,bmoderxtx=1,synthon=1, 498 * txon=1,paon=1,oscon=1,synthon_force=1 499 */ 500 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 501 udelay(30); 502 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); 503 504 /* find off_6_1; */ 505 for (i = 6; i > 0; i--) { 506 regVal = REG_READ(ah, 0x7834); 507 regVal |= (1 << (20 + i)); 508 REG_WRITE(ah, 0x7834, regVal); 509 udelay(1); 510 /* regVal = REG_READ(ah, 0x7834); */ 511 regVal &= (~(0x1 << (20 + i))); 512 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) 513 << (20 + i)); 514 REG_WRITE(ah, 0x7834, regVal); 515 } 516 517 regVal = (regVal >> 20) & 0x7f; 518 519 /* Update PA cal info */ 520 if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { 521 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) 522 ah->pacal_info.max_skipcount = 523 2 * ah->pacal_info.max_skipcount; 524 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; 525 } else { 526 ah->pacal_info.max_skipcount = 1; 527 ah->pacal_info.skipcount = 0; 528 ah->pacal_info.prev_offset = regVal; 529 } 530 531 ENABLE_REGWRITE_BUFFER(ah); 532 533 regVal = REG_READ(ah, 0x7834); 534 regVal |= 0x1; 535 REG_WRITE(ah, 0x7834, regVal); 536 regVal = REG_READ(ah, 0x9808); 537 regVal &= (~(0x1 << 27)); 538 REG_WRITE(ah, 0x9808, regVal); 539 540 for (i = 0; i < ARRAY_SIZE(regList); i++) 541 REG_WRITE(ah, regList[i][0], regList[i][1]); 542 543 REGWRITE_BUFFER_FLUSH(ah); 544 DISABLE_REGWRITE_BUFFER(ah); 545} 546 547static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) 548{ 549 struct ath_common *common = ath9k_hw_common(ah); 550 u32 regVal; 551 int i, offset, offs_6_1, offs_0; 552 u32 ccomp_org, reg_field; 553 u32 regList[][2] = { 554 { 0x786c, 0 }, 555 { 0x7854, 0 }, 556 { 0x7820, 0 }, 557 { 0x7824, 0 }, 558 { 0x7868, 0 }, 559 { 0x783c, 0 }, 560 { 0x7838, 0 }, 561 }; 562 563 ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); 564 565 /* PA CAL is not needed for high power solution */ 566 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 567 AR5416_EEP_TXGAIN_HIGH_POWER) 568 return; 569 570 if (AR_SREV_9285_11(ah)) { 571 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); 572 udelay(10); 573 } 574 575 for (i = 0; i < ARRAY_SIZE(regList); i++) 576 regList[i][1] = REG_READ(ah, regList[i][0]); 577 578 regVal = REG_READ(ah, 0x7834); 579 regVal &= (~(0x1)); 580 REG_WRITE(ah, 0x7834, regVal); 581 regVal = REG_READ(ah, 0x9808); 582 regVal |= (0x1 << 27); 583 REG_WRITE(ah, 0x9808, regVal); 584 585 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 586 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 587 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 588 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 589 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 590 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 591 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 592 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 593 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 594 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 595 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 596 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 597 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); 598 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); 599 600 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 601 udelay(30); 602 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); 603 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); 604 605 for (i = 6; i > 0; i--) { 606 regVal = REG_READ(ah, 0x7834); 607 regVal |= (1 << (19 + i)); 608 REG_WRITE(ah, 0x7834, regVal); 609 udelay(1); 610 regVal = REG_READ(ah, 0x7834); 611 regVal &= (~(0x1 << (19 + i))); 612 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); 613 regVal |= (reg_field << (19 + i)); 614 REG_WRITE(ah, 0x7834, regVal); 615 } 616 617 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); 618 udelay(1); 619 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); 620 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); 621 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); 622 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); 623 624 offset = (offs_6_1<<1) | offs_0; 625 offset = offset - 0; 626 offs_6_1 = offset>>1; 627 offs_0 = offset & 1; 628 629 if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { 630 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) 631 ah->pacal_info.max_skipcount = 632 2 * ah->pacal_info.max_skipcount; 633 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; 634 } else { 635 ah->pacal_info.max_skipcount = 1; 636 ah->pacal_info.skipcount = 0; 637 ah->pacal_info.prev_offset = offset; 638 } 639 640 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); 641 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); 642 643 regVal = REG_READ(ah, 0x7834); 644 regVal |= 0x1; 645 REG_WRITE(ah, 0x7834, regVal); 646 regVal = REG_READ(ah, 0x9808); 647 regVal &= (~(0x1 << 27)); 648 REG_WRITE(ah, 0x9808, regVal); 649 650 for (i = 0; i < ARRAY_SIZE(regList); i++) 651 REG_WRITE(ah, regList[i][0], regList[i][1]); 652 653 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); 654 655 if (AR_SREV_9285_11(ah)) 656 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); 657 658} 659 660static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) 661{ 662 if (AR_SREV_9271(ah)) { 663 if (is_reset || !ah->pacal_info.skipcount) 664 ar9271_hw_pa_cal(ah, is_reset); 665 else 666 ah->pacal_info.skipcount--; 667 } else if (AR_SREV_9285_11_OR_LATER(ah)) { 668 if (is_reset || !ah->pacal_info.skipcount) 669 ar9285_hw_pa_cal(ah, is_reset); 670 else 671 ah->pacal_info.skipcount--; 672 } 673} 674 675static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) 676{ 677 if (OLC_FOR_AR9287_10_LATER) 678 ar9287_hw_olc_temp_compensation(ah); 679 else if (OLC_FOR_AR9280_20_LATER) 680 ar9280_hw_olc_temp_compensation(ah); 681} 682 683static bool ar9002_hw_calibrate(struct ath_hw *ah, 684 struct ath9k_channel *chan, 685 u8 rxchainmask, 686 bool longcal) 687{ 688 bool iscaldone = true; 689 struct ath9k_cal_list *currCal = ah->cal_list_curr; 690 bool nfcal, nfcal_pending = false; 691 692 nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); 693 if (ah->caldata) 694 nfcal_pending = ah->caldata->nfcal_pending; 695 696 if (currCal && !nfcal && 697 (currCal->calState == CAL_RUNNING || 698 currCal->calState == CAL_WAITING)) { 699 iscaldone = ar9002_hw_per_calibration(ah, chan, 700 rxchainmask, currCal); 701 if (iscaldone) { 702 ah->cal_list_curr = currCal = currCal->calNext; 703 704 if (currCal->calState == CAL_WAITING) { 705 iscaldone = false; 706 ath9k_hw_reset_calibration(ah, currCal); 707 } 708 } 709 } 710 711 /* Do NF cal only at longer intervals */ 712 if (longcal || nfcal_pending) { 713 /* 714 * Get the value from the previous NF cal and update 715 * history buffer. 716 */ 717 if (ath9k_hw_getnf(ah, chan)) { 718 /* 719 * Load the NF from history buffer of the current 720 * channel. 721 * NF is slow time-variant, so it is OK to use a 722 * historical value. 723 */ 724 ath9k_hw_loadnf(ah, ah->curchan); 725 } 726 727 if (longcal) { 728 ath9k_hw_start_nfcal(ah, false); 729 /* Do periodic PAOffset Cal */ 730 ar9002_hw_pa_cal(ah, false); 731 ar9002_hw_olc_temp_compensation(ah); 732 } 733 } 734 735 return iscaldone; 736} 737 738/* Carrier leakage Calibration fix */ 739static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) 740{ 741 struct ath_common *common = ath9k_hw_common(ah); 742 743 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 744 if (IS_CHAN_HT20(chan)) { 745 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 746 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 747 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 748 AR_PHY_AGC_CONTROL_FLTR_CAL); 749 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 750 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 751 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 752 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { 753 ath_print(common, ATH_DBG_CALIBRATE, "offset " 754 "calibration failed to complete in " 755 "1ms; noisy ??\n"); 756 return false; 757 } 758 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 759 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 760 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 761 } 762 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 763 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 764 REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 765 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 766 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 767 0, AH_WAIT_TIMEOUT)) { 768 ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " 769 "failed to complete in 1ms; noisy ??\n"); 770 return false; 771 } 772 773 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 774 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 775 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 776 777 return true; 778} 779 780static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan) 781{ 782 int i; 783 u_int32_t txgain_max; 784 u_int32_t clc_gain, gain_mask = 0, clc_num = 0; 785 u_int32_t reg_clc_I0, reg_clc_Q0; 786 u_int32_t i0_num = 0; 787 u_int32_t q0_num = 0; 788 u_int32_t total_num = 0; 789 u_int32_t reg_rf2g5_org; 790 bool retv = true; 791 792 if (!(ar9285_hw_cl_cal(ah, chan))) 793 return false; 794 795 txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), 796 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); 797 798 for (i = 0; i < (txgain_max+1); i++) { 799 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & 800 AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; 801 if (!(gain_mask & (1 << clc_gain))) { 802 gain_mask |= (1 << clc_gain); 803 clc_num++; 804 } 805 } 806 807 for (i = 0; i < clc_num; i++) { 808 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) 809 & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; 810 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) 811 & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; 812 if (reg_clc_I0 == 0) 813 i0_num++; 814 815 if (reg_clc_Q0 == 0) 816 q0_num++; 817 } 818 total_num = i0_num + q0_num; 819 if (total_num > AR9285_CLCAL_REDO_THRESH) { 820 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); 821 if (AR_SREV_9285E_20(ah)) { 822 REG_WRITE(ah, AR9285_RF2G5, 823 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | 824 AR9285_RF2G5_IC50TX_XE_SET); 825 } else { 826 REG_WRITE(ah, AR9285_RF2G5, 827 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | 828 AR9285_RF2G5_IC50TX_SET); 829 } 830 retv = ar9285_hw_cl_cal(ah, chan); 831 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); 832 } 833 return retv; 834} 835 836static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) 837{ 838 struct ath_common *common = ath9k_hw_common(ah); 839 840 if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { 841 if (!ar9285_hw_clc(ah, chan)) 842 return false; 843 } else { 844 if (AR_SREV_9280_10_OR_LATER(ah)) { 845 if (!AR_SREV_9287_10_OR_LATER(ah)) 846 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, 847 AR_PHY_ADC_CTL_OFF_PWDADC); 848 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 849 AR_PHY_AGC_CONTROL_FLTR_CAL); 850 } 851 852 /* Calibrate the AGC */ 853 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 854 REG_READ(ah, AR_PHY_AGC_CONTROL) | 855 AR_PHY_AGC_CONTROL_CAL); 856 857 /* Poll for offset calibration complete */ 858 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 859 AR_PHY_AGC_CONTROL_CAL, 860 0, AH_WAIT_TIMEOUT)) { 861 ath_print(common, ATH_DBG_CALIBRATE, 862 "offset calibration failed to " 863 "complete in 1ms; noisy environment?\n"); 864 return false; 865 } 866 867 if (AR_SREV_9280_10_OR_LATER(ah)) { 868 if (!AR_SREV_9287_10_OR_LATER(ah)) 869 REG_SET_BIT(ah, AR_PHY_ADC_CTL, 870 AR_PHY_ADC_CTL_OFF_PWDADC); 871 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 872 AR_PHY_AGC_CONTROL_FLTR_CAL); 873 } 874 } 875 876 /* Do PA Calibration */ 877 ar9002_hw_pa_cal(ah, true); 878 879 /* Do NF Calibration after DC offset and other calibrations */ 880 ath9k_hw_start_nfcal(ah, true); 881 882 if (ah->caldata) 883 ah->caldata->nfcal_pending = true; 884 885 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; 886 887 /* Enable IQ, ADC Gain and ADC DC offset CALs */ 888 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { 889 if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) { 890 INIT_CAL(&ah->adcgain_caldata); 891 INSERT_CAL(ah, &ah->adcgain_caldata); 892 ath_print(common, ATH_DBG_CALIBRATE, 893 "enabling ADC Gain Calibration.\n"); 894 } 895 if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) { 896 INIT_CAL(&ah->adcdc_caldata); 897 INSERT_CAL(ah, &ah->adcdc_caldata); 898 ath_print(common, ATH_DBG_CALIBRATE, 899 "enabling ADC DC Calibration.\n"); 900 } 901 if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { 902 INIT_CAL(&ah->iq_caldata); 903 INSERT_CAL(ah, &ah->iq_caldata); 904 ath_print(common, ATH_DBG_CALIBRATE, 905 "enabling IQ Calibration.\n"); 906 } 907 908 ah->cal_list_curr = ah->cal_list; 909 910 if (ah->cal_list_curr) 911 ath9k_hw_reset_calibration(ah, ah->cal_list_curr); 912 } 913 914 if (ah->caldata) 915 ah->caldata->CalValid = 0; 916 917 return true; 918} 919 920static const struct ath9k_percal_data iq_cal_multi_sample = { 921 IQ_MISMATCH_CAL, 922 MAX_CAL_SAMPLES, 923 PER_MIN_LOG_COUNT, 924 ar9002_hw_iqcal_collect, 925 ar9002_hw_iqcalibrate 926}; 927static const struct ath9k_percal_data iq_cal_single_sample = { 928 IQ_MISMATCH_CAL, 929 MIN_CAL_SAMPLES, 930 PER_MAX_LOG_COUNT, 931 ar9002_hw_iqcal_collect, 932 ar9002_hw_iqcalibrate 933}; 934static const struct ath9k_percal_data adc_gain_cal_multi_sample = { 935 ADC_GAIN_CAL, 936 MAX_CAL_SAMPLES, 937 PER_MIN_LOG_COUNT, 938 ar9002_hw_adc_gaincal_collect, 939 ar9002_hw_adc_gaincal_calibrate 940}; 941static const struct ath9k_percal_data adc_gain_cal_single_sample = { 942 ADC_GAIN_CAL, 943 MIN_CAL_SAMPLES, 944 PER_MAX_LOG_COUNT, 945 ar9002_hw_adc_gaincal_collect, 946 ar9002_hw_adc_gaincal_calibrate 947}; 948static const struct ath9k_percal_data adc_dc_cal_multi_sample = { 949 ADC_DC_CAL, 950 MAX_CAL_SAMPLES, 951 PER_MIN_LOG_COUNT, 952 ar9002_hw_adc_dccal_collect, 953 ar9002_hw_adc_dccal_calibrate 954}; 955static const struct ath9k_percal_data adc_dc_cal_single_sample = { 956 ADC_DC_CAL, 957 MIN_CAL_SAMPLES, 958 PER_MAX_LOG_COUNT, 959 ar9002_hw_adc_dccal_collect, 960 ar9002_hw_adc_dccal_calibrate 961}; 962static const struct ath9k_percal_data adc_init_dc_cal = { 963 ADC_DC_INIT_CAL, 964 MIN_CAL_SAMPLES, 965 INIT_LOG_COUNT, 966 ar9002_hw_adc_dccal_collect, 967 ar9002_hw_adc_dccal_calibrate 968}; 969 970static void ar9002_hw_init_cal_settings(struct ath_hw *ah) 971{ 972 if (AR_SREV_9100(ah)) { 973 ah->iq_caldata.calData = &iq_cal_multi_sample; 974 ah->supp_cals = IQ_MISMATCH_CAL; 975 return; 976 } 977 978 if (AR_SREV_9160_10_OR_LATER(ah)) { 979 if (AR_SREV_9280_10_OR_LATER(ah)) { 980 ah->iq_caldata.calData = &iq_cal_single_sample; 981 ah->adcgain_caldata.calData = 982 &adc_gain_cal_single_sample; 983 ah->adcdc_caldata.calData = 984 &adc_dc_cal_single_sample; 985 ah->adcdc_calinitdata.calData = 986 &adc_init_dc_cal; 987 } else { 988 ah->iq_caldata.calData = &iq_cal_multi_sample; 989 ah->adcgain_caldata.calData = 990 &adc_gain_cal_multi_sample; 991 ah->adcdc_caldata.calData = 992 &adc_dc_cal_multi_sample; 993 ah->adcdc_calinitdata.calData = 994 &adc_init_dc_cal; 995 } 996 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 997 } 998} 999 1000void ar9002_hw_attach_calib_ops(struct ath_hw *ah) 1001{ 1002 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 1003 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 1004 1005 priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; 1006 priv_ops->init_cal = ar9002_hw_init_cal; 1007 priv_ops->setup_calibration = ar9002_hw_setup_calibration; 1008 priv_ops->iscal_supported = ar9002_hw_iscal_supported; 1009 1010 ops->calibrate = ar9002_hw_calibrate; 1011} 1012