ar9003_calib.c revision 6497827f53eb90dcf30c5d6414c83238f722e8ae
1795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez/*
2795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * Copyright (c) 2010 Atheros Communications Inc.
3795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez *
4795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * Permission to use, copy, modify, and/or distribute this software for any
5795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * purpose with or without fee is hereby granted, provided that the above
6795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * copyright notice and this permission notice appear in all copies.
7795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez *
8795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez */
16795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
17795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez#include "hw.h"
18795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez#include "hw-ops.h"
19795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez#include "ar9003_phy.h"
20795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
216497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkauenum ar9003_cal_types {
226497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau	IQ_MISMATCH_CAL = BIT(0),
236497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau	TEMP_COMP_CAL = BIT(1),
246497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau};
256497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau
26795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguezstatic void ar9003_hw_setup_calibration(struct ath_hw *ah,
27795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez					struct ath9k_cal_list *currCal)
28795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez{
294b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
304b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez
314b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	/* Select calibration to run */
324b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	switch (currCal->calData->calType) {
334b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	case IQ_MISMATCH_CAL:
344b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		/*
354b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		 * Start calibration with
364b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		 * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
374b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		 */
384b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		REG_RMW_FIELD(ah, AR_PHY_TIMING4,
394b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez			      AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
404b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		currCal->calData->calCountMax);
414b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
424b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez
434b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
444b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez			  "starting IQ Mismatch Calibration\n");
454b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez
464b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		/* Kick-off cal */
474b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
484b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		break;
494b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	case TEMP_COMP_CAL:
504b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
514b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez			      AR_PHY_65NM_CH0_THERM_LOCAL, 1);
524b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
534b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez			      AR_PHY_65NM_CH0_THERM_START, 1);
544b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez
554b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
564b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez			  "starting Temperature Compensation Calibration\n");
574b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez		break;
584b01931e3a3ca5ec49604e2b279b8b9dd42fbe4cLuis R. Rodriguez	}
59795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez}
60795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
61df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez/*
62df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez * Generic calibration routine.
63df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez * Recalibrate the lower PHY chips to account for temperature/environment
64df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez * changes.
65df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez */
66df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic bool ar9003_hw_per_calibration(struct ath_hw *ah,
67df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				      struct ath9k_channel *ichan,
68df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				      u8 rxchainmask,
69df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				      struct ath9k_cal_list *currCal)
70df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez{
7120bd2a0952d01ba82a99b3f22d46e3832c255529Felix Fietkau	struct ath9k_hw_cal_data *caldata = ah->caldata;
72df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Cal is assumed not done until explicitly set below */
73df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	bool iscaldone = false;
74df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
75df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Calibration in progress. */
76df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (currCal->calState == CAL_RUNNING) {
77df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		/* Check to see if it has finished. */
78df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
79df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			/*
80df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			* Accumulate cal measures for active chains
81df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			*/
82df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			currCal->calData->calCollect(ah);
83df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ah->cal_samples++;
84df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
85df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			if (ah->cal_samples >=
86df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			    currCal->calData->calNumSamples) {
87df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				unsigned int i, numChains = 0;
88df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				for (i = 0; i < AR9300_MAX_CHAINS; i++) {
89df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez					if (rxchainmask & (1 << i))
90df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez						numChains++;
91df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				}
92df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
93df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				/*
94df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				* Process accumulated data
95df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				*/
96df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				currCal->calData->calPostProc(ah, numChains);
97df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
98df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				/* Calibration has finished. */
9920bd2a0952d01ba82a99b3f22d46e3832c255529Felix Fietkau				caldata->CalValid |= currCal->calData->calType;
100df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				currCal->calState = CAL_DONE;
101df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				iscaldone = true;
102df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			} else {
103df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			/*
104df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			 * Set-up collection of another sub-sample until we
105df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			 * get desired number
106df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			 */
107df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ar9003_hw_setup_calibration(ah, currCal);
108df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			}
109df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		}
11020bd2a0952d01ba82a99b3f22d46e3832c255529Felix Fietkau	} else if (!(caldata->CalValid & currCal->calData->calType)) {
111df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		/* If current cal is marked invalid in channel, kick it off */
112df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath9k_hw_reset_calibration(ah, currCal);
113df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
114df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
115df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return iscaldone;
116df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez}
117df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
118795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguezstatic bool ar9003_hw_calibrate(struct ath_hw *ah,
119795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez				struct ath9k_channel *chan,
120795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez				u8 rxchainmask,
121795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez				bool longcal)
122795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez{
123df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	bool iscaldone = true;
124df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	struct ath9k_cal_list *currCal = ah->cal_list_curr;
125df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
126df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/*
127df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * For given calibration:
128df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * 1. Call generic cal routine
129df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * 2. When this cal is done (isCalDone) if we have more cals waiting
130df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 *    (eg after reset), mask this to upper layers by not propagating
131df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 *    isCalDone if it is set to TRUE.
132df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
133df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 *    to be run.
134df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 */
135df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (currCal &&
136df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    (currCal->calState == CAL_RUNNING ||
137df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	     currCal->calState == CAL_WAITING)) {
138df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		iscaldone = ar9003_hw_per_calibration(ah, chan,
139df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez						      rxchainmask, currCal);
140df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		if (iscaldone) {
141df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ah->cal_list_curr = currCal = currCal->calNext;
142df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
143df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			if (currCal->calState == CAL_WAITING) {
144df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				iscaldone = false;
145df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				ath9k_hw_reset_calibration(ah, currCal);
146df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			}
147df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		}
148df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
149795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
150df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Do NF cal only at longer intervals */
151df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (longcal) {
152df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		/*
1539369746050e838c57e357f0caa552386ad65a82dFelix Fietkau		 * Get the value from the previous NF cal and update
1549369746050e838c57e357f0caa552386ad65a82dFelix Fietkau		 * history buffer.
1559369746050e838c57e357f0caa552386ad65a82dFelix Fietkau		 */
1569369746050e838c57e357f0caa552386ad65a82dFelix Fietkau		ath9k_hw_getnf(ah, chan);
1579369746050e838c57e357f0caa552386ad65a82dFelix Fietkau
1589369746050e838c57e357f0caa552386ad65a82dFelix Fietkau		/*
159df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 * Load the NF from history buffer of the current channel.
160df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 * NF is slow time-variant, so it is OK to use a historical
161df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 * value.
162df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 */
163df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath9k_hw_loadnf(ah, ah->curchan);
164df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
165df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		/* start NF calibration, without updating BB NF register */
16600c86590e36bd42574821b43b5124d75f30df9ddFelix Fietkau		ath9k_hw_start_nfcal(ah, false);
167df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
168df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
169df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return iscaldone;
170795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez}
171795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
172590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguezstatic void ar9003_hw_iqcal_collect(struct ath_hw *ah)
173590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez{
174590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	int i;
175590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
176590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	/* Accumulate IQ cal measures for active chains */
177590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
178590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ah->totalPowerMeasI[i] +=
179590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
180590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ah->totalPowerMeasQ[i] +=
181590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
182590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ah->totalIqCorrMeas[i] +=
183590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
184590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
185590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
186590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  ah->cal_samples, i, ah->totalPowerMeasI[i],
187590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  ah->totalPowerMeasQ[i],
188590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  ah->totalIqCorrMeas[i]);
189590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	}
190590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez}
191590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
192590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguezstatic void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
193590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez{
194590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
195590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	u32 powerMeasQ, powerMeasI, iqCorrMeas;
196590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	u32 qCoffDenom, iCoffDenom;
197590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	int32_t qCoff, iCoff;
198590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	int iqCorrNeg, i;
199590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	const u_int32_t offset_array[3] = {
200590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B0,
201590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B1,
202590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B2,
203590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	};
204590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
205590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	for (i = 0; i < numChains; i++) {
206590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		powerMeasI = ah->totalPowerMeasI[i];
207590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		powerMeasQ = ah->totalPowerMeasQ[i];
208590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		iqCorrMeas = ah->totalIqCorrMeas[i];
209590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
210590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
211590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  "Starting IQ Cal and Correction for Chain %d\n",
212590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  i);
213590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
214590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
215590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
216590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  i, ah->totalIqCorrMeas[i]);
217590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
218590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		iqCorrNeg = 0;
219590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
220590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		if (iqCorrMeas > 0x80000000) {
221590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
222590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			iqCorrNeg = 1;
223590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		}
224590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
225590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
226590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
227590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
228590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
229590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
230590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			  iqCorrNeg);
231590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
232590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
233590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		qCoffDenom = powerMeasQ / 64;
234590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
235590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
236590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			iCoff = iqCorrMeas / iCoffDenom;
237590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			qCoff = powerMeasI / qCoffDenom - 64;
238590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
239590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Chn %d iCoff = 0x%08x\n", i, iCoff);
240590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
241590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Chn %d qCoff = 0x%08x\n", i, qCoff);
242590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
243590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			/* Force bounds on iCoff */
244590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			if (iCoff >= 63)
245590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				iCoff = 63;
246590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			else if (iCoff <= -63)
247590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				iCoff = -63;
248590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
249590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			/* Negate iCoff if iqCorrNeg == 0 */
250590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			if (iqCorrNeg == 0x0)
251590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				iCoff = -iCoff;
252590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
253590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			/* Force bounds on qCoff */
254590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			if (qCoff >= 63)
255590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				qCoff = 63;
256590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			else if (qCoff <= -63)
257590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				qCoff = -63;
258590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
259590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			iCoff = iCoff & 0x7f;
260590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			qCoff = qCoff & 0x7f;
261590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
262590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
263590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
264590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  i, iCoff, qCoff);
265590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
266590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Register offset (0x%04x) "
267590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "before update = 0x%x\n",
268590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  offset_array[i],
269590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  REG_READ(ah, offset_array[i]));
270590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
271590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			REG_RMW_FIELD(ah, offset_array[i],
272590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
273590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				      iCoff);
274590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			REG_RMW_FIELD(ah, offset_array[i],
275590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
276590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				      qCoff);
277590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
278590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Register offset (0x%04x) QI COFF "
279590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "(bitfields 0x%08x) after update = 0x%x\n",
280590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  offset_array[i],
281590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
282590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  REG_READ(ah, offset_array[i]));
283590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
284590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "Register offset (0x%04x) QQ COFF "
285590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "(bitfields 0x%08x) after update = 0x%x\n",
286590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  offset_array[i],
287590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
288590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  REG_READ(ah, offset_array[i]));
289590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
290590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
291590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  "IQ Cal and Correction done for Chain %d\n",
292590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez				  i);
293590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		}
294590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	}
295590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
296590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
297590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		    AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
298590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
299590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		  "IQ Cal and Correction (offset 0x%04x) enabled "
300590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		  "(bit position 0x%08x). New Value 0x%08x\n",
301590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		  (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
302590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		  AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
303590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez		  REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
304590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez}
305590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
306590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguezstatic const struct ath9k_percal_data iq_cal_single_sample = {
307590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	IQ_MISMATCH_CAL,
308590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	MIN_CAL_SAMPLES,
309590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	PER_MAX_LOG_COUNT,
310590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	ar9003_hw_iqcal_collect,
311590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	ar9003_hw_iqcalibrate
312590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez};
313590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez
314795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguezstatic void ar9003_hw_init_cal_settings(struct ath_hw *ah)
315795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez{
316590b7d2f10f4552e5b7570c84dc565d3cb7825c9Luis R. Rodriguez	ah->iq_caldata.calData = &iq_cal_single_sample;
317795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez}
318795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
319df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez/*
320df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez * solve 4x4 linear equation used in loopback iq cal.
321df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez */
322df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
323df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 sin_2phi_1,
324df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 cos_2phi_1,
325df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 sin_2phi_2,
326df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 cos_2phi_2,
327df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 mag_a0_d0,
328df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 phs_a0_d0,
329df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 mag_a1_d0,
330df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 phs_a1_d0,
331df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 solved_eq[])
332df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez{
333df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 f1 = cos_2phi_1 - cos_2phi_2,
334df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    f3 = sin_2phi_1 - sin_2phi_2,
335df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    f2;
336df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 mag_tx, phs_tx, mag_rx, phs_rx;
337df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const s32 result_shift = 1 << 15;
338df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
339df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
340df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	f2 = (f1 * f1 + f3 * f3) / result_shift;
341df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
342df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (!f2) {
343df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
344df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
345df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
346df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
347df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* mag mismatch, tx */
348df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
349df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* phs mismatch, tx */
350df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
351df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
352df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_tx = (mag_tx / f2);
353df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_tx = (phs_tx / f2);
354df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
355df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* mag mismatch, rx */
356df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
357df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 result_shift;
358df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* phs mismatch, rx */
359df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
360df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		 result_shift;
361df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
362df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	solved_eq[0] = mag_tx;
363df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	solved_eq[1] = phs_tx;
364df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	solved_eq[2] = mag_rx;
365df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	solved_eq[3] = phs_rx;
366df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
367df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return true;
368df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez}
369df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
370df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
37177d6d39a77939e5ed7e2ec72a1c1dce828ee582eLuis R. Rodriguez{
372df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 abs_i = abs(in_re),
373df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    abs_q = abs(in_im),
374df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    max_abs, min_abs;
375df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
376df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (abs_i > abs_q) {
377df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		max_abs = abs_i;
378df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		min_abs = abs_q;
379df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	} else {
380df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		max_abs = abs_q;
381df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		min_abs = abs_i;
382df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
383df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
384df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
385df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez}
386df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
387df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez#define DELPT 32
388df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
389df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
390df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 chain_idx,
391df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   const s32 iq_res[],
392df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				   s32 iqc_coeff[])
393df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez{
394df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
395df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
396df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
397df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
398df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
399df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
400df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    sin_2phi_1, cos_2phi_1,
401df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    sin_2phi_2, cos_2phi_2;
402df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 mag_tx, phs_tx, mag_rx, phs_rx;
403df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
404df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    q_q_coff, q_i_coff;
405df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const s32 res_scale = 1 << 15;
406df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const s32 delpt_shift = 1 << 8;
407df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 mag1, mag2;
408df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
409df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
410df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
411df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
412df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
413df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
414df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_m_q2_a0_d0 > 0x800)
415df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
416df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
417df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_p_q2_a0_d0 > 0x800)
418df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
419df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
420df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (iq_corr_a0_d0 > 0x800)
421df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
422df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
423df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
424df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
425df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
426df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
427df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_m_q2_a0_d1 > 0x800)
428df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
429df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
430df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_p_q2_a0_d1 > 0x800)
431df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
432df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
433df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (iq_corr_a0_d1 > 0x800)
434df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
435df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
436df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
437df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
438df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iq_corr_a1_d0 = iq_res[4] & 0xfff;
439df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
440df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_m_q2_a1_d0 > 0x800)
441df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
442df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
443df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_p_q2_a1_d0 > 0x800)
444df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
445df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
446df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (iq_corr_a1_d0 > 0x800)
447df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
448df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
449df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
450df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
451df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
452df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
453df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_m_q2_a1_d1 > 0x800)
454df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
455df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
456df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (i2_p_q2_a1_d1 > 0x800)
457df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
458df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
459df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (iq_corr_a1_d1 > 0x800)
460df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
461df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
462df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
463df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	    (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
464df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
465df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Divide by 0:\na0_d0=%d\n"
466df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "a0_d1=%d\na2_d0=%d\na1_d1=%d\n",
467df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  i2_p_q2_a0_d0, i2_p_q2_a0_d1,
468df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  i2_p_q2_a1_d0, i2_p_q2_a1_d1);
469df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
470df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
471df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
472df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
473df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
474df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
475df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
476df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
477df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
478df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
479df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
480df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
481df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
482df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
483df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
484df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* w/o analog phase shift */
485df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
486df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* w/o analog phase shift */
487df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
488df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* w/  analog phase shift */
489df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
490df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* w/  analog phase shift */
491df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
492df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
493df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/*
494df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * force sin^2 + cos^2 = 1;
495df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * find magnitude by approximation
496df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 */
497df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
498df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
499df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
500df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if ((mag1 == 0) || (mag2 == 0)) {
501df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
502df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Divide by 0: mag1=%d, mag2=%d\n",
503df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  mag1, mag2);
504df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
505df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
506df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
507df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* normalization sin and cos by mag */
508df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
509df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
510df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
511df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
512df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
513df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* calculate IQ mismatch */
514df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (!ar9003_hw_solve_iq_cal(ah,
515df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     sin_2phi_1, cos_2phi_1,
516df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     sin_2phi_2, cos_2phi_2,
517df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     mag_a0_d0, phs_a0_d0,
518df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     mag_a1_d0,
519df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     phs_a1_d0, solved_eq)) {
520df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
521df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Call to ar9003_hw_solve_iq_cal() failed.\n");
522df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
523df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
524df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
525df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_tx = solved_eq[0];
526df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_tx = solved_eq[1];
527df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_rx = solved_eq[2];
528df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_rx = solved_eq[3];
529df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
530df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
531df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  "chain %d: mag mismatch=%d phase mismatch=%d\n",
532df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  chain_idx, mag_tx/res_scale, phs_tx/res_scale);
533df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
534df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (res_scale == mag_tx) {
535df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
536df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Divide by 0: mag_tx=%d, res_scale=%d\n",
537df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  mag_tx, res_scale);
538df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
539df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
540df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
541df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* calculate and quantize Tx IQ correction factor */
542df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
543df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_corr_tx = -phs_tx;
544df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
545df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	q_q_coff = (mag_corr_tx * 128 / res_scale);
546df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	q_i_coff = (phs_corr_tx * 256 / res_scale);
547df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
548df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
549df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  "tx chain %d: mag corr=%d  phase corr=%d\n",
550df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  chain_idx, q_q_coff, q_i_coff);
551df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
552df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_i_coff < -63)
553df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_i_coff = -63;
554df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_i_coff > 63)
555df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_i_coff = 63;
556df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_q_coff < -63)
557df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_q_coff = -63;
558df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_q_coff > 63)
559df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_q_coff = 63;
560df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
561df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
562df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
563df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
564df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  "tx chain %d: iq corr coeff=%x\n",
565df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  chain_idx, iqc_coeff[0]);
566df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
567df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (-mag_rx == res_scale) {
568df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
569df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Divide by 0: mag_rx=%d, res_scale=%d\n",
570df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  mag_rx, res_scale);
571df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
572df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
573df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
574df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* calculate and quantize Rx IQ correction factors */
575df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
576df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	phs_corr_rx = -phs_rx;
577df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
578df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	q_q_coff = (mag_corr_rx * 128 / res_scale);
579df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	q_i_coff = (phs_corr_rx * 256 / res_scale);
580df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
581df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
582df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  "rx chain %d: mag corr=%d  phase corr=%d\n",
583df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  chain_idx, q_q_coff, q_i_coff);
584df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
585df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_i_coff < -63)
586df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_i_coff = -63;
587df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_i_coff > 63)
588df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_i_coff = 63;
589df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_q_coff < -63)
590df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_q_coff = -63;
591df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (q_q_coff > 63)
592df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		q_q_coff = 63;
593df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
594df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
595df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
596df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE,
597df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  "rx chain %d: iq corr coeff=%x\n",
598df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  chain_idx, iqc_coeff[1]);
599df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
600df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return true;
601df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez}
602df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
603df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
604df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez{
605df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
606df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
607df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_STATUS_B0,
608df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_STATUS_B1,
609df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_STATUS_B2,
610df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	};
611df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
612df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
613df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
614df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_TX_IQCAL_CORR_COEFF_01_B2,
615df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	};
616df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const u32 rx_corr[AR9300_MAX_CHAINS] = {
617df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B0,
618df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B1,
619df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_RX_IQCAL_CORR_B2,
620df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	};
621df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	const u_int32_t chan_info_tab[] = {
622df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_CHAN_INFO_TAB_0,
623df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_CHAN_INFO_TAB_1,
624df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		AR_PHY_CHAN_INFO_TAB_2,
625df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	};
626df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 iq_res[6];
627df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 iqc_coeff[2];
628df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	s32 i, j;
629df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	u32 num_chains = 0;
630df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
631df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
632df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		if (ah->txchainmask & (1 << i))
633df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			num_chains++;
634df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
635df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
636df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
637df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
638df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      DELPT);
639df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
640df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      AR_PHY_TX_IQCAL_START_DO_CAL,
641df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      AR_PHY_TX_IQCAL_START_DO_CAL);
642df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
643df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
644df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			   AR_PHY_TX_IQCAL_START_DO_CAL,
645df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			   0, AH_WAIT_TIMEOUT)) {
646df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
647df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Tx IQ Cal not complete.\n");
648df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		goto TX_IQ_CAL_FAILED;
649df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
650df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
651df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	for (i = 0; i < num_chains; i++) {
652df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
653df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "Doing Tx IQ Cal for chain %d.\n", i);
654df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
655df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		if (REG_READ(ah, txiqcal_status[i]) &
656df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			     AR_PHY_TX_IQCAL_STATUS_FAILED) {
657df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
658df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				  "Tx IQ Cal failed for chain %d.\n", i);
659df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			goto TX_IQ_CAL_FAILED;
660df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		}
661df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
662df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		for (j = 0; j < 3; j++) {
663df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			u_int8_t idx = 2 * j,
664df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			offset = 4 * j;
665df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
666df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
667df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				      AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
668df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
669df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			/* 32 bits */
670df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset);
671df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
672df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
673df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				      AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
674df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
675df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			/* 16 bits */
676df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			iq_res[idx+1] = 0xffff & REG_READ(ah,
677df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez							  chan_info_tab[i] +
678df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez							  offset);
679df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
680df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
681df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				  "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
682df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				  idx, iq_res[idx], idx+1, iq_res[idx+1]);
683df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		}
684df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
685df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) {
686df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			ath_print(common, ATH_DBG_CALIBRATE,
687df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez				  "Failed in calculation of IQ correction.\n");
688df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			goto TX_IQ_CAL_FAILED;
689df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		}
690df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
691df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
692df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n",
693df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  iqc_coeff[0], iqc_coeff[1]);
694df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
695df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		REG_RMW_FIELD(ah, tx_corr_coeff[i],
696df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
697df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      iqc_coeff[0]);
698df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		REG_RMW_FIELD(ah, rx_corr[i],
699df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF,
700df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      iqc_coeff[1] >> 7);
701df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		REG_RMW_FIELD(ah, rx_corr[i],
702df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF,
703df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			      iqc_coeff[1]);
704df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
705df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
706df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
707df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
708df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
709df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
710df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
711df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return;
712df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
713df23acaa5d3239745805650e2f27a4252182c063Luis R. RodriguezTX_IQ_CAL_FAILED:
714df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
715df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez}
716df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
717df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguezstatic bool ar9003_hw_init_cal(struct ath_hw *ah,
718df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			       struct ath9k_channel *chan)
719df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez{
720df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	struct ath_common *common = ath9k_hw_common(ah);
721df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
722df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/*
723df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before
724df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 * running AGC/TxIQ cals
725df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	 */
726df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
727df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
728c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez	/* Do Tx IQ Calibration */
729c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez	ar9003_hw_tx_iq_cal(ah);
730c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
731c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez	udelay(5);
732c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
733c5395b67437b47c4a4c0686d3db99be9327ef67eLuis R. Rodriguez
734df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Calibrate the AGC */
735df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
736df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
737df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		  AR_PHY_AGC_CONTROL_CAL);
738df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
739df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Poll for offset calibration complete */
740df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
741df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			   0, AH_WAIT_TIMEOUT)) {
742df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
743df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "offset calibration failed to "
744df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "complete in 1ms; noisy environment?\n");
745df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		return false;
746df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
747df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
748df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Revert chainmasks to their original values before NF cal */
749df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
750df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
75100c86590e36bd42574821b43b5124d75f30df9ddFelix Fietkau	ath9k_hw_start_nfcal(ah, true);
75200c86590e36bd42574821b43b5124d75f30df9ddFelix Fietkau
753df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Initialize list pointers */
754df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
7556497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau	ah->supp_cals = IQ_MISMATCH_CAL;
756df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
7576497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau	if (ah->supp_cals & IQ_MISMATCH_CAL) {
758df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		INIT_CAL(&ah->iq_caldata);
759df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		INSERT_CAL(ah, &ah->iq_caldata);
760df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
761df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "enabling IQ Calibration.\n");
762df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
763df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
7646497827f53eb90dcf30c5d6414c83238f722e8aeFelix Fietkau	if (ah->supp_cals & TEMP_COMP_CAL) {
765df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		INIT_CAL(&ah->tempCompCalData);
766df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		INSERT_CAL(ah, &ah->tempCompCalData);
767df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath_print(common, ATH_DBG_CALIBRATE,
768df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez			  "enabling Temperature Compensation Calibration.\n");
769df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	}
770df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
771df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	/* Initialize current pointer to first element in list */
772df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	ah->cal_list_curr = ah->cal_list;
773df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
774df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	if (ah->cal_list_curr)
775df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez		ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
776df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
77720bd2a0952d01ba82a99b3f22d46e3832c255529Felix Fietkau	if (ah->caldata)
77820bd2a0952d01ba82a99b3f22d46e3832c255529Felix Fietkau		ah->caldata->CalValid = 0;
779df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez
780df23acaa5d3239745805650e2f27a4252182c063Luis R. Rodriguez	return true;
78177d6d39a77939e5ed7e2ec72a1c1dce828ee582eLuis R. Rodriguez}
78277d6d39a77939e5ed7e2ec72a1c1dce828ee582eLuis R. Rodriguez
783795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguezvoid ar9003_hw_attach_calib_ops(struct ath_hw *ah)
784795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez{
785795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
786795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
787795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
788795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
789795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	priv_ops->init_cal = ar9003_hw_init_cal;
790795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	priv_ops->setup_calibration = ar9003_hw_setup_calibration;
791795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez
792795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez	ops->calibrate = ar9003_hw_calibrate;
793795f5e2ca672727a96bacf97075976cfe1249fcfLuis R. Rodriguez}
794