calib.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. /*
  2. * Copyright (c) 2008 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. #include "core.h"
  17. #include "hw.h"
  18. #include "reg.h"
  19. #include "phy.h"
  20. static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
  21. /* We can tune this as we go by monitoring really low values */
  22. #define ATH9K_NF_TOO_LOW -60
  23. /* AR5416 may return very high value (like -31 dBm), in those cases the nf
  24. * is incorrect and we should use the static NF value. Later we can try to
  25. * find out why they are reporting these values */
  26. static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
  27. {
  28. if (nf > ATH9K_NF_TOO_LOW) {
  29. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  30. "noise floor value detected (%d) is "
  31. "lower than what we think is a "
  32. "reasonable value (%d)\n",
  33. nf, ATH9K_NF_TOO_LOW);
  34. return false;
  35. }
  36. return true;
  37. }
  38. static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
  39. {
  40. int16_t nfval;
  41. int16_t sort[ATH9K_NF_CAL_HIST_MAX];
  42. int i, j;
  43. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
  44. sort[i] = nfCalBuffer[i];
  45. for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
  46. for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
  47. if (sort[j] > sort[j - 1]) {
  48. nfval = sort[j];
  49. sort[j] = sort[j - 1];
  50. sort[j - 1] = nfval;
  51. }
  52. }
  53. }
  54. nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
  55. return nfval;
  56. }
  57. static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
  58. int16_t *nfarray)
  59. {
  60. int i;
  61. for (i = 0; i < NUM_NF_READINGS; i++) {
  62. h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
  63. if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
  64. h[i].currIndex = 0;
  65. if (h[i].invalidNFcount > 0) {
  66. if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
  67. nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
  68. h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
  69. } else {
  70. h[i].invalidNFcount--;
  71. h[i].privNF = nfarray[i];
  72. }
  73. } else {
  74. h[i].privNF =
  75. ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
  76. }
  77. }
  78. return;
  79. }
  80. static void ath9k_hw_do_getnf(struct ath_hal *ah,
  81. int16_t nfarray[NUM_NF_READINGS])
  82. {
  83. int16_t nf;
  84. if (AR_SREV_9280_10_OR_LATER(ah))
  85. nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
  86. else
  87. nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
  88. if (nf & 0x100)
  89. nf = 0 - ((nf ^ 0x1ff) + 1);
  90. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  91. "NF calibrated [ctl] [chain 0] is %d\n", nf);
  92. nfarray[0] = nf;
  93. if (AR_SREV_9280_10_OR_LATER(ah))
  94. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  95. AR9280_PHY_CH1_MINCCA_PWR);
  96. else
  97. nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
  98. AR_PHY_CH1_MINCCA_PWR);
  99. if (nf & 0x100)
  100. nf = 0 - ((nf ^ 0x1ff) + 1);
  101. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  102. "NF calibrated [ctl] [chain 1] is %d\n", nf);
  103. nfarray[1] = nf;
  104. if (!AR_SREV_9280(ah)) {
  105. nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
  106. AR_PHY_CH2_MINCCA_PWR);
  107. if (nf & 0x100)
  108. nf = 0 - ((nf ^ 0x1ff) + 1);
  109. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  110. "NF calibrated [ctl] [chain 2] is %d\n", nf);
  111. nfarray[2] = nf;
  112. }
  113. if (AR_SREV_9280_10_OR_LATER(ah))
  114. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  115. AR9280_PHY_EXT_MINCCA_PWR);
  116. else
  117. nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
  118. AR_PHY_EXT_MINCCA_PWR);
  119. if (nf & 0x100)
  120. nf = 0 - ((nf ^ 0x1ff) + 1);
  121. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  122. "NF calibrated [ext] [chain 0] is %d\n", nf);
  123. nfarray[3] = nf;
  124. if (AR_SREV_9280_10_OR_LATER(ah))
  125. nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
  126. AR9280_PHY_CH1_EXT_MINCCA_PWR);
  127. else
  128. nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
  129. AR_PHY_CH1_EXT_MINCCA_PWR);
  130. if (nf & 0x100)
  131. nf = 0 - ((nf ^ 0x1ff) + 1);
  132. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  133. "NF calibrated [ext] [chain 1] is %d\n", nf);
  134. nfarray[4] = nf;
  135. if (!AR_SREV_9280(ah)) {
  136. nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
  137. AR_PHY_CH2_EXT_MINCCA_PWR);
  138. if (nf & 0x100)
  139. nf = 0 - ((nf ^ 0x1ff) + 1);
  140. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  141. "NF calibrated [ext] [chain 2] is %d\n", nf);
  142. nfarray[5] = nf;
  143. }
  144. }
  145. static bool getNoiseFloorThresh(struct ath_hal *ah,
  146. enum ieee80211_band band,
  147. int16_t *nft)
  148. {
  149. switch (band) {
  150. case IEEE80211_BAND_5GHZ:
  151. *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
  152. break;
  153. case IEEE80211_BAND_2GHZ:
  154. *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
  155. break;
  156. default:
  157. BUG_ON(1);
  158. return false;
  159. }
  160. return true;
  161. }
  162. static void ath9k_hw_setup_calibration(struct ath_hal *ah,
  163. struct hal_cal_list *currCal)
  164. {
  165. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
  166. AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
  167. currCal->calData->calCountMax);
  168. switch (currCal->calData->calType) {
  169. case IQ_MISMATCH_CAL:
  170. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
  171. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  172. "starting IQ Mismatch Calibration\n");
  173. break;
  174. case ADC_GAIN_CAL:
  175. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
  176. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  177. "starting ADC Gain Calibration\n");
  178. break;
  179. case ADC_DC_CAL:
  180. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
  181. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  182. "starting ADC DC Calibration\n");
  183. break;
  184. case ADC_DC_INIT_CAL:
  185. REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
  186. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  187. "starting Init ADC DC Calibration\n");
  188. break;
  189. }
  190. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  191. AR_PHY_TIMING_CTRL4_DO_CAL);
  192. }
  193. static void ath9k_hw_reset_calibration(struct ath_hal *ah,
  194. struct hal_cal_list *currCal)
  195. {
  196. struct ath_hal_5416 *ahp = AH5416(ah);
  197. int i;
  198. ath9k_hw_setup_calibration(ah, currCal);
  199. currCal->calState = CAL_RUNNING;
  200. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  201. ahp->ah_Meas0.sign[i] = 0;
  202. ahp->ah_Meas1.sign[i] = 0;
  203. ahp->ah_Meas2.sign[i] = 0;
  204. ahp->ah_Meas3.sign[i] = 0;
  205. }
  206. ahp->ah_CalSamples = 0;
  207. }
  208. static void ath9k_hw_per_calibration(struct ath_hal *ah,
  209. struct ath9k_channel *ichan,
  210. u8 rxchainmask,
  211. struct hal_cal_list *currCal,
  212. bool *isCalDone)
  213. {
  214. struct ath_hal_5416 *ahp = AH5416(ah);
  215. *isCalDone = false;
  216. if (currCal->calState == CAL_RUNNING) {
  217. if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
  218. AR_PHY_TIMING_CTRL4_DO_CAL)) {
  219. currCal->calData->calCollect(ah);
  220. ahp->ah_CalSamples++;
  221. if (ahp->ah_CalSamples >= currCal->calData->calNumSamples) {
  222. int i, numChains = 0;
  223. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  224. if (rxchainmask & (1 << i))
  225. numChains++;
  226. }
  227. currCal->calData->calPostProc(ah, numChains);
  228. ichan->CalValid |= currCal->calData->calType;
  229. currCal->calState = CAL_DONE;
  230. *isCalDone = true;
  231. } else {
  232. ath9k_hw_setup_calibration(ah, currCal);
  233. }
  234. }
  235. } else if (!(ichan->CalValid & currCal->calData->calType)) {
  236. ath9k_hw_reset_calibration(ah, currCal);
  237. }
  238. }
  239. /* Assumes you are talking about the currently configured channel */
  240. static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
  241. enum hal_cal_types calType)
  242. {
  243. struct ath_hal_5416 *ahp = AH5416(ah);
  244. struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
  245. switch (calType & ahp->ah_suppCals) {
  246. case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
  247. return true;
  248. case ADC_GAIN_CAL:
  249. case ADC_DC_CAL:
  250. if (conf->channel->band == IEEE80211_BAND_5GHZ &&
  251. conf_is_ht20(conf))
  252. return true;
  253. break;
  254. }
  255. return false;
  256. }
  257. static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
  258. {
  259. struct ath_hal_5416 *ahp = AH5416(ah);
  260. int i;
  261. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  262. ahp->ah_totalPowerMeasI[i] +=
  263. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  264. ahp->ah_totalPowerMeasQ[i] +=
  265. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  266. ahp->ah_totalIqCorrMeas[i] +=
  267. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  268. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  269. "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
  270. ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
  271. ahp->ah_totalPowerMeasQ[i],
  272. ahp->ah_totalIqCorrMeas[i]);
  273. }
  274. }
  275. static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
  276. {
  277. struct ath_hal_5416 *ahp = AH5416(ah);
  278. int i;
  279. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  280. ahp->ah_totalAdcIOddPhase[i] +=
  281. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  282. ahp->ah_totalAdcIEvenPhase[i] +=
  283. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  284. ahp->ah_totalAdcQOddPhase[i] +=
  285. REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  286. ahp->ah_totalAdcQEvenPhase[i] +=
  287. REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  288. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  289. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  290. "oddq=0x%08x; evenq=0x%08x;\n",
  291. ahp->ah_CalSamples, i,
  292. ahp->ah_totalAdcIOddPhase[i],
  293. ahp->ah_totalAdcIEvenPhase[i],
  294. ahp->ah_totalAdcQOddPhase[i],
  295. ahp->ah_totalAdcQEvenPhase[i]);
  296. }
  297. }
  298. static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
  299. {
  300. struct ath_hal_5416 *ahp = AH5416(ah);
  301. int i;
  302. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  303. ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
  304. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  305. ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
  306. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  307. ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
  308. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  309. ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
  310. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
  311. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  312. "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
  313. "oddq=0x%08x; evenq=0x%08x;\n",
  314. ahp->ah_CalSamples, i,
  315. ahp->ah_totalAdcDcOffsetIOddPhase[i],
  316. ahp->ah_totalAdcDcOffsetIEvenPhase[i],
  317. ahp->ah_totalAdcDcOffsetQOddPhase[i],
  318. ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
  319. }
  320. }
  321. static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
  322. {
  323. struct ath_hal_5416 *ahp = AH5416(ah);
  324. u32 powerMeasQ, powerMeasI, iqCorrMeas;
  325. u32 qCoffDenom, iCoffDenom;
  326. int32_t qCoff, iCoff;
  327. int iqCorrNeg, i;
  328. for (i = 0; i < numChains; i++) {
  329. powerMeasI = ahp->ah_totalPowerMeasI[i];
  330. powerMeasQ = ahp->ah_totalPowerMeasQ[i];
  331. iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
  332. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  333. "Starting IQ Cal and Correction for Chain %d\n",
  334. i);
  335. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  336. "Orignal: Chn %diq_corr_meas = 0x%08x\n",
  337. i, ahp->ah_totalIqCorrMeas[i]);
  338. iqCorrNeg = 0;
  339. if (iqCorrMeas > 0x80000000) {
  340. iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
  341. iqCorrNeg = 1;
  342. }
  343. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  344. "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
  345. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  346. "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
  347. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
  348. iqCorrNeg);
  349. iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
  350. qCoffDenom = powerMeasQ / 64;
  351. if (powerMeasQ != 0) {
  352. iCoff = iqCorrMeas / iCoffDenom;
  353. qCoff = powerMeasI / qCoffDenom - 64;
  354. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  355. "Chn %d iCoff = 0x%08x\n", i, iCoff);
  356. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  357. "Chn %d qCoff = 0x%08x\n", i, qCoff);
  358. iCoff = iCoff & 0x3f;
  359. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  360. "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
  361. if (iqCorrNeg == 0x0)
  362. iCoff = 0x40 - iCoff;
  363. if (qCoff > 15)
  364. qCoff = 15;
  365. else if (qCoff <= -16)
  366. qCoff = 16;
  367. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  368. "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
  369. i, iCoff, qCoff);
  370. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  371. AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
  372. iCoff);
  373. REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
  374. AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
  375. qCoff);
  376. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  377. "IQ Cal and Correction done for Chain %d\n",
  378. i);
  379. }
  380. }
  381. REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
  382. AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
  383. }
  384. static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
  385. {
  386. struct ath_hal_5416 *ahp = AH5416(ah);
  387. u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
  388. u32 qGainMismatch, iGainMismatch, val, i;
  389. for (i = 0; i < numChains; i++) {
  390. iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
  391. iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
  392. qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
  393. qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
  394. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  395. "Starting ADC Gain Cal for Chain %d\n", i);
  396. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  397. "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
  398. iOddMeasOffset);
  399. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  400. "Chn %d pwr_meas_even_i = 0x%08x\n", i,
  401. iEvenMeasOffset);
  402. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  403. "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
  404. qOddMeasOffset);
  405. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  406. "Chn %d pwr_meas_even_q = 0x%08x\n", i,
  407. qEvenMeasOffset);
  408. if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
  409. iGainMismatch =
  410. ((iEvenMeasOffset * 32) /
  411. iOddMeasOffset) & 0x3f;
  412. qGainMismatch =
  413. ((qOddMeasOffset * 32) /
  414. qEvenMeasOffset) & 0x3f;
  415. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  416. "Chn %d gain_mismatch_i = 0x%08x\n", i,
  417. iGainMismatch);
  418. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  419. "Chn %d gain_mismatch_q = 0x%08x\n", i,
  420. qGainMismatch);
  421. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  422. val &= 0xfffff000;
  423. val |= (qGainMismatch) | (iGainMismatch << 6);
  424. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  425. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  426. "ADC Gain Cal done for Chain %d\n", i);
  427. }
  428. }
  429. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  430. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  431. AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
  432. }
  433. static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
  434. {
  435. struct ath_hal_5416 *ahp = AH5416(ah);
  436. u32 iOddMeasOffset, iEvenMeasOffset, val, i;
  437. int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
  438. const struct hal_percal_data *calData =
  439. ahp->ah_cal_list_curr->calData;
  440. u32 numSamples =
  441. (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
  442. for (i = 0; i < numChains; i++) {
  443. iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
  444. iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
  445. qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
  446. qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
  447. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  448. "Starting ADC DC Offset Cal for Chain %d\n", i);
  449. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  450. "Chn %d pwr_meas_odd_i = %d\n", i,
  451. iOddMeasOffset);
  452. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  453. "Chn %d pwr_meas_even_i = %d\n", i,
  454. iEvenMeasOffset);
  455. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  456. "Chn %d pwr_meas_odd_q = %d\n", i,
  457. qOddMeasOffset);
  458. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  459. "Chn %d pwr_meas_even_q = %d\n", i,
  460. qEvenMeasOffset);
  461. iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
  462. numSamples) & 0x1ff;
  463. qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
  464. numSamples) & 0x1ff;
  465. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  466. "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
  467. iDcMismatch);
  468. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  469. "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
  470. qDcMismatch);
  471. val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
  472. val &= 0xc0000fff;
  473. val |= (qDcMismatch << 12) | (iDcMismatch << 21);
  474. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
  475. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  476. "ADC DC Offset Cal done for Chain %d\n", i);
  477. }
  478. REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
  479. REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
  480. AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
  481. }
  482. /* This is done for the currently configured channel */
  483. bool ath9k_hw_reset_calvalid(struct ath_hal *ah)
  484. {
  485. struct ath_hal_5416 *ahp = AH5416(ah);
  486. struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
  487. struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
  488. if (!ah->ah_curchan)
  489. return true;
  490. if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
  491. return true;
  492. if (currCal == NULL)
  493. return true;
  494. if (currCal->calState != CAL_DONE) {
  495. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  496. "Calibration state incorrect, %d\n",
  497. currCal->calState);
  498. return true;
  499. }
  500. if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
  501. return true;
  502. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  503. "Resetting Cal %d state for channel %u\n",
  504. currCal->calData->calType, conf->channel->center_freq);
  505. ah->ah_curchan->CalValid &= ~currCal->calData->calType;
  506. currCal->calState = CAL_WAITING;
  507. return false;
  508. }
  509. void ath9k_hw_start_nfcal(struct ath_hal *ah)
  510. {
  511. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  512. AR_PHY_AGC_CONTROL_ENABLE_NF);
  513. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
  514. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  515. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  516. }
  517. void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
  518. {
  519. struct ath9k_nfcal_hist *h;
  520. int i, j;
  521. int32_t val;
  522. const u32 ar5416_cca_regs[6] = {
  523. AR_PHY_CCA,
  524. AR_PHY_CH1_CCA,
  525. AR_PHY_CH2_CCA,
  526. AR_PHY_EXT_CCA,
  527. AR_PHY_CH1_EXT_CCA,
  528. AR_PHY_CH2_EXT_CCA
  529. };
  530. u8 chainmask;
  531. if (AR_SREV_9280(ah))
  532. chainmask = 0x1B;
  533. else
  534. chainmask = 0x3F;
  535. #ifdef ATH_NF_PER_CHAN
  536. h = chan->nfCalHist;
  537. #else
  538. h = ah->nfCalHist;
  539. #endif
  540. for (i = 0; i < NUM_NF_READINGS; i++) {
  541. if (chainmask & (1 << i)) {
  542. val = REG_READ(ah, ar5416_cca_regs[i]);
  543. val &= 0xFFFFFE00;
  544. val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
  545. REG_WRITE(ah, ar5416_cca_regs[i], val);
  546. }
  547. }
  548. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  549. AR_PHY_AGC_CONTROL_ENABLE_NF);
  550. REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
  551. AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
  552. REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  553. for (j = 0; j < 1000; j++) {
  554. if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
  555. AR_PHY_AGC_CONTROL_NF) == 0)
  556. break;
  557. udelay(10);
  558. }
  559. for (i = 0; i < NUM_NF_READINGS; i++) {
  560. if (chainmask & (1 << i)) {
  561. val = REG_READ(ah, ar5416_cca_regs[i]);
  562. val &= 0xFFFFFE00;
  563. val |= (((u32) (-50) << 1) & 0x1ff);
  564. REG_WRITE(ah, ar5416_cca_regs[i], val);
  565. }
  566. }
  567. }
  568. int16_t ath9k_hw_getnf(struct ath_hal *ah,
  569. struct ath9k_channel *chan)
  570. {
  571. int16_t nf, nfThresh;
  572. int16_t nfarray[NUM_NF_READINGS] = { 0 };
  573. struct ath9k_nfcal_hist *h;
  574. struct ieee80211_channel *c = chan->chan;
  575. u8 chainmask;
  576. if (AR_SREV_9280(ah))
  577. chainmask = 0x1B;
  578. else
  579. chainmask = 0x3F;
  580. chan->channelFlags &= (~CHANNEL_CW_INT);
  581. if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
  582. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  583. "NF did not complete in calibration window\n");
  584. nf = 0;
  585. chan->rawNoiseFloor = nf;
  586. return chan->rawNoiseFloor;
  587. } else {
  588. ath9k_hw_do_getnf(ah, nfarray);
  589. nf = nfarray[0];
  590. if (getNoiseFloorThresh(ah, c->band, &nfThresh)
  591. && nf > nfThresh) {
  592. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  593. "noise floor failed detected; "
  594. "detected %d, threshold %d\n",
  595. nf, nfThresh);
  596. chan->channelFlags |= CHANNEL_CW_INT;
  597. }
  598. }
  599. #ifdef ATH_NF_PER_CHAN
  600. h = chan->nfCalHist;
  601. #else
  602. h = ah->nfCalHist;
  603. #endif
  604. ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
  605. chan->rawNoiseFloor = h[0].privNF;
  606. return chan->rawNoiseFloor;
  607. }
  608. void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
  609. {
  610. int i, j;
  611. for (i = 0; i < NUM_NF_READINGS; i++) {
  612. ah->nfCalHist[i].currIndex = 0;
  613. ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
  614. ah->nfCalHist[i].invalidNFcount =
  615. AR_PHY_CCA_FILTERWINDOW_LENGTH;
  616. for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
  617. ah->nfCalHist[i].nfCalBuffer[j] =
  618. AR_PHY_CCA_MAX_GOOD_VALUE;
  619. }
  620. }
  621. return;
  622. }
  623. s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
  624. {
  625. struct ath9k_channel *ichan;
  626. s16 nf;
  627. ichan = ath9k_regd_check_channel(ah, chan);
  628. if (ichan == NULL) {
  629. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  630. "invalid channel %u/0x%x; no mapping\n",
  631. chan->channel, chan->channelFlags);
  632. return ATH_DEFAULT_NOISE_FLOOR;
  633. }
  634. if (ichan->rawNoiseFloor == 0) {
  635. enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
  636. nf = NOISE_FLOOR[mode];
  637. } else
  638. nf = ichan->rawNoiseFloor;
  639. if (!ath9k_hw_nf_in_range(ah, nf))
  640. nf = ATH_DEFAULT_NOISE_FLOOR;
  641. return nf;
  642. }
  643. bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
  644. u8 rxchainmask, bool longcal,
  645. bool *isCalDone)
  646. {
  647. struct ath_hal_5416 *ahp = AH5416(ah);
  648. struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
  649. struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
  650. *isCalDone = true;
  651. if (ichan == NULL) {
  652. DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
  653. "invalid channel %u/0x%x; no mapping\n",
  654. chan->channel, chan->channelFlags);
  655. return false;
  656. }
  657. if (currCal &&
  658. (currCal->calState == CAL_RUNNING ||
  659. currCal->calState == CAL_WAITING)) {
  660. ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
  661. isCalDone);
  662. if (*isCalDone) {
  663. ahp->ah_cal_list_curr = currCal = currCal->calNext;
  664. if (currCal->calState == CAL_WAITING) {
  665. *isCalDone = false;
  666. ath9k_hw_reset_calibration(ah, currCal);
  667. }
  668. }
  669. }
  670. if (longcal) {
  671. ath9k_hw_getnf(ah, ichan);
  672. ath9k_hw_loadnf(ah, ah->ah_curchan);
  673. ath9k_hw_start_nfcal(ah);
  674. if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
  675. chan->channelFlags |= CHANNEL_CW_INT;
  676. ichan->channelFlags &= ~CHANNEL_CW_INT;
  677. }
  678. }
  679. return true;
  680. }
  681. static inline void ath9k_hw_9285_pa_cal(struct ath_hal *ah)
  682. {
  683. u32 regVal;
  684. int i, offset, offs_6_1, offs_0;
  685. u32 ccomp_org, reg_field;
  686. u32 regList[][2] = {
  687. { 0x786c, 0 },
  688. { 0x7854, 0 },
  689. { 0x7820, 0 },
  690. { 0x7824, 0 },
  691. { 0x7868, 0 },
  692. { 0x783c, 0 },
  693. { 0x7838, 0 },
  694. };
  695. if (AR_SREV_9285_11(ah)) {
  696. REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
  697. udelay(10);
  698. }
  699. for (i = 0; i < ARRAY_SIZE(regList); i++)
  700. regList[i][1] = REG_READ(ah, regList[i][0]);
  701. regVal = REG_READ(ah, 0x7834);
  702. regVal &= (~(0x1));
  703. REG_WRITE(ah, 0x7834, regVal);
  704. regVal = REG_READ(ah, 0x9808);
  705. regVal |= (0x1 << 27);
  706. REG_WRITE(ah, 0x9808, regVal);
  707. REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
  708. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
  709. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
  710. REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
  711. REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
  712. REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
  713. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
  714. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
  715. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
  716. REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
  717. REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
  718. REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
  719. ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
  720. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
  721. REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
  722. udelay(30);
  723. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
  724. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
  725. for (i = 6; i > 0; i--) {
  726. regVal = REG_READ(ah, 0x7834);
  727. regVal |= (1 << (19 + i));
  728. REG_WRITE(ah, 0x7834, regVal);
  729. udelay(1);
  730. regVal = REG_READ(ah, 0x7834);
  731. regVal &= (~(0x1 << (19 + i)));
  732. reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
  733. regVal |= (reg_field << (19 + i));
  734. REG_WRITE(ah, 0x7834, regVal);
  735. }
  736. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
  737. udelay(1);
  738. reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
  739. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
  740. offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
  741. offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
  742. offset = (offs_6_1<<1) | offs_0;
  743. offset = offset - 0;
  744. offs_6_1 = offset>>1;
  745. offs_0 = offset & 1;
  746. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
  747. REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
  748. regVal = REG_READ(ah, 0x7834);
  749. regVal |= 0x1;
  750. REG_WRITE(ah, 0x7834, regVal);
  751. regVal = REG_READ(ah, 0x9808);
  752. regVal &= (~(0x1 << 27));
  753. REG_WRITE(ah, 0x9808, regVal);
  754. for (i = 0; i < ARRAY_SIZE(regList); i++)
  755. REG_WRITE(ah, regList[i][0], regList[i][1]);
  756. REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
  757. if (AR_SREV_9285_11(ah))
  758. REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
  759. }
  760. bool ath9k_hw_init_cal(struct ath_hal *ah,
  761. struct ath9k_channel *chan)
  762. {
  763. struct ath_hal_5416 *ahp = AH5416(ah);
  764. struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
  765. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  766. REG_READ(ah, AR_PHY_AGC_CONTROL) |
  767. AR_PHY_AGC_CONTROL_CAL);
  768. if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
  769. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  770. "offset calibration failed to complete in 1ms; "
  771. "noisy environment?\n");
  772. return false;
  773. }
  774. if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
  775. ath9k_hw_9285_pa_cal(ah);
  776. REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  777. REG_READ(ah, AR_PHY_AGC_CONTROL) |
  778. AR_PHY_AGC_CONTROL_NF);
  779. ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
  780. if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
  781. if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
  782. INIT_CAL(&ahp->ah_adcGainCalData);
  783. INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
  784. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  785. "enabling ADC Gain Calibration.\n");
  786. }
  787. if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
  788. INIT_CAL(&ahp->ah_adcDcCalData);
  789. INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
  790. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  791. "enabling ADC DC Calibration.\n");
  792. }
  793. if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
  794. INIT_CAL(&ahp->ah_iqCalData);
  795. INSERT_CAL(ahp, &ahp->ah_iqCalData);
  796. DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  797. "enabling IQ Calibration.\n");
  798. }
  799. ahp->ah_cal_list_curr = ahp->ah_cal_list;
  800. if (ahp->ah_cal_list_curr)
  801. ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
  802. }
  803. ichan->CalValid = 0;
  804. return true;
  805. }
  806. const struct hal_percal_data iq_cal_multi_sample = {
  807. IQ_MISMATCH_CAL,
  808. MAX_CAL_SAMPLES,
  809. PER_MIN_LOG_COUNT,
  810. ath9k_hw_iqcal_collect,
  811. ath9k_hw_iqcalibrate
  812. };
  813. const struct hal_percal_data iq_cal_single_sample = {
  814. IQ_MISMATCH_CAL,
  815. MIN_CAL_SAMPLES,
  816. PER_MAX_LOG_COUNT,
  817. ath9k_hw_iqcal_collect,
  818. ath9k_hw_iqcalibrate
  819. };
  820. const struct hal_percal_data adc_gain_cal_multi_sample = {
  821. ADC_GAIN_CAL,
  822. MAX_CAL_SAMPLES,
  823. PER_MIN_LOG_COUNT,
  824. ath9k_hw_adc_gaincal_collect,
  825. ath9k_hw_adc_gaincal_calibrate
  826. };
  827. const struct hal_percal_data adc_gain_cal_single_sample = {
  828. ADC_GAIN_CAL,
  829. MIN_CAL_SAMPLES,
  830. PER_MAX_LOG_COUNT,
  831. ath9k_hw_adc_gaincal_collect,
  832. ath9k_hw_adc_gaincal_calibrate
  833. };
  834. const struct hal_percal_data adc_dc_cal_multi_sample = {
  835. ADC_DC_CAL,
  836. MAX_CAL_SAMPLES,
  837. PER_MIN_LOG_COUNT,
  838. ath9k_hw_adc_dccal_collect,
  839. ath9k_hw_adc_dccal_calibrate
  840. };
  841. const struct hal_percal_data adc_dc_cal_single_sample = {
  842. ADC_DC_CAL,
  843. MIN_CAL_SAMPLES,
  844. PER_MAX_LOG_COUNT,
  845. ath9k_hw_adc_dccal_collect,
  846. ath9k_hw_adc_dccal_calibrate
  847. };
  848. const struct hal_percal_data adc_init_dc_cal = {
  849. ADC_DC_INIT_CAL,
  850. MIN_CAL_SAMPLES,
  851. INIT_LOG_COUNT,
  852. ath9k_hw_adc_dccal_collect,
  853. ath9k_hw_adc_dccal_calibrate
  854. };