Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / ar9003_calib.c
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
17 #include "hw.h"
18 #include "hw-ops.h"
19 #include "ar9003_phy.h"
20
21 #define MPASS   3
22 #define MAX_MEASUREMENT 8
23 #define MAX_DIFFERENCE  10
24
25 struct coeff {
26         int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
27         int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
28         int iqc_coeff[2];
29 };
30
31 enum ar9003_cal_types {
32         IQ_MISMATCH_CAL = BIT(0),
33         TEMP_COMP_CAL = BIT(1),
34 };
35
36 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
37                                         struct ath9k_cal_list *currCal)
38 {
39         struct ath_common *common = ath9k_hw_common(ah);
40
41         /* Select calibration to run */
42         switch (currCal->calData->calType) {
43         case IQ_MISMATCH_CAL:
44                 /*
45                  * Start calibration with
46                  * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
47                  */
48                 REG_RMW_FIELD(ah, AR_PHY_TIMING4,
49                               AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
50                 currCal->calData->calCountMax);
51                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
52
53                 ath_dbg(common, ATH_DBG_CALIBRATE,
54                         "starting IQ Mismatch Calibration\n");
55
56                 /* Kick-off cal */
57                 REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
58                 break;
59         case TEMP_COMP_CAL:
60                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
61                               AR_PHY_65NM_CH0_THERM_LOCAL, 1);
62                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
63                               AR_PHY_65NM_CH0_THERM_START, 1);
64
65                 ath_dbg(common, ATH_DBG_CALIBRATE,
66                         "starting Temperature Compensation Calibration\n");
67                 break;
68         }
69 }
70
71 /*
72  * Generic calibration routine.
73  * Recalibrate the lower PHY chips to account for temperature/environment
74  * changes.
75  */
76 static bool ar9003_hw_per_calibration(struct ath_hw *ah,
77                                       struct ath9k_channel *ichan,
78                                       u8 rxchainmask,
79                                       struct ath9k_cal_list *currCal)
80 {
81         struct ath9k_hw_cal_data *caldata = ah->caldata;
82         /* Cal is assumed not done until explicitly set below */
83         bool iscaldone = false;
84
85         /* Calibration in progress. */
86         if (currCal->calState == CAL_RUNNING) {
87                 /* Check to see if it has finished. */
88                 if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
89                         /*
90                         * Accumulate cal measures for active chains
91                         */
92                         currCal->calData->calCollect(ah);
93                         ah->cal_samples++;
94
95                         if (ah->cal_samples >=
96                             currCal->calData->calNumSamples) {
97                                 unsigned int i, numChains = 0;
98                                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
99                                         if (rxchainmask & (1 << i))
100                                                 numChains++;
101                                 }
102
103                                 /*
104                                 * Process accumulated data
105                                 */
106                                 currCal->calData->calPostProc(ah, numChains);
107
108                                 /* Calibration has finished. */
109                                 caldata->CalValid |= currCal->calData->calType;
110                                 currCal->calState = CAL_DONE;
111                                 iscaldone = true;
112                         } else {
113                         /*
114                          * Set-up collection of another sub-sample until we
115                          * get desired number
116                          */
117                         ar9003_hw_setup_calibration(ah, currCal);
118                         }
119                 }
120         } else if (!(caldata->CalValid & currCal->calData->calType)) {
121                 /* If current cal is marked invalid in channel, kick it off */
122                 ath9k_hw_reset_calibration(ah, currCal);
123         }
124
125         return iscaldone;
126 }
127
128 static bool ar9003_hw_calibrate(struct ath_hw *ah,
129                                 struct ath9k_channel *chan,
130                                 u8 rxchainmask,
131                                 bool longcal)
132 {
133         bool iscaldone = true;
134         struct ath9k_cal_list *currCal = ah->cal_list_curr;
135
136         /*
137          * For given calibration:
138          * 1. Call generic cal routine
139          * 2. When this cal is done (isCalDone) if we have more cals waiting
140          *    (eg after reset), mask this to upper layers by not propagating
141          *    isCalDone if it is set to TRUE.
142          *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
143          *    to be run.
144          */
145         if (currCal &&
146             (currCal->calState == CAL_RUNNING ||
147              currCal->calState == CAL_WAITING)) {
148                 iscaldone = ar9003_hw_per_calibration(ah, chan,
149                                                       rxchainmask, currCal);
150                 if (iscaldone) {
151                         ah->cal_list_curr = currCal = currCal->calNext;
152
153                         if (currCal->calState == CAL_WAITING) {
154                                 iscaldone = false;
155                                 ath9k_hw_reset_calibration(ah, currCal);
156                         }
157                 }
158         }
159
160         /* Do NF cal only at longer intervals */
161         if (longcal) {
162                 /*
163                  * Get the value from the previous NF cal and update
164                  * history buffer.
165                  */
166                 ath9k_hw_getnf(ah, chan);
167
168                 /*
169                  * Load the NF from history buffer of the current channel.
170                  * NF is slow time-variant, so it is OK to use a historical
171                  * value.
172                  */
173                 ath9k_hw_loadnf(ah, ah->curchan);
174
175                 /* start NF calibration, without updating BB NF register */
176                 ath9k_hw_start_nfcal(ah, false);
177         }
178
179         return iscaldone;
180 }
181
182 static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
183 {
184         int i;
185
186         /* Accumulate IQ cal measures for active chains */
187         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
188                 ah->totalPowerMeasI[i] +=
189                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
190                 ah->totalPowerMeasQ[i] +=
191                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
192                 ah->totalIqCorrMeas[i] +=
193                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
194                 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
195                         "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
196                         ah->cal_samples, i, ah->totalPowerMeasI[i],
197                         ah->totalPowerMeasQ[i],
198                         ah->totalIqCorrMeas[i]);
199         }
200 }
201
202 static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
203 {
204         struct ath_common *common = ath9k_hw_common(ah);
205         u32 powerMeasQ, powerMeasI, iqCorrMeas;
206         u32 qCoffDenom, iCoffDenom;
207         int32_t qCoff, iCoff;
208         int iqCorrNeg, i;
209         static const u_int32_t offset_array[3] = {
210                 AR_PHY_RX_IQCAL_CORR_B0,
211                 AR_PHY_RX_IQCAL_CORR_B1,
212                 AR_PHY_RX_IQCAL_CORR_B2,
213         };
214
215         for (i = 0; i < numChains; i++) {
216                 powerMeasI = ah->totalPowerMeasI[i];
217                 powerMeasQ = ah->totalPowerMeasQ[i];
218                 iqCorrMeas = ah->totalIqCorrMeas[i];
219
220                 ath_dbg(common, ATH_DBG_CALIBRATE,
221                         "Starting IQ Cal and Correction for Chain %d\n",
222                         i);
223
224                 ath_dbg(common, ATH_DBG_CALIBRATE,
225                         "Orignal: Chn %diq_corr_meas = 0x%08x\n",
226                         i, ah->totalIqCorrMeas[i]);
227
228                 iqCorrNeg = 0;
229
230                 if (iqCorrMeas > 0x80000000) {
231                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
232                         iqCorrNeg = 1;
233                 }
234
235                 ath_dbg(common, ATH_DBG_CALIBRATE,
236                         "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
237                 ath_dbg(common, ATH_DBG_CALIBRATE,
238                         "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
239                 ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
240                         iqCorrNeg);
241
242                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
243                 qCoffDenom = powerMeasQ / 64;
244
245                 if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
246                         iCoff = iqCorrMeas / iCoffDenom;
247                         qCoff = powerMeasI / qCoffDenom - 64;
248                         ath_dbg(common, ATH_DBG_CALIBRATE,
249                                 "Chn %d iCoff = 0x%08x\n", i, iCoff);
250                         ath_dbg(common, ATH_DBG_CALIBRATE,
251                                 "Chn %d qCoff = 0x%08x\n", i, qCoff);
252
253                         /* Force bounds on iCoff */
254                         if (iCoff >= 63)
255                                 iCoff = 63;
256                         else if (iCoff <= -63)
257                                 iCoff = -63;
258
259                         /* Negate iCoff if iqCorrNeg == 0 */
260                         if (iqCorrNeg == 0x0)
261                                 iCoff = -iCoff;
262
263                         /* Force bounds on qCoff */
264                         if (qCoff >= 63)
265                                 qCoff = 63;
266                         else if (qCoff <= -63)
267                                 qCoff = -63;
268
269                         iCoff = iCoff & 0x7f;
270                         qCoff = qCoff & 0x7f;
271
272                         ath_dbg(common, ATH_DBG_CALIBRATE,
273                                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
274                                 i, iCoff, qCoff);
275                         ath_dbg(common, ATH_DBG_CALIBRATE,
276                                 "Register offset (0x%04x) before update = 0x%x\n",
277                                 offset_array[i],
278                                 REG_READ(ah, offset_array[i]));
279
280                         REG_RMW_FIELD(ah, offset_array[i],
281                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
282                                       iCoff);
283                         REG_RMW_FIELD(ah, offset_array[i],
284                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
285                                       qCoff);
286                         ath_dbg(common, ATH_DBG_CALIBRATE,
287                                 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
288                                 offset_array[i],
289                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
290                                 REG_READ(ah, offset_array[i]));
291                         ath_dbg(common, ATH_DBG_CALIBRATE,
292                                 "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
293                                 offset_array[i],
294                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
295                                 REG_READ(ah, offset_array[i]));
296
297                         ath_dbg(common, ATH_DBG_CALIBRATE,
298                                 "IQ Cal and Correction done for Chain %d\n", i);
299                 }
300         }
301
302         REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
303                     AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
304         ath_dbg(common, ATH_DBG_CALIBRATE,
305                 "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
306                 (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
307                 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
308                 REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
309 }
310
311 static const struct ath9k_percal_data iq_cal_single_sample = {
312         IQ_MISMATCH_CAL,
313         MIN_CAL_SAMPLES,
314         PER_MAX_LOG_COUNT,
315         ar9003_hw_iqcal_collect,
316         ar9003_hw_iqcalibrate
317 };
318
319 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
320 {
321         ah->iq_caldata.calData = &iq_cal_single_sample;
322 }
323
324 /*
325  * solve 4x4 linear equation used in loopback iq cal.
326  */
327 static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
328                                    s32 sin_2phi_1,
329                                    s32 cos_2phi_1,
330                                    s32 sin_2phi_2,
331                                    s32 cos_2phi_2,
332                                    s32 mag_a0_d0,
333                                    s32 phs_a0_d0,
334                                    s32 mag_a1_d0,
335                                    s32 phs_a1_d0,
336                                    s32 solved_eq[])
337 {
338         s32 f1 = cos_2phi_1 - cos_2phi_2,
339             f3 = sin_2phi_1 - sin_2phi_2,
340             f2;
341         s32 mag_tx, phs_tx, mag_rx, phs_rx;
342         const s32 result_shift = 1 << 15;
343         struct ath_common *common = ath9k_hw_common(ah);
344
345         f2 = (f1 * f1 + f3 * f3) / result_shift;
346
347         if (!f2) {
348                 ath_dbg(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
349                 return false;
350         }
351
352         /* mag mismatch, tx */
353         mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
354         /* phs mismatch, tx */
355         phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
356
357         mag_tx = (mag_tx / f2);
358         phs_tx = (phs_tx / f2);
359
360         /* mag mismatch, rx */
361         mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
362                  result_shift;
363         /* phs mismatch, rx */
364         phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
365                  result_shift;
366
367         solved_eq[0] = mag_tx;
368         solved_eq[1] = phs_tx;
369         solved_eq[2] = mag_rx;
370         solved_eq[3] = phs_rx;
371
372         return true;
373 }
374
375 static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
376 {
377         s32 abs_i = abs(in_re),
378             abs_q = abs(in_im),
379             max_abs, min_abs;
380
381         if (abs_i > abs_q) {
382                 max_abs = abs_i;
383                 min_abs = abs_q;
384         } else {
385                 max_abs = abs_q;
386                 min_abs = abs_i;
387         }
388
389         return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
390 }
391
392 #define DELPT 32
393
394 static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
395                                    s32 chain_idx,
396                                    const s32 iq_res[],
397                                    s32 iqc_coeff[])
398 {
399         s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
400             i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
401             i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
402             i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
403         s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
404             phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
405             sin_2phi_1, cos_2phi_1,
406             sin_2phi_2, cos_2phi_2;
407         s32 mag_tx, phs_tx, mag_rx, phs_rx;
408         s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
409             q_q_coff, q_i_coff;
410         const s32 res_scale = 1 << 15;
411         const s32 delpt_shift = 1 << 8;
412         s32 mag1, mag2;
413         struct ath_common *common = ath9k_hw_common(ah);
414
415         i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
416         i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
417         iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
418
419         if (i2_m_q2_a0_d0 > 0x800)
420                 i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
421
422         if (i2_p_q2_a0_d0 > 0x800)
423                 i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
424
425         if (iq_corr_a0_d0 > 0x800)
426                 iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
427
428         i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
429         i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
430         iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
431
432         if (i2_m_q2_a0_d1 > 0x800)
433                 i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
434
435         if (i2_p_q2_a0_d1 > 0x800)
436                 i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
437
438         if (iq_corr_a0_d1 > 0x800)
439                 iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
440
441         i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
442         i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
443         iq_corr_a1_d0 = iq_res[4] & 0xfff;
444
445         if (i2_m_q2_a1_d0 > 0x800)
446                 i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
447
448         if (i2_p_q2_a1_d0 > 0x800)
449                 i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
450
451         if (iq_corr_a1_d0 > 0x800)
452                 iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
453
454         i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
455         i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
456         iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
457
458         if (i2_m_q2_a1_d1 > 0x800)
459                 i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
460
461         if (i2_p_q2_a1_d1 > 0x800)
462                 i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
463
464         if (iq_corr_a1_d1 > 0x800)
465                 iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
466
467         if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
468             (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
469                 ath_dbg(common, ATH_DBG_CALIBRATE,
470                         "Divide by 0:\n"
471                         "a0_d0=%d\n"
472                         "a0_d1=%d\n"
473                         "a2_d0=%d\n"
474                         "a1_d1=%d\n",
475                         i2_p_q2_a0_d0, i2_p_q2_a0_d1,
476                         i2_p_q2_a1_d0, i2_p_q2_a1_d1);
477                 return false;
478         }
479
480         mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
481         phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
482
483         mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
484         phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
485
486         mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
487         phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
488
489         mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
490         phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
491
492         /* w/o analog phase shift */
493         sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
494         /* w/o analog phase shift */
495         cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
496         /* w/  analog phase shift */
497         sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
498         /* w/  analog phase shift */
499         cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
500
501         /*
502          * force sin^2 + cos^2 = 1;
503          * find magnitude by approximation
504          */
505         mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
506         mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
507
508         if ((mag1 == 0) || (mag2 == 0)) {
509                 ath_dbg(common, ATH_DBG_CALIBRATE,
510                         "Divide by 0: mag1=%d, mag2=%d\n",
511                         mag1, mag2);
512                 return false;
513         }
514
515         /* normalization sin and cos by mag */
516         sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
517         cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
518         sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
519         cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
520
521         /* calculate IQ mismatch */
522         if (!ar9003_hw_solve_iq_cal(ah,
523                              sin_2phi_1, cos_2phi_1,
524                              sin_2phi_2, cos_2phi_2,
525                              mag_a0_d0, phs_a0_d0,
526                              mag_a1_d0,
527                              phs_a1_d0, solved_eq)) {
528                 ath_dbg(common, ATH_DBG_CALIBRATE,
529                         "Call to ar9003_hw_solve_iq_cal() failed.\n");
530                 return false;
531         }
532
533         mag_tx = solved_eq[0];
534         phs_tx = solved_eq[1];
535         mag_rx = solved_eq[2];
536         phs_rx = solved_eq[3];
537
538         ath_dbg(common, ATH_DBG_CALIBRATE,
539                 "chain %d: mag mismatch=%d phase mismatch=%d\n",
540                 chain_idx, mag_tx/res_scale, phs_tx/res_scale);
541
542         if (res_scale == mag_tx) {
543                 ath_dbg(common, ATH_DBG_CALIBRATE,
544                         "Divide by 0: mag_tx=%d, res_scale=%d\n",
545                         mag_tx, res_scale);
546                 return false;
547         }
548
549         /* calculate and quantize Tx IQ correction factor */
550         mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
551         phs_corr_tx = -phs_tx;
552
553         q_q_coff = (mag_corr_tx * 128 / res_scale);
554         q_i_coff = (phs_corr_tx * 256 / res_scale);
555
556         ath_dbg(common, ATH_DBG_CALIBRATE,
557                 "tx chain %d: mag corr=%d  phase corr=%d\n",
558                 chain_idx, q_q_coff, q_i_coff);
559
560         if (q_i_coff < -63)
561                 q_i_coff = -63;
562         if (q_i_coff > 63)
563                 q_i_coff = 63;
564         if (q_q_coff < -63)
565                 q_q_coff = -63;
566         if (q_q_coff > 63)
567                 q_q_coff = 63;
568
569         iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
570
571         ath_dbg(common, ATH_DBG_CALIBRATE,
572                 "tx chain %d: iq corr coeff=%x\n",
573                 chain_idx, iqc_coeff[0]);
574
575         if (-mag_rx == res_scale) {
576                 ath_dbg(common, ATH_DBG_CALIBRATE,
577                         "Divide by 0: mag_rx=%d, res_scale=%d\n",
578                         mag_rx, res_scale);
579                 return false;
580         }
581
582         /* calculate and quantize Rx IQ correction factors */
583         mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
584         phs_corr_rx = -phs_rx;
585
586         q_q_coff = (mag_corr_rx * 128 / res_scale);
587         q_i_coff = (phs_corr_rx * 256 / res_scale);
588
589         ath_dbg(common, ATH_DBG_CALIBRATE,
590                 "rx chain %d: mag corr=%d  phase corr=%d\n",
591                 chain_idx, q_q_coff, q_i_coff);
592
593         if (q_i_coff < -63)
594                 q_i_coff = -63;
595         if (q_i_coff > 63)
596                 q_i_coff = 63;
597         if (q_q_coff < -63)
598                 q_q_coff = -63;
599         if (q_q_coff > 63)
600                 q_q_coff = 63;
601
602         iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
603
604         ath_dbg(common, ATH_DBG_CALIBRATE,
605                 "rx chain %d: iq corr coeff=%x\n",
606                 chain_idx, iqc_coeff[1]);
607
608         return true;
609 }
610
611 static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
612 {
613         int diff[MPASS];
614
615         diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
616         diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
617         diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
618
619         if (diff[0] > MAX_DIFFERENCE &&
620             diff[1] > MAX_DIFFERENCE &&
621             diff[2] > MAX_DIFFERENCE)
622                 return false;
623
624         if (diff[0] <= diff[1] && diff[0] <= diff[2])
625                 *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
626         else if (diff[1] <= diff[2])
627                 *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
628         else
629                 *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;
630
631         return true;
632 }
633
634 static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
635                                                  u8 num_chains,
636                                                  struct coeff *coeff)
637 {
638         struct ath_common *common = ath9k_hw_common(ah);
639         int i, im, nmeasurement;
640         int magnitude, phase;
641         u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
642
643         memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
644         for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
645                 tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
646                                         AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
647                 if (!AR_SREV_9485(ah)) {
648                         tx_corr_coeff[i * 2][1] =
649                         tx_corr_coeff[(i * 2) + 1][1] =
650                                         AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
651
652                         tx_corr_coeff[i * 2][2] =
653                         tx_corr_coeff[(i * 2) + 1][2] =
654                                         AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
655                 }
656         }
657
658         /* Load the average of 2 passes */
659         for (i = 0; i < num_chains; i++) {
660                 if (AR_SREV_9485(ah))
661                         nmeasurement = REG_READ_FIELD(ah,
662                                         AR_PHY_TX_IQCAL_STATUS_B0_9485,
663                                         AR_PHY_CALIBRATED_GAINS_0);
664                 else
665                         nmeasurement = REG_READ_FIELD(ah,
666                                         AR_PHY_TX_IQCAL_STATUS_B0,
667                                         AR_PHY_CALIBRATED_GAINS_0);
668
669                 if (nmeasurement > MAX_MEASUREMENT)
670                         nmeasurement = MAX_MEASUREMENT;
671
672                 for (im = 0; im < nmeasurement; im++) {
673                         /*
674                          * Determine which 2 passes are closest and compute avg
675                          * magnitude
676                          */
677                         if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
678                                                                     &magnitude))
679                                 goto disable_txiqcal;
680
681                         /*
682                          * Determine which 2 passes are closest and compute avg
683                          * phase
684                          */
685                         if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
686                                                                     &phase))
687                                 goto disable_txiqcal;
688
689                         coeff->iqc_coeff[0] = (magnitude & 0x7f) |
690                                               ((phase & 0x7f) << 7);
691
692                         if ((im % 2) == 0)
693                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
694                                         AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
695                                         coeff->iqc_coeff[0]);
696                         else
697                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
698                                         AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
699                                         coeff->iqc_coeff[0]);
700                 }
701         }
702
703         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
704                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
705         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
706                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
707
708         return;
709
710 disable_txiqcal:
711         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
712                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
713         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
714                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
715
716         ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
717 }
718
719 static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
720 {
721         struct ath_common *common = ath9k_hw_common(ah);
722         static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
723                 AR_PHY_TX_IQCAL_STATUS_B0,
724                 AR_PHY_TX_IQCAL_STATUS_B1,
725                 AR_PHY_TX_IQCAL_STATUS_B2,
726         };
727         static const u32 chan_info_tab[] = {
728                 AR_PHY_CHAN_INFO_TAB_0,
729                 AR_PHY_CHAN_INFO_TAB_1,
730                 AR_PHY_CHAN_INFO_TAB_2,
731         };
732         struct coeff coeff;
733         s32 iq_res[6];
734         s32 i, j, ip, im, nmeasurement;
735         u8 nchains = get_streams(common->tx_chainmask);
736
737         for (ip = 0; ip < MPASS; ip++) {
738                 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
739                               AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
740                               DELPT);
741                 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
742                               AR_PHY_TX_IQCAL_START_DO_CAL,
743                               AR_PHY_TX_IQCAL_START_DO_CAL);
744
745                 if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
746                                    AR_PHY_TX_IQCAL_START_DO_CAL,
747                                    0, AH_WAIT_TIMEOUT)) {
748                         ath_dbg(common, ATH_DBG_CALIBRATE,
749                                 "Tx IQ Cal not complete.\n");
750                         goto TX_IQ_CAL_FAILED;
751                 }
752
753                 nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
754                                               AR_PHY_CALIBRATED_GAINS_0);
755                         if (nmeasurement > MAX_MEASUREMENT)
756                                 nmeasurement = MAX_MEASUREMENT;
757
758                 for (i = 0; i < nchains; i++) {
759                         ath_dbg(common, ATH_DBG_CALIBRATE,
760                                 "Doing Tx IQ Cal for chain %d.\n", i);
761                         for (im = 0; im < nmeasurement; im++) {
762                                 if (REG_READ(ah, txiqcal_status[i]) &
763                                              AR_PHY_TX_IQCAL_STATUS_FAILED) {
764                                         ath_dbg(common, ATH_DBG_CALIBRATE,
765                                                 "Tx IQ Cal failed for chain %d.\n", i);
766                                         goto TX_IQ_CAL_FAILED;
767                                 }
768
769                                 for (j = 0; j < 3; j++) {
770                                         u8 idx = 2 * j,
771                                            offset = 4 * (3 * im + j);
772
773                                         REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
774                                                       AR_PHY_CHAN_INFO_TAB_S2_READ,
775                                                       0);
776
777                                         /* 32 bits */
778                                         iq_res[idx] = REG_READ(ah,
779                                                         chan_info_tab[i] +
780                                                         offset);
781
782                                         REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
783                                                       AR_PHY_CHAN_INFO_TAB_S2_READ,
784                                                       1);
785
786                                         /* 16 bits */
787                                         iq_res[idx+1] = 0xffff & REG_READ(ah,
788                                                                 chan_info_tab[i] +
789                                                                 offset);
790
791                                         ath_dbg(common, ATH_DBG_CALIBRATE,
792                                                 "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
793                                                 idx, iq_res[idx], idx+1, iq_res[idx+1]);
794                                 }
795
796                                 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
797                                                             coeff.iqc_coeff)) {
798                                         ath_dbg(common, ATH_DBG_CALIBRATE,
799                                                 "Failed in calculation of IQ correction.\n");
800                                         goto TX_IQ_CAL_FAILED;
801                                 }
802                                 coeff.mag_coeff[i][im][ip] =
803                                                 coeff.iqc_coeff[0] & 0x7f;
804                                 coeff.phs_coeff[i][im][ip] =
805                                                 (coeff.iqc_coeff[0] >> 7) & 0x7f;
806
807                                 if (coeff.mag_coeff[i][im][ip] > 63)
808                                         coeff.mag_coeff[i][im][ip] -= 128;
809                                 if (coeff.phs_coeff[i][im][ip] > 63)
810                                         coeff.phs_coeff[i][im][ip] -= 128;
811
812                         }
813                 }
814         }
815
816         ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
817
818         return;
819
820 TX_IQ_CAL_FAILED:
821         ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
822 }
823
824 static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
825 {
826         u8 tx_gain_forced;
827
828         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
829                       AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
830         tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
831                                         AR_PHY_TXGAIN_FORCE);
832         if (tx_gain_forced)
833                 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
834                               AR_PHY_TXGAIN_FORCE, 0);
835
836         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
837                       AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
838 }
839
840 static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
841 {
842         struct ath_common *common = ath9k_hw_common(ah);
843         const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
844                 AR_PHY_TX_IQCAL_STATUS_B0_9485,
845                 AR_PHY_TX_IQCAL_STATUS_B1,
846                 AR_PHY_TX_IQCAL_STATUS_B2,
847         };
848         const u_int32_t chan_info_tab[] = {
849                 AR_PHY_CHAN_INFO_TAB_0,
850                 AR_PHY_CHAN_INFO_TAB_1,
851                 AR_PHY_CHAN_INFO_TAB_2,
852         };
853         struct coeff coeff;
854         s32 iq_res[6];
855         u8 num_chains = 0;
856         int i, ip, im, j;
857         int nmeasurement;
858
859         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
860                 if (ah->txchainmask & (1 << i))
861                         num_chains++;
862         }
863
864         for (ip = 0; ip < MPASS; ip++) {
865                 for (i = 0; i < num_chains; i++) {
866                         nmeasurement = REG_READ_FIELD(ah,
867                                         AR_PHY_TX_IQCAL_STATUS_B0_9485,
868                                         AR_PHY_CALIBRATED_GAINS_0);
869                         if (nmeasurement > MAX_MEASUREMENT)
870                                 nmeasurement = MAX_MEASUREMENT;
871
872                         for (im = 0; im < nmeasurement; im++) {
873                                 ath_dbg(common, ATH_DBG_CALIBRATE,
874                                         "Doing Tx IQ Cal for chain %d.\n", i);
875
876                                 if (REG_READ(ah, txiqcal_status[i]) &
877                                     AR_PHY_TX_IQCAL_STATUS_FAILED) {
878                                         ath_dbg(common, ATH_DBG_CALIBRATE,
879                                         "Tx IQ Cal failed for chain %d.\n", i);
880                                         goto tx_iqcal_fail;
881                                 }
882
883                                 for (j = 0; j < 3; j++) {
884                                         u32 idx = 2 * j, offset = 4 * (3 * im + j);
885
886                                         REG_RMW_FIELD(ah,
887                                                 AR_PHY_CHAN_INFO_MEMORY,
888                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
889                                                 0);
890
891                                         /* 32 bits */
892                                         iq_res[idx] = REG_READ(ah,
893                                                         chan_info_tab[i] +
894                                                         offset);
895
896                                         REG_RMW_FIELD(ah,
897                                                 AR_PHY_CHAN_INFO_MEMORY,
898                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
899                                                 1);
900
901                                         /* 16 bits */
902                                         iq_res[idx + 1] = 0xffff & REG_READ(ah,
903                                                           chan_info_tab[i] + offset);
904
905                                         ath_dbg(common, ATH_DBG_CALIBRATE,
906                                                 "IQ RES[%d]=0x%x"
907                                                 "IQ_RES[%d]=0x%x\n",
908                                                 idx, iq_res[idx], idx + 1,
909                                                 iq_res[idx + 1]);
910                                 }
911
912                                 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
913                                                             coeff.iqc_coeff)) {
914                                         ath_dbg(common, ATH_DBG_CALIBRATE,
915                                          "Failed in calculation of IQ correction.\n");
916                                         goto tx_iqcal_fail;
917                                 }
918
919                                 coeff.mag_coeff[i][im][ip] =
920                                                 coeff.iqc_coeff[0] & 0x7f;
921                                 coeff.phs_coeff[i][im][ip] =
922                                                 (coeff.iqc_coeff[0] >> 7) & 0x7f;
923
924                                 if (coeff.mag_coeff[i][im][ip] > 63)
925                                         coeff.mag_coeff[i][im][ip] -= 128;
926                                 if (coeff.phs_coeff[i][im][ip] > 63)
927                                         coeff.phs_coeff[i][im][ip] -= 128;
928                         }
929                 }
930         }
931         ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
932
933         return;
934
935 tx_iqcal_fail:
936         ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
937         return;
938 }
939 static bool ar9003_hw_init_cal(struct ath_hw *ah,
940                                struct ath9k_channel *chan)
941 {
942         struct ath_common *common = ath9k_hw_common(ah);
943         int val;
944
945         val = REG_READ(ah, AR_ENT_OTP);
946         ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
947
948         if (AR_SREV_9485(ah))
949                 ar9003_hw_set_chain_masks(ah, 0x1, 0x1);
950         else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
951                 ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
952         else
953                 /*
954                  * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
955                  * mode before running AGC/TxIQ cals
956                  */
957                 ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
958
959         /* Do Tx IQ Calibration */
960         if (AR_SREV_9485(ah))
961                 ar9003_hw_tx_iq_cal_run(ah);
962         else
963                 ar9003_hw_tx_iq_cal(ah);
964
965         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
966         udelay(5);
967         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
968
969         /* Calibrate the AGC */
970         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
971                   REG_READ(ah, AR_PHY_AGC_CONTROL) |
972                   AR_PHY_AGC_CONTROL_CAL);
973
974         /* Poll for offset calibration complete */
975         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
976                            0, AH_WAIT_TIMEOUT)) {
977                 ath_dbg(common, ATH_DBG_CALIBRATE,
978                         "offset calibration failed to complete in 1ms; noisy environment?\n");
979                 return false;
980         }
981
982         if (AR_SREV_9485(ah))
983                 ar9003_hw_tx_iq_cal_post_proc(ah);
984
985         /* Revert chainmasks to their original values before NF cal */
986         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
987
988         ath9k_hw_start_nfcal(ah, true);
989
990         /* Initialize list pointers */
991         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
992         ah->supp_cals = IQ_MISMATCH_CAL;
993
994         if (ah->supp_cals & IQ_MISMATCH_CAL) {
995                 INIT_CAL(&ah->iq_caldata);
996                 INSERT_CAL(ah, &ah->iq_caldata);
997                 ath_dbg(common, ATH_DBG_CALIBRATE,
998                         "enabling IQ Calibration.\n");
999         }
1000
1001         if (ah->supp_cals & TEMP_COMP_CAL) {
1002                 INIT_CAL(&ah->tempCompCalData);
1003                 INSERT_CAL(ah, &ah->tempCompCalData);
1004                 ath_dbg(common, ATH_DBG_CALIBRATE,
1005                         "enabling Temperature Compensation Calibration.\n");
1006         }
1007
1008         /* Initialize current pointer to first element in list */
1009         ah->cal_list_curr = ah->cal_list;
1010
1011         if (ah->cal_list_curr)
1012                 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1013
1014         if (ah->caldata)
1015                 ah->caldata->CalValid = 0;
1016
1017         return true;
1018 }
1019
1020 void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
1021 {
1022         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1023         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1024
1025         priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
1026         priv_ops->init_cal = ar9003_hw_init_cal;
1027         priv_ops->setup_calibration = ar9003_hw_setup_calibration;
1028
1029         ops->calibrate = ar9003_hw_calibrate;
1030 }