1*572ff6f6SMatthew Dillon /*
2*572ff6f6SMatthew Dillon * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3*572ff6f6SMatthew Dillon * Copyright (c) 2002-2008 Atheros Communications, Inc.
4*572ff6f6SMatthew Dillon *
5*572ff6f6SMatthew Dillon * Permission to use, copy, modify, and/or distribute this software for any
6*572ff6f6SMatthew Dillon * purpose with or without fee is hereby granted, provided that the above
7*572ff6f6SMatthew Dillon * copyright notice and this permission notice appear in all copies.
8*572ff6f6SMatthew Dillon *
9*572ff6f6SMatthew Dillon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*572ff6f6SMatthew Dillon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*572ff6f6SMatthew Dillon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*572ff6f6SMatthew Dillon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*572ff6f6SMatthew Dillon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*572ff6f6SMatthew Dillon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*572ff6f6SMatthew Dillon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*572ff6f6SMatthew Dillon *
17*572ff6f6SMatthew Dillon * $FreeBSD$
18*572ff6f6SMatthew Dillon */
19*572ff6f6SMatthew Dillon #include "opt_ah.h"
20*572ff6f6SMatthew Dillon
21*572ff6f6SMatthew Dillon #include "ah.h"
22*572ff6f6SMatthew Dillon #include "ah_internal.h"
23*572ff6f6SMatthew Dillon #include "ah_devid.h"
24*572ff6f6SMatthew Dillon
25*572ff6f6SMatthew Dillon #include "ar5212/ar5212.h"
26*572ff6f6SMatthew Dillon #include "ar5212/ar5212reg.h"
27*572ff6f6SMatthew Dillon #include "ar5212/ar5212phy.h"
28*572ff6f6SMatthew Dillon
29*572ff6f6SMatthew Dillon #include "ah_eeprom_v3.h"
30*572ff6f6SMatthew Dillon
31*572ff6f6SMatthew Dillon static const GAIN_OPTIMIZATION_LADDER gainLadder = {
32*572ff6f6SMatthew Dillon 9, /* numStepsInLadder */
33*572ff6f6SMatthew Dillon 4, /* defaultStepNum */
34*572ff6f6SMatthew Dillon { { {4, 1, 1, 1}, 6, "FG8"},
35*572ff6f6SMatthew Dillon { {4, 0, 1, 1}, 4, "FG7"},
36*572ff6f6SMatthew Dillon { {3, 1, 1, 1}, 3, "FG6"},
37*572ff6f6SMatthew Dillon { {4, 0, 0, 1}, 1, "FG5"},
38*572ff6f6SMatthew Dillon { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */
39*572ff6f6SMatthew Dillon { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */
40*572ff6f6SMatthew Dillon { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */
41*572ff6f6SMatthew Dillon { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */
42*572ff6f6SMatthew Dillon { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */
43*572ff6f6SMatthew Dillon }
44*572ff6f6SMatthew Dillon };
45*572ff6f6SMatthew Dillon
46*572ff6f6SMatthew Dillon static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = {
47*572ff6f6SMatthew Dillon 8, /* numStepsInLadder */
48*572ff6f6SMatthew Dillon 1, /* defaultStepNum */
49*572ff6f6SMatthew Dillon { { {3, 0,0,0, 0,0,0}, 6, "FG7"}, /* most fixed gain */
50*572ff6f6SMatthew Dillon { {2, 0,0,0, 0,0,0}, 0, "FG6"},
51*572ff6f6SMatthew Dillon { {1, 0,0,0, 0,0,0}, -3, "FG5"},
52*572ff6f6SMatthew Dillon { {0, 0,0,0, 0,0,0}, -6, "FG4"},
53*572ff6f6SMatthew Dillon { {0, 1,1,0, 0,0,0}, -8, "FG3"},
54*572ff6f6SMatthew Dillon { {0, 1,1,0, 1,1,0}, -10, "FG2"},
55*572ff6f6SMatthew Dillon { {0, 1,0,1, 1,1,0}, -13, "FG1"},
56*572ff6f6SMatthew Dillon { {0, 1,0,1, 1,0,1}, -16, "FG0"}, /* least fixed gain */
57*572ff6f6SMatthew Dillon }
58*572ff6f6SMatthew Dillon };
59*572ff6f6SMatthew Dillon
60*572ff6f6SMatthew Dillon /*
61*572ff6f6SMatthew Dillon * Initialize the gain structure to good values
62*572ff6f6SMatthew Dillon */
63*572ff6f6SMatthew Dillon void
ar5212InitializeGainValues(struct ath_hal * ah)64*572ff6f6SMatthew Dillon ar5212InitializeGainValues(struct ath_hal *ah)
65*572ff6f6SMatthew Dillon {
66*572ff6f6SMatthew Dillon struct ath_hal_5212 *ahp = AH5212(ah);
67*572ff6f6SMatthew Dillon GAIN_VALUES *gv = &ahp->ah_gainValues;
68*572ff6f6SMatthew Dillon
69*572ff6f6SMatthew Dillon /* initialize gain optimization values */
70*572ff6f6SMatthew Dillon if (IS_RAD5112_ANY(ah)) {
71*572ff6f6SMatthew Dillon gv->currStepNum = gainLadder5112.defaultStepNum;
72*572ff6f6SMatthew Dillon gv->currStep =
73*572ff6f6SMatthew Dillon &gainLadder5112.optStep[gainLadder5112.defaultStepNum];
74*572ff6f6SMatthew Dillon gv->active = AH_TRUE;
75*572ff6f6SMatthew Dillon gv->loTrig = 20;
76*572ff6f6SMatthew Dillon gv->hiTrig = 85;
77*572ff6f6SMatthew Dillon } else {
78*572ff6f6SMatthew Dillon gv->currStepNum = gainLadder.defaultStepNum;
79*572ff6f6SMatthew Dillon gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];
80*572ff6f6SMatthew Dillon gv->active = AH_TRUE;
81*572ff6f6SMatthew Dillon gv->loTrig = 20;
82*572ff6f6SMatthew Dillon gv->hiTrig = 35;
83*572ff6f6SMatthew Dillon }
84*572ff6f6SMatthew Dillon }
85*572ff6f6SMatthew Dillon
86*572ff6f6SMatthew Dillon #define MAX_ANALOG_START 319 /* XXX */
87*572ff6f6SMatthew Dillon
88*572ff6f6SMatthew Dillon /*
89*572ff6f6SMatthew Dillon * Find analog bits of given parameter data and return a reversed value
90*572ff6f6SMatthew Dillon */
91*572ff6f6SMatthew Dillon static uint32_t
ar5212GetRfField(uint32_t * rfBuf,uint32_t numBits,uint32_t firstBit,uint32_t column)92*572ff6f6SMatthew Dillon ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column)
93*572ff6f6SMatthew Dillon {
94*572ff6f6SMatthew Dillon uint32_t reg32 = 0, mask, arrayEntry, lastBit;
95*572ff6f6SMatthew Dillon uint32_t bitPosition, bitsShifted;
96*572ff6f6SMatthew Dillon int32_t bitsLeft;
97*572ff6f6SMatthew Dillon
98*572ff6f6SMatthew Dillon HALASSERT(column <= 3);
99*572ff6f6SMatthew Dillon HALASSERT(numBits <= 32);
100*572ff6f6SMatthew Dillon HALASSERT(firstBit + numBits <= MAX_ANALOG_START);
101*572ff6f6SMatthew Dillon
102*572ff6f6SMatthew Dillon arrayEntry = (firstBit - 1) / 8;
103*572ff6f6SMatthew Dillon bitPosition = (firstBit - 1) % 8;
104*572ff6f6SMatthew Dillon bitsLeft = numBits;
105*572ff6f6SMatthew Dillon bitsShifted = 0;
106*572ff6f6SMatthew Dillon while (bitsLeft > 0) {
107*572ff6f6SMatthew Dillon lastBit = (bitPosition + bitsLeft > 8) ?
108*572ff6f6SMatthew Dillon (8) : (bitPosition + bitsLeft);
109*572ff6f6SMatthew Dillon mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
110*572ff6f6SMatthew Dillon (column * 8);
111*572ff6f6SMatthew Dillon reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >>
112*572ff6f6SMatthew Dillon bitPosition) << bitsShifted;
113*572ff6f6SMatthew Dillon bitsShifted += lastBit - bitPosition;
114*572ff6f6SMatthew Dillon bitsLeft -= (8 - bitPosition);
115*572ff6f6SMatthew Dillon bitPosition = 0;
116*572ff6f6SMatthew Dillon arrayEntry++;
117*572ff6f6SMatthew Dillon }
118*572ff6f6SMatthew Dillon reg32 = ath_hal_reverseBits(reg32, numBits);
119*572ff6f6SMatthew Dillon return reg32;
120*572ff6f6SMatthew Dillon }
121*572ff6f6SMatthew Dillon
122*572ff6f6SMatthew Dillon static HAL_BOOL
ar5212InvalidGainReadback(struct ath_hal * ah,GAIN_VALUES * gv)123*572ff6f6SMatthew Dillon ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv)
124*572ff6f6SMatthew Dillon {
125*572ff6f6SMatthew Dillon uint32_t gStep, g, mixOvr;
126*572ff6f6SMatthew Dillon uint32_t L1, L2, L3, L4;
127*572ff6f6SMatthew Dillon
128*572ff6f6SMatthew Dillon if (IS_RAD5112_ANY(ah)) {
129*572ff6f6SMatthew Dillon mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0);
130*572ff6f6SMatthew Dillon L1 = 0;
131*572ff6f6SMatthew Dillon L2 = 107;
132*572ff6f6SMatthew Dillon L3 = 0;
133*572ff6f6SMatthew Dillon L4 = 107;
134*572ff6f6SMatthew Dillon if (mixOvr == 1) {
135*572ff6f6SMatthew Dillon L2 = 83;
136*572ff6f6SMatthew Dillon L4 = 83;
137*572ff6f6SMatthew Dillon gv->hiTrig = 55;
138*572ff6f6SMatthew Dillon }
139*572ff6f6SMatthew Dillon } else {
140*572ff6f6SMatthew Dillon gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0);
141*572ff6f6SMatthew Dillon
142*572ff6f6SMatthew Dillon L1 = 0;
143*572ff6f6SMatthew Dillon L2 = (gStep == 0x3f) ? 50 : gStep + 4;
144*572ff6f6SMatthew Dillon L3 = (gStep != 0x3f) ? 0x40 : L1;
145*572ff6f6SMatthew Dillon L4 = L3 + 50;
146*572ff6f6SMatthew Dillon
147*572ff6f6SMatthew Dillon gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0);
148*572ff6f6SMatthew Dillon /* never adjust if != 0x3f */
149*572ff6f6SMatthew Dillon gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5);
150*572ff6f6SMatthew Dillon }
151*572ff6f6SMatthew Dillon g = gv->currGain;
152*572ff6f6SMatthew Dillon
153*572ff6f6SMatthew Dillon return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
154*572ff6f6SMatthew Dillon }
155*572ff6f6SMatthew Dillon
156*572ff6f6SMatthew Dillon /*
157*572ff6f6SMatthew Dillon * Enable the probe gain check on the next packet
158*572ff6f6SMatthew Dillon */
159*572ff6f6SMatthew Dillon void
ar5212RequestRfgain(struct ath_hal * ah)160*572ff6f6SMatthew Dillon ar5212RequestRfgain(struct ath_hal *ah)
161*572ff6f6SMatthew Dillon {
162*572ff6f6SMatthew Dillon struct ath_hal_5212 *ahp = AH5212(ah);
163*572ff6f6SMatthew Dillon uint32_t probePowerIndex;
164*572ff6f6SMatthew Dillon
165*572ff6f6SMatthew Dillon /* Enable the gain readback probe */
166*572ff6f6SMatthew Dillon probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset;
167*572ff6f6SMatthew Dillon OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,
168*572ff6f6SMatthew Dillon SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX)
169*572ff6f6SMatthew Dillon | AR_PHY_PAPD_PROBE_NEXT_TX);
170*572ff6f6SMatthew Dillon
171*572ff6f6SMatthew Dillon ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;
172*572ff6f6SMatthew Dillon }
173*572ff6f6SMatthew Dillon
174*572ff6f6SMatthew Dillon /*
175*572ff6f6SMatthew Dillon * Check to see if our readback gain level sits within the linear
176*572ff6f6SMatthew Dillon * region of our current variable attenuation window
177*572ff6f6SMatthew Dillon */
178*572ff6f6SMatthew Dillon static HAL_BOOL
ar5212IsGainAdjustNeeded(struct ath_hal * ah,const GAIN_VALUES * gv)179*572ff6f6SMatthew Dillon ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv)
180*572ff6f6SMatthew Dillon {
181*572ff6f6SMatthew Dillon return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
182*572ff6f6SMatthew Dillon }
183*572ff6f6SMatthew Dillon
184*572ff6f6SMatthew Dillon /*
185*572ff6f6SMatthew Dillon * Move the rabbit ears in the correct direction.
186*572ff6f6SMatthew Dillon */
187*572ff6f6SMatthew Dillon static int32_t
ar5212AdjustGain(struct ath_hal * ah,GAIN_VALUES * gv)188*572ff6f6SMatthew Dillon ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv)
189*572ff6f6SMatthew Dillon {
190*572ff6f6SMatthew Dillon const GAIN_OPTIMIZATION_LADDER *gl;
191*572ff6f6SMatthew Dillon
192*572ff6f6SMatthew Dillon if (IS_RAD5112_ANY(ah))
193*572ff6f6SMatthew Dillon gl = &gainLadder5112;
194*572ff6f6SMatthew Dillon else
195*572ff6f6SMatthew Dillon gl = &gainLadder;
196*572ff6f6SMatthew Dillon gv->currStep = &gl->optStep[gv->currStepNum];
197*572ff6f6SMatthew Dillon if (gv->currGain >= gv->hiTrig) {
198*572ff6f6SMatthew Dillon if (gv->currStepNum == 0) {
199*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n",
200*572ff6f6SMatthew Dillon __func__);
201*572ff6f6SMatthew Dillon return -1;
202*572ff6f6SMatthew Dillon }
203*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_RFPARAM,
204*572ff6f6SMatthew Dillon "%s: Adding gain: currG=%d [%s] --> ",
205*572ff6f6SMatthew Dillon __func__, gv->currGain, gv->currStep->stepName);
206*572ff6f6SMatthew Dillon gv->targetGain = gv->currGain;
207*572ff6f6SMatthew Dillon while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
208*572ff6f6SMatthew Dillon gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain -
209*572ff6f6SMatthew Dillon gv->currStep->stepGain);
210*572ff6f6SMatthew Dillon gv->currStep = &gl->optStep[gv->currStepNum];
211*572ff6f6SMatthew Dillon }
212*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
213*572ff6f6SMatthew Dillon gv->targetGain, gv->currStep->stepName);
214*572ff6f6SMatthew Dillon return 1;
215*572ff6f6SMatthew Dillon }
216*572ff6f6SMatthew Dillon if (gv->currGain <= gv->loTrig) {
217*572ff6f6SMatthew Dillon if (gv->currStepNum == gl->numStepsInLadder-1) {
218*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_RFPARAM,
219*572ff6f6SMatthew Dillon "%s: Min gain limit.\n", __func__);
220*572ff6f6SMatthew Dillon return -2;
221*572ff6f6SMatthew Dillon }
222*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_RFPARAM,
223*572ff6f6SMatthew Dillon "%s: Deducting gain: currG=%d [%s] --> ",
224*572ff6f6SMatthew Dillon __func__, gv->currGain, gv->currStep->stepName);
225*572ff6f6SMatthew Dillon gv->targetGain = gv->currGain;
226*572ff6f6SMatthew Dillon while (gv->targetGain <= gv->loTrig &&
227*572ff6f6SMatthew Dillon gv->currStepNum < (gl->numStepsInLadder - 1)) {
228*572ff6f6SMatthew Dillon gv->targetGain -= 2 *
229*572ff6f6SMatthew Dillon (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
230*572ff6f6SMatthew Dillon gv->currStep = &gl->optStep[gv->currStepNum];
231*572ff6f6SMatthew Dillon }
232*572ff6f6SMatthew Dillon HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
233*572ff6f6SMatthew Dillon gv->targetGain, gv->currStep->stepName);
234*572ff6f6SMatthew Dillon return 2;
235*572ff6f6SMatthew Dillon }
236*572ff6f6SMatthew Dillon return 0; /* caller didn't call needAdjGain first */
237*572ff6f6SMatthew Dillon }
238*572ff6f6SMatthew Dillon
239*572ff6f6SMatthew Dillon /*
240*572ff6f6SMatthew Dillon * Read rf register to determine if gainF needs correction
241*572ff6f6SMatthew Dillon */
242*572ff6f6SMatthew Dillon static uint32_t
ar5212GetGainFCorrection(struct ath_hal * ah)243*572ff6f6SMatthew Dillon ar5212GetGainFCorrection(struct ath_hal *ah)
244*572ff6f6SMatthew Dillon {
245*572ff6f6SMatthew Dillon struct ath_hal_5212 *ahp = AH5212(ah);
246*572ff6f6SMatthew Dillon uint32_t correction;
247*572ff6f6SMatthew Dillon
248*572ff6f6SMatthew Dillon HALASSERT(IS_RADX112_REV2(ah));
249*572ff6f6SMatthew Dillon
250*572ff6f6SMatthew Dillon correction = 0;
251*572ff6f6SMatthew Dillon if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) {
252*572ff6f6SMatthew Dillon const GAIN_VALUES *gv = &ahp->ah_gainValues;
253*572ff6f6SMatthew Dillon uint32_t mixGain = gv->currStep->paramVal[0];
254*572ff6f6SMatthew Dillon uint32_t gainStep =
255*572ff6f6SMatthew Dillon ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0);
256*572ff6f6SMatthew Dillon switch (mixGain) {
257*572ff6f6SMatthew Dillon case 0 :
258*572ff6f6SMatthew Dillon correction = 0;
259*572ff6f6SMatthew Dillon break;
260*572ff6f6SMatthew Dillon case 1 :
261*572ff6f6SMatthew Dillon correction = gainStep;
262*572ff6f6SMatthew Dillon break;
263*572ff6f6SMatthew Dillon case 2 :
264*572ff6f6SMatthew Dillon correction = 2 * gainStep - 5;
265*572ff6f6SMatthew Dillon break;
266*572ff6f6SMatthew Dillon case 3 :
267*572ff6f6SMatthew Dillon correction = 2 * gainStep;
268*572ff6f6SMatthew Dillon break;
269*572ff6f6SMatthew Dillon }
270*572ff6f6SMatthew Dillon }
271*572ff6f6SMatthew Dillon return correction;
272*572ff6f6SMatthew Dillon }
273*572ff6f6SMatthew Dillon
274*572ff6f6SMatthew Dillon /*
275*572ff6f6SMatthew Dillon * Exported call to check for a recent gain reading and return
276*572ff6f6SMatthew Dillon * the current state of the thermal calibration gain engine.
277*572ff6f6SMatthew Dillon */
278*572ff6f6SMatthew Dillon HAL_RFGAIN
ar5212GetRfgain(struct ath_hal * ah)279*572ff6f6SMatthew Dillon ar5212GetRfgain(struct ath_hal *ah)
280*572ff6f6SMatthew Dillon {
281*572ff6f6SMatthew Dillon struct ath_hal_5212 *ahp = AH5212(ah);
282*572ff6f6SMatthew Dillon GAIN_VALUES *gv = &ahp->ah_gainValues;
283*572ff6f6SMatthew Dillon uint32_t rddata, probeType;
284*572ff6f6SMatthew Dillon
285*572ff6f6SMatthew Dillon /* NB: beware of touching the BB when PHY is powered down */
286*572ff6f6SMatthew Dillon if (!gv->active || !ahp->ah_phyPowerOn)
287*572ff6f6SMatthew Dillon return HAL_RFGAIN_INACTIVE;
288*572ff6f6SMatthew Dillon
289*572ff6f6SMatthew Dillon if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
290*572ff6f6SMatthew Dillon /* Caller had asked to setup a new reading. Check it. */
291*572ff6f6SMatthew Dillon rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
292*572ff6f6SMatthew Dillon
293*572ff6f6SMatthew Dillon if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
294*572ff6f6SMatthew Dillon /* bit got cleared, we have a new reading. */
295*572ff6f6SMatthew Dillon gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
296*572ff6f6SMatthew Dillon probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE);
297*572ff6f6SMatthew Dillon if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) {
298*572ff6f6SMatthew Dillon const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
299*572ff6f6SMatthew Dillon
300*572ff6f6SMatthew Dillon HALASSERT(IS_RAD5112_ANY(ah));
301*572ff6f6SMatthew Dillon HALASSERT(ah->ah_magic == AR5212_MAGIC);
302*572ff6f6SMatthew Dillon if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
303*572ff6f6SMatthew Dillon gv->currGain += ee->ee_cckOfdmGainDelta;
304*572ff6f6SMatthew Dillon else
305*572ff6f6SMatthew Dillon gv->currGain += PHY_PROBE_CCK_CORRECTION;
306*572ff6f6SMatthew Dillon }
307*572ff6f6SMatthew Dillon if (IS_RADX112_REV2(ah)) {
308*572ff6f6SMatthew Dillon uint32_t correct = ar5212GetGainFCorrection(ah);
309*572ff6f6SMatthew Dillon if (gv->currGain >= correct)
310*572ff6f6SMatthew Dillon gv->currGain -= correct;
311*572ff6f6SMatthew Dillon else
312*572ff6f6SMatthew Dillon gv->currGain = 0;
313*572ff6f6SMatthew Dillon }
314*572ff6f6SMatthew Dillon /* inactive by default */
315*572ff6f6SMatthew Dillon ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
316*572ff6f6SMatthew Dillon
317*572ff6f6SMatthew Dillon if (!ar5212InvalidGainReadback(ah, gv) &&
318*572ff6f6SMatthew Dillon ar5212IsGainAdjustNeeded(ah, gv) &&
319*572ff6f6SMatthew Dillon ar5212AdjustGain(ah, gv) > 0) {
320*572ff6f6SMatthew Dillon /*
321*572ff6f6SMatthew Dillon * Change needed. Copy ladder info
322*572ff6f6SMatthew Dillon * into eeprom info.
323*572ff6f6SMatthew Dillon */
324*572ff6f6SMatthew Dillon ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;
325*572ff6f6SMatthew Dillon /* for ap51 */
326*572ff6f6SMatthew Dillon ahp->ah_cwCalRequire = AH_TRUE;
327*572ff6f6SMatthew Dillon /* Request IQ recalibration for temperature chang */
328*572ff6f6SMatthew Dillon ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
329*572ff6f6SMatthew Dillon }
330*572ff6f6SMatthew Dillon }
331*572ff6f6SMatthew Dillon }
332*572ff6f6SMatthew Dillon return ahp->ah_rfgainState;
333*572ff6f6SMatthew Dillon }
334