ar9003_calib.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (c) 2010 Atheros Communications Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "hw.h"
  17. #include "hw-ops.h"
  18. #include "ar9003_phy.h"
  19. static void ar9003_hw_setup_calibration(struct ath_hw *ah,
  20. struct ath9k_cal_list *currCal)
  21. {
  22. /* TODO */
  23. }
  24. static bool ar9003_hw_calibrate(struct ath_hw *ah,
  25. struct ath9k_channel *chan,
  26. u8 rxchainmask,
  27. bool longcal)
  28. {
  29. /* TODO */
  30. return false;
  31. }
  32. static bool ar9003_hw_init_cal(struct ath_hw *ah,
  33. struct ath9k_channel *chan)
  34. {
  35. /* TODO */
  36. return false;
  37. }
  38. static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
  39. {
  40. int i;
  41. /* Accumulate IQ cal measures for active chains */
  42. for (i = 0; i < AR5416_MAX_CHAINS; i++) {
  43. ah->totalPowerMeasI[i] +=
  44. REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
  45. ah->totalPowerMeasQ[i] +=
  46. REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
  47. ah->totalIqCorrMeas[i] +=
  48. (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
  49. ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
  50. "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
  51. ah->cal_samples, i, ah->totalPowerMeasI[i],
  52. ah->totalPowerMeasQ[i],
  53. ah->totalIqCorrMeas[i]);
  54. }
  55. }
  56. static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
  57. {
  58. struct ath_common *common = ath9k_hw_common(ah);
  59. u32 powerMeasQ, powerMeasI, iqCorrMeas;
  60. u32 qCoffDenom, iCoffDenom;
  61. int32_t qCoff, iCoff;
  62. int iqCorrNeg, i;
  63. const u_int32_t offset_array[3] = {
  64. AR_PHY_RX_IQCAL_CORR_B0,
  65. AR_PHY_RX_IQCAL_CORR_B1,
  66. AR_PHY_RX_IQCAL_CORR_B2,
  67. };
  68. for (i = 0; i < numChains; i++) {
  69. powerMeasI = ah->totalPowerMeasI[i];
  70. powerMeasQ = ah->totalPowerMeasQ[i];
  71. iqCorrMeas = ah->totalIqCorrMeas[i];
  72. ath_print(common, ATH_DBG_CALIBRATE,
  73. "Starting IQ Cal and Correction for Chain %d\n",
  74. i);
  75. ath_print(common, ATH_DBG_CALIBRATE,
  76. "Orignal: Chn %diq_corr_meas = 0x%08x\n",
  77. i, ah->totalIqCorrMeas[i]);
  78. iqCorrNeg = 0;
  79. if (iqCorrMeas > 0x80000000) {
  80. iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
  81. iqCorrNeg = 1;
  82. }
  83. ath_print(common, ATH_DBG_CALIBRATE,
  84. "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
  85. ath_print(common, ATH_DBG_CALIBRATE,
  86. "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
  87. ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
  88. iqCorrNeg);
  89. iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
  90. qCoffDenom = powerMeasQ / 64;
  91. if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
  92. iCoff = iqCorrMeas / iCoffDenom;
  93. qCoff = powerMeasI / qCoffDenom - 64;
  94. ath_print(common, ATH_DBG_CALIBRATE,
  95. "Chn %d iCoff = 0x%08x\n", i, iCoff);
  96. ath_print(common, ATH_DBG_CALIBRATE,
  97. "Chn %d qCoff = 0x%08x\n", i, qCoff);
  98. /* Force bounds on iCoff */
  99. if (iCoff >= 63)
  100. iCoff = 63;
  101. else if (iCoff <= -63)
  102. iCoff = -63;
  103. /* Negate iCoff if iqCorrNeg == 0 */
  104. if (iqCorrNeg == 0x0)
  105. iCoff = -iCoff;
  106. /* Force bounds on qCoff */
  107. if (qCoff >= 63)
  108. qCoff = 63;
  109. else if (qCoff <= -63)
  110. qCoff = -63;
  111. iCoff = iCoff & 0x7f;
  112. qCoff = qCoff & 0x7f;
  113. ath_print(common, ATH_DBG_CALIBRATE,
  114. "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
  115. i, iCoff, qCoff);
  116. ath_print(common, ATH_DBG_CALIBRATE,
  117. "Register offset (0x%04x) "
  118. "before update = 0x%x\n",
  119. offset_array[i],
  120. REG_READ(ah, offset_array[i]));
  121. REG_RMW_FIELD(ah, offset_array[i],
  122. AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
  123. iCoff);
  124. REG_RMW_FIELD(ah, offset_array[i],
  125. AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
  126. qCoff);
  127. ath_print(common, ATH_DBG_CALIBRATE,
  128. "Register offset (0x%04x) QI COFF "
  129. "(bitfields 0x%08x) after update = 0x%x\n",
  130. offset_array[i],
  131. AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
  132. REG_READ(ah, offset_array[i]));
  133. ath_print(common, ATH_DBG_CALIBRATE,
  134. "Register offset (0x%04x) QQ COFF "
  135. "(bitfields 0x%08x) after update = 0x%x\n",
  136. offset_array[i],
  137. AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
  138. REG_READ(ah, offset_array[i]));
  139. ath_print(common, ATH_DBG_CALIBRATE,
  140. "IQ Cal and Correction done for Chain %d\n",
  141. i);
  142. }
  143. }
  144. REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
  145. AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
  146. ath_print(common, ATH_DBG_CALIBRATE,
  147. "IQ Cal and Correction (offset 0x%04x) enabled "
  148. "(bit position 0x%08x). New Value 0x%08x\n",
  149. (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
  150. AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
  151. REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
  152. }
  153. static const struct ath9k_percal_data iq_cal_single_sample = {
  154. IQ_MISMATCH_CAL,
  155. MIN_CAL_SAMPLES,
  156. PER_MAX_LOG_COUNT,
  157. ar9003_hw_iqcal_collect,
  158. ar9003_hw_iqcalibrate
  159. };
  160. static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
  161. {
  162. ah->iq_caldata.calData = &iq_cal_single_sample;
  163. ah->supp_cals = IQ_MISMATCH_CAL;
  164. }
  165. static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
  166. enum ath9k_cal_types calType)
  167. {
  168. /* TODO */
  169. return false;
  170. }
  171. void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
  172. {
  173. struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
  174. struct ath_hw_ops *ops = ath9k_hw_ops(ah);
  175. priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
  176. priv_ops->init_cal = ar9003_hw_init_cal;
  177. priv_ops->setup_calibration = ar9003_hw_setup_calibration;
  178. priv_ops->iscal_supported = ar9003_hw_iscal_supported;
  179. ops->calibrate = ar9003_hw_calibrate;
  180. }