diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_eeprom.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 136 |
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, |