ath9k: Modify IQ calibration for AR955x
IQ calibration post-processing for AR955x is different from other chips - instead of just doing it as part of AGC calibration once, it is triggered 3 times and a median is determined. This patch adds initial support for changing the calibration behavior for AR955x. Also, to simplify things, a helper routine to issue/poll AGC calibration is used. For non-AR955x chips, the iqcal_idx (which will be used in subsequent patches) is set to zero. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
adddc0d20b
commit
97fe6420c9
|
@ -23,6 +23,7 @@
|
|||
#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
|
||||
#define MAX_MAG_DELTA 11
|
||||
#define MAX_PHS_DELTA 10
|
||||
#define MAXIQCAL 3
|
||||
|
||||
struct coeff {
|
||||
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
|
||||
|
@ -797,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
|||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
|
||||
iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
|
||||
|
||||
ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[0]);
|
||||
|
@ -828,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
|||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
|
||||
iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
|
||||
|
||||
ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[1]);
|
||||
|
@ -991,7 +992,9 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
|
||||
int iqcal_idx,
|
||||
bool is_reusable)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
|
||||
|
@ -1410,7 +1413,7 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
|
||||
else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
|
||||
ar9003_hw_tx_iq_cal_reload(ah);
|
||||
|
||||
|
@ -1456,6 +1459,29 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool do_ar9003_agc_cal(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
bool status;
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
|
||||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (!status) {
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"offset calibration failed to complete in %d ms,"
|
||||
"noisy environment?\n",
|
||||
AH_WAIT_TIMEOUT / 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
|
@ -1464,6 +1490,7 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
|||
bool txiqcal_done = false;
|
||||
bool status = true;
|
||||
bool run_agc_cal = false, sep_iq_cal = false;
|
||||
int i = 0;
|
||||
|
||||
/* Use chip chainmask only for calibration */
|
||||
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
|
||||
|
@ -1518,27 +1545,37 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
|||
if (AR_SREV_9330_11(ah))
|
||||
ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
|
||||
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
/*
|
||||
* For non-AR9550 chips, we just trigger AGC calibration
|
||||
* in the HW, poll for completion and then process
|
||||
* the results.
|
||||
*
|
||||
* For AR955x, we run it multiple times and use
|
||||
* median IQ correction.
|
||||
*/
|
||||
if (!AR_SREV_9550(ah)) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
/* Poll for offset calibration complete */
|
||||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
|
||||
} else {
|
||||
if (!txiqcal_done) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
} else {
|
||||
for (i = 0; i < MAXIQCAL; i++) {
|
||||
status = do_ar9003_agc_cal(ah);
|
||||
if (!status)
|
||||
return false;
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"offset calibration failed to complete in %d ms; noisy environment?\n",
|
||||
AH_WAIT_TIMEOUT / 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah, false);
|
||||
|
||||
/* Revert chainmask to runtime parameters */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
|
|
Loading…
Reference in New Issue