Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90864fbc authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'for-davem' of...

parents 228e548e a70171dc
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -158,6 +158,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
	txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211);
	rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211);

	/*
	 * Set default Tx frame to Tx data start delay
	 */
	txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;

	/*
	 * 5210 initvals don't include usec settings
	 * so we need to use magic values here for
+5 −1
Original line number Diff line number Diff line
@@ -21,11 +21,15 @@
#include <linux/ath9k_platform.h>
#include "ath9k.h"

const struct platform_device_id ath9k_platform_id_table[] = {
static const struct platform_device_id ath9k_platform_id_table[] = {
	{
		.name = "ath9k",
		.driver_data = AR5416_AR9100_DEVID,
	},
	{
		.name = "ar934x_wmac",
		.driver_data = AR9300_DEVID_AR9340,
	},
	{},
};

+0 −6
Original line number Diff line number Diff line
@@ -899,12 +899,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
	 * check here default level should not modify INI setting.
	 */
	if (use_new_ani(ah)) {
		const struct ani_ofdm_level_entry *entry_ofdm;
		const struct ani_cck_level_entry *entry_cck;

		entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
		entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];

		ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
		ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
	} else {
+146 −241
Original line number Diff line number Diff line
@@ -18,13 +18,13 @@
#include "hw-ops.h"
#include "ar9003_phy.h"

#define MPASS	3
#define MAX_MEASUREMENT	8
#define MAX_DIFFERENCE	10
#define MAX_MAG_DELTA	11
#define MAX_PHS_DELTA	10

struct coeff {
	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
	int iqc_coeff[2];
};

@@ -185,6 +185,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah)

	/* Accumulate IQ cal measures for active chains */
	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
		if (ah->txchainmask & BIT(i)) {
			ah->totalPowerMeasI[i] +=
				REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
			ah->totalPowerMeasQ[i] +=
@@ -198,6 +199,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
				ah->totalIqCorrMeas[i]);
		}
	}
}

static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
{
@@ -608,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
	return true;
}

static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
				     int max_delta)
{
	int diff[MPASS];

	diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
	diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
	diff[2] = abs(mp_coeff[2] - mp_coeff[0]);

	if (diff[0] > MAX_DIFFERENCE &&
	    diff[1] > MAX_DIFFERENCE &&
	    diff[2] > MAX_DIFFERENCE)
		return false;

	if (diff[0] <= diff[1] && diff[0] <= diff[2])
		*mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
	else if (diff[1] <= diff[2])
		*mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
	int mp_max = -64, max_idx = 0;
	int mp_min = 63, min_idx = 0;
	int mp_avg = 0, i, outlier_idx = 0;

	/* find min/max mismatch across all calibrated gains */
	for (i = 0; i < nmeasurement; i++) {
		mp_avg += mp_coeff[i];
		if (mp_coeff[i] > mp_max) {
			mp_max = mp_coeff[i];
			max_idx = i;
		} else if (mp_coeff[i] < mp_min) {
			mp_min = mp_coeff[i];
			min_idx = i;
		}
	}

	/* find average (exclude max abs value) */
	for (i = 0; i < nmeasurement; i++) {
		if ((abs(mp_coeff[i]) < abs(mp_max)) ||
		    (abs(mp_coeff[i]) < abs(mp_min)))
			mp_avg += mp_coeff[i];
	}
	mp_avg /= (nmeasurement - 1);

	/* detect outlier */
	if (abs(mp_max - mp_min) > max_delta) {
		if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
			outlier_idx = max_idx;
		else
		*mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;

	return true;
			outlier_idx = min_idx;
	}
	mp_coeff[outlier_idx] = mp_avg;
}

static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
						 u8 num_chains,
						 struct coeff *coeff)
{
	struct ath_common *common = ath9k_hw_common(ah);
	int i, im, nmeasurement;
	int magnitude, phase;
	u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];

	memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
@@ -657,11 +671,6 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,

	/* Load the average of 2 passes */
	for (i = 0; i < num_chains; i++) {
		if (AR_SREV_9485(ah))
			nmeasurement = REG_READ_FIELD(ah,
					AR_PHY_TX_IQCAL_STATUS_B0_9485,
					AR_PHY_CALIBRATED_GAINS_0);
		else
		nmeasurement = REG_READ_FIELD(ah,
				AR_PHY_TX_IQCAL_STATUS_B0,
				AR_PHY_CALIBRATED_GAINS_0);
@@ -669,25 +678,21 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
		if (nmeasurement > MAX_MEASUREMENT)
			nmeasurement = MAX_MEASUREMENT;

		for (im = 0; im < nmeasurement; im++) {
			/*
			 * Determine which 2 passes are closest and compute avg
			 * magnitude
			 */
			if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
								    &magnitude))
				goto disable_txiqcal;
		/* detect outlier only if nmeasurement > 1 */
		if (nmeasurement > 1) {
			/* Detect magnitude outlier */
			ar9003_hw_detect_outlier(coeff->mag_coeff[i],
					nmeasurement, MAX_MAG_DELTA);

			/*
			 * Determine which 2 passes are closest and compute avg
			 * phase
			 */
			if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
								    &phase))
				goto disable_txiqcal;
			/* Detect phase outlier */
			ar9003_hw_detect_outlier(coeff->phs_coeff[i],
					nmeasurement, MAX_PHS_DELTA);
		}

			coeff->iqc_coeff[0] = (magnitude & 0x7f) |
					      ((phase & 0x7f) << 7);
		for (im = 0; im < nmeasurement; im++) {

			coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
				((coeff->phs_coeff[i][im] & 0x7f) << 7);

			if ((im % 2) == 0)
				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
@@ -707,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,

	return;

disable_txiqcal:
	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);

	ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
}

static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);
	static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
		AR_PHY_TX_IQCAL_STATUS_B0,
		AR_PHY_TX_IQCAL_STATUS_B1,
		AR_PHY_TX_IQCAL_STATUS_B2,
	};
	static const u32 chan_info_tab[] = {
		AR_PHY_CHAN_INFO_TAB_0,
		AR_PHY_CHAN_INFO_TAB_1,
		AR_PHY_CHAN_INFO_TAB_2,
	};
	struct coeff coeff;
	s32 iq_res[6];
	s32 i, j, ip, im, nmeasurement;
	u8 nchains = get_streams(common->tx_chainmask);

	for (ip = 0; ip < MPASS; ip++) {
		REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
			      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
			      DELPT);
		REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
			      AR_PHY_TX_IQCAL_START_DO_CAL,
			      AR_PHY_TX_IQCAL_START_DO_CAL);

		if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
				   AR_PHY_TX_IQCAL_START_DO_CAL,
				   0, AH_WAIT_TIMEOUT)) {
			ath_dbg(common, ATH_DBG_CALIBRATE,
				"Tx IQ Cal not complete.\n");
			goto TX_IQ_CAL_FAILED;
		}

		nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
					      AR_PHY_CALIBRATED_GAINS_0);
			if (nmeasurement > MAX_MEASUREMENT)
				nmeasurement = MAX_MEASUREMENT;

		for (i = 0; i < nchains; i++) {
			ath_dbg(common, ATH_DBG_CALIBRATE,
				"Doing Tx IQ Cal for chain %d.\n", i);
			for (im = 0; im < nmeasurement; im++) {
				if (REG_READ(ah, txiqcal_status[i]) &
					     AR_PHY_TX_IQCAL_STATUS_FAILED) {
					ath_dbg(common, ATH_DBG_CALIBRATE,
						"Tx IQ Cal failed for chain %d.\n", i);
					goto TX_IQ_CAL_FAILED;
				}

				for (j = 0; j < 3; j++) {
					u8 idx = 2 * j,
					   offset = 4 * (3 * im + j);

					REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
						      AR_PHY_CHAN_INFO_TAB_S2_READ,
						      0);

					/* 32 bits */
					iq_res[idx] = REG_READ(ah,
							chan_info_tab[i] +
							offset);

					REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
						      AR_PHY_CHAN_INFO_TAB_S2_READ,
						      1);

					/* 16 bits */
					iq_res[idx+1] = 0xffff & REG_READ(ah,
								chan_info_tab[i] +
								offset);

					ath_dbg(common, ATH_DBG_CALIBRATE,
						"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
						idx, iq_res[idx], idx+1, iq_res[idx+1]);
				}

				if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
							    coeff.iqc_coeff)) {
					ath_dbg(common, ATH_DBG_CALIBRATE,
						"Failed in calculation of IQ correction.\n");
					goto TX_IQ_CAL_FAILED;
				}
				coeff.mag_coeff[i][im][ip] =
						coeff.iqc_coeff[0] & 0x7f;
				coeff.phs_coeff[i][im][ip] =
						(coeff.iqc_coeff[0] >> 7) & 0x7f;

				if (coeff.mag_coeff[i][im][ip] > 63)
					coeff.mag_coeff[i][im][ip] -= 128;
				if (coeff.phs_coeff[i][im][ip] > 63)
					coeff.phs_coeff[i][im][ip] -= 128;

			}
		}
	}

	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);

	return;

TX_IQ_CAL_FAILED:
	ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
}

static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
{
	u8 tx_gain_forced;

	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
		      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
	tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
					AR_PHY_TXGAIN_FORCE);
	if (tx_gain_forced)
		REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
			      AR_PHY_TXGAIN_FORCE, 0);

	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
		      AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
		      AR_PHY_TX_IQCAL_START_DO_CAL, 1);

	if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
			AR_PHY_TX_IQCAL_START_DO_CAL, 0,
			AH_WAIT_TIMEOUT)) {
		ath_dbg(common, ATH_DBG_CALIBRATE,
			"Tx IQ Cal is not completed.\n");
		return false;
	}
	return true;
}

static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);
	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
		AR_PHY_TX_IQCAL_STATUS_B0_9485,
		AR_PHY_TX_IQCAL_STATUS_B0,
		AR_PHY_TX_IQCAL_STATUS_B1,
		AR_PHY_TX_IQCAL_STATUS_B2,
	};
@@ -853,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
	struct coeff coeff;
	s32 iq_res[6];
	u8 num_chains = 0;
	int i, ip, im, j;
	int i, im, j;
	int nmeasurement;

	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
@@ -861,10 +762,9 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
			num_chains++;
	}

	for (ip = 0; ip < MPASS; ip++) {
	for (i = 0; i < num_chains; i++) {
		nmeasurement = REG_READ_FIELD(ah,
					AR_PHY_TX_IQCAL_STATUS_B0_9485,
				AR_PHY_TX_IQCAL_STATUS_B0,
				AR_PHY_CALIBRATED_GAINS_0);
		if (nmeasurement > MAX_MEASUREMENT)
			nmeasurement = MAX_MEASUREMENT;
@@ -912,20 +812,19 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
			if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
						coeff.iqc_coeff)) {
				ath_dbg(common, ATH_DBG_CALIBRATE,
					 "Failed in calculation of IQ correction.\n");
					"Failed in calculation of \
					IQ correction.\n");
				goto tx_iqcal_fail;
			}

				coeff.mag_coeff[i][im][ip] =
						coeff.iqc_coeff[0] & 0x7f;
				coeff.phs_coeff[i][im][ip] =
			coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
			coeff.phs_coeff[i][im] =
				(coeff.iqc_coeff[0] >> 7) & 0x7f;

				if (coeff.mag_coeff[i][im][ip] > 63)
					coeff.mag_coeff[i][im][ip] -= 128;
				if (coeff.phs_coeff[i][im][ip] > 63)
					coeff.phs_coeff[i][im][ip] -= 128;
			}
			if (coeff.mag_coeff[i][im] > 63)
				coeff.mag_coeff[i][im] -= 128;
			if (coeff.phs_coeff[i][im] > 63)
				coeff.phs_coeff[i][im] -= 128;
		}
	}
	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
@@ -940,31 +839,37 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
			       struct ath9k_channel *chan)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_hw_capabilities *pCap = &ah->caps;
	int val;
	bool txiqcal_done = false;

	val = REG_READ(ah, AR_ENT_OTP);
	ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);

	if (AR_SREV_9485(ah))
		ar9003_hw_set_chain_masks(ah, 0x1, 0x1);
	else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
	/* Configure rx/tx chains before running AGC/TxiQ cals */
	if (val & AR_ENT_OTP_CHAIN2_DISABLE)
		ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
	else
		/*
		 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
		 * mode before running AGC/TxIQ cals
		 */
		ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
		ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
					  pCap->tx_chainmask);

	/* Do Tx IQ Calibration */
	if (AR_SREV_9485(ah))
		ar9003_hw_tx_iq_cal_run(ah);
	else
		ar9003_hw_tx_iq_cal(ah);
	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
		      AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
		      DELPT);

	/*
	 * For AR9485 or later chips, TxIQ cal runs as part of
	 * AGC calibration
	 */
	if (AR_SREV_9485_OR_LATER(ah))
		txiqcal_done = true;
	else {
		txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
		REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
		udelay(5);
		REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
	}

	/* Calibrate the AGC */
	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
@@ -979,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
		return false;
	}

	if (AR_SREV_9485(ah))
	if (txiqcal_done)
		ar9003_hw_tx_iq_cal_post_proc(ah);

	/* Revert chainmasks to their original values before NF cal */
+36 −25
Original line number Diff line number Diff line
@@ -3217,7 +3217,6 @@ static int ar9300_compress_decision(struct ath_hw *ah,
				    u8 *word, int length, int mdata_size)
{
	struct ath_common *common = ath9k_hw_common(ah);
	u8 *dptr;
	const struct ar9300_eeprom *eep = NULL;

	switch (code) {
@@ -3235,7 +3234,6 @@ static int ar9300_compress_decision(struct ath_hw *ah,
		break;
	case _CompressBlock:
		if (reference == 0) {
			dptr = mptr;
		} else {
			eep = ar9003_eeprom_struct_find_by_id(reference);
			if (eep == NULL) {
@@ -3448,9 +3446,13 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
		REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
	else {
		REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
		REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB,
		if (!AR_SREV_9340(ah)) {
			REG_RMW_FIELD(ah, AR_CH0_THERM,
				      AR_CH0_THERM_XPABIASLVL_MSB,
				      bias >> 2);
		REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1);
			REG_RMW_FIELD(ah, AR_CH0_THERM,
				      AR_CH0_THERM_XPASHORT2GND, 1);
		}
	}
}

@@ -3497,23 +3499,28 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,

static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
{
	int chain;
	static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
			AR_PHY_SWITCH_CHAIN_0,
			AR_PHY_SWITCH_CHAIN_1,
			AR_PHY_SWITCH_CHAIN_2,
	};

	u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);

	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);

	value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);

	value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);

	if (!AR_SREV_9485(ah)) {
		value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
		REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL,
			      value);

		value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
		REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL,
			      value);
	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
		if ((ah->rxchainmask & BIT(chain)) ||
		    (ah->txchainmask & BIT(chain))) {
			value = ar9003_hw_ant_ctrl_chain_get(ah, chain,
							     is2ghz);
			REG_RMW_FIELD(ah, switch_chain_reg[chain],
				      AR_SWITCH_TABLE_ALL, value);
		}
	}

	if (AR_SREV_9485(ah)) {
@@ -3634,13 +3641,16 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)

	/* Test value. if 0 then attenuation is unused. Don't load anything. */
	for (i = 0; i < 3; i++) {
		if (ah->txchainmask & BIT(i)) {
			value = ar9003_hw_atten_chain_get(ah, i, chan);
			REG_RMW_FIELD(ah, ext_atten_reg[i],
				      AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);

			value = ar9003_hw_atten_chain_get_margin(ah, i, chan);
			REG_RMW_FIELD(ah, ext_atten_reg[i],
			      AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
				      AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
				      value);
		}
	}
}

@@ -3749,8 +3759,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
	ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
	ar9003_hw_drive_strength_apply(ah);
	ar9003_hw_atten_apply(ah, chan);
	if (!AR_SREV_9340(ah))
		ar9003_hw_internal_regulator_apply(ah);
	if (AR_SREV_9485(ah))
	if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
		ar9003_hw_apply_tuning_caps(ah);
}

Loading