summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-12-22 14:27:21 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-22 14:27:21 -0500
commit63e35cd9bd4c8ae085c8b9a70554595b529c4100 (patch)
tree68e771e0035d5f3ee394a3d86885631a2610bba5 /drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
parent503b1a529a6b62b31904bab4699752c523cf76b2 (diff)
parent3d986b25b5faa50ba6afd94f60f270b6c3061e5e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/iwlwifi/iwl-1000.c drivers/net/wireless/iwlwifi/iwl-6000.c drivers/net/wireless/iwlwifi/iwl-core.h
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_eeprom.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c136
1 files changed, 110 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index a16b3dae5b34..466d2bf02eab 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -73,7 +73,7 @@ static const struct ar9300_eeprom ar9300_default = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
- .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@@ -650,7 +650,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
- .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@@ -1228,7 +1228,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
- .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@@ -1806,7 +1806,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
- .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@@ -2383,7 +2383,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x33, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
- .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@@ -2975,7 +2975,7 @@ static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
{
- if (fbin == AR9300_BCHAN_UNUSED)
+ if (fbin == AR5416_BCHAN_UNUSED)
return fbin;
return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
@@ -3428,18 +3428,6 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
return 0;
}
-static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
- enum ath9k_hal_freq_band freq_band)
-{
- return 1;
-}
-
-static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- return -EINVAL;
-}
-
static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -4486,7 +4474,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
}
- return AR9300_MAX_RATE_POWER;
+ return MAX_RATE_POWER;
}
/*
@@ -4495,7 +4483,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
u16 freq, int idx, bool is2GHz)
{
- u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
u8 *ctl_freqbin = is2GHz ?
&eep->ctl_freqbin_2G[idx][0] :
&eep->ctl_freqbin_5G[idx][0];
@@ -4505,7 +4493,7 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
/* Get the edge power */
for (edge = 0;
- (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
+ (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED);
edge++) {
/*
* If there's an exact channel match or an inband flag set
@@ -4543,9 +4531,9 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
- u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+ u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] = {
- 0, 3, 6, 9, AR9300_MAX_RATE_POWER
+ 0, 3, 6, 9, MAX_RATE_POWER
};
int i;
int16_t twiceLargestAntenna;
@@ -4756,6 +4744,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
} /* end ctl mode checking */
}
+static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
+{
+ u8 mod_idx = mcs_idx % 8;
+
+ if (mod_idx <= 3)
+ return mod_idx ? (base_pwridx + 1) : base_pwridx;
+ else
+ return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
+}
+
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
@@ -4764,16 +4762,70 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct ar9300_modal_eep_header *modal_hdr;
u8 targetPowerValT2[ar9300RateSize];
- unsigned int i = 0;
+ u8 target_power_val_t2_eep[ar9300RateSize];
+ unsigned int i = 0, paprd_scale_factor = 0;
+ u8 pwr_idx, min_pwridx = 0;
ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
+
+ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ if (IS_CHAN_2GHZ(chan))
+ modal_hdr = &eep->modalHeader2G;
+ else
+ modal_hdr = &eep->modalHeader5G;
+
+ ah->paprd_ratemask =
+ le32_to_cpu(modal_hdr->papdRateMaskHt20) &
+ AR9300_PAPRD_RATE_MASK;
+
+ ah->paprd_ratemask_ht40 =
+ le32_to_cpu(modal_hdr->papdRateMaskHt40) &
+ AR9300_PAPRD_RATE_MASK;
+
+ paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan);
+ min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 :
+ ALL_TARGET_HT20_0_8_16;
+
+ if (!ah->paprd_table_write_done) {
+ memcpy(target_power_val_t2_eep, targetPowerValT2,
+ sizeof(targetPowerValT2));
+ for (i = 0; i < 24; i++) {
+ pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx);
+ if (ah->paprd_ratemask & (1 << i)) {
+ if (targetPowerValT2[pwr_idx] &&
+ targetPowerValT2[pwr_idx] ==
+ target_power_val_t2_eep[pwr_idx])
+ targetPowerValT2[pwr_idx] -=
+ paprd_scale_factor;
+ }
+ }
+ }
+ memcpy(target_power_val_t2_eep, targetPowerValT2,
+ sizeof(targetPowerValT2));
+ }
+
ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit);
+ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+ for (i = 0; i < ar9300RateSize; i++) {
+ if ((ah->paprd_ratemask & (1 << i)) &&
+ (abs(targetPowerValT2[i] -
+ target_power_val_t2_eep[i]) >
+ paprd_scale_factor)) {
+ ah->paprd_ratemask &= ~(1 << i);
+ ath_dbg(common, ATH_DBG_EEPROM,
+ "paprd disabled for mcs %d\n", i);
+ }
+ }
+ }
+
regulatory->max_power_level = 0;
for (i = 0; i < ar9300RateSize; i++) {
if (targetPowerValT2[i] > regulatory->max_power_level)
@@ -4811,6 +4863,19 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
/* Write target power array to registers */
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
ar9003_hw_calibration_apply(ah, chan->channel);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_0_8_16;
+ else
+ i = ALL_TARGET_HT20_0_8_16;
+ } else {
+ if (IS_CHAN_HT40(chan))
+ i = ALL_TARGET_HT40_7;
+ else
+ i = ALL_TARGET_HT20_7;
+ }
+ ah->paprd_target_power = targetPowerValT2[i];
}
static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
@@ -4843,14 +4908,33 @@ u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz)
return eep->modalHeader5G.spurChans;
}
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (IS_CHAN_2GHZ(chan))
+ return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20),
+ AR9300_PAPRD_SCALE_1);
+ else {
+ if (chan->channel >= 5700)
+ return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
+ AR9300_PAPRD_SCALE_1);
+ else if (chan->channel >= 5400)
+ return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+ AR9300_PAPRD_SCALE_2);
+ else
+ return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+ AR9300_PAPRD_SCALE_1);
+ }
+}
+
const struct eeprom_ops eep_ar9300_ops = {
.check_eeprom = ath9k_hw_ar9300_check_eeprom,
.get_eeprom = ath9k_hw_ar9300_get_eeprom,
.fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
- .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
- .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
.set_board_values = ath9k_hw_ar9300_set_board_values,
.set_addac = ath9k_hw_ar9300_set_addac,
.set_txpower = ath9k_hw_ar9300_set_txpower,