Index: chromeos/compat-wireless/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
diff --git a/chromeos/compat-wireless/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/chromeos/compat-wireless/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
index 716db414c258f254263a47238f45aa9fd6c2d813..22938f673e9a231f4fa4c85405f32e4240074ff0 100644 |
--- a/chromeos/compat-wireless/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
+++ b/chromeos/compat-wireless/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
@@ -19,6 +19,20 @@ |
void ar9003_paprd_enable(struct ath_hw *ah, bool val) |
{ |
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
+ struct ath9k_channel *chan = ah->curchan; |
+ |
+ if (val) { |
+ ah->paprd_table_write_done = true; |
+ |
+ ah->eep_ops->set_txpower(ah, chan, |
+ ath9k_regd_get_ctl(regulatory, chan), |
+ chan->chan->max_antenna_gain * 2, |
+ chan->chan->max_power * 2, |
+ min((u32) MAX_RATE_POWER, |
+ (u32) regulatory->power_limit)); |
+ } |
+ |
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, |
AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, |
@@ -28,10 +42,63 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val) |
} |
EXPORT_SYMBOL(ar9003_paprd_enable); |
-static void ar9003_paprd_setup_single_table(struct ath_hw *ah) |
+static int ar9003_get_training_power_2g(struct ath_hw *ah) |
+{ |
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
+ struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G; |
+ unsigned int power, scale, delta; |
+ |
+ scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1); |
+ power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, |
+ AR_PHY_POWERTX_RATE5_POWERTXHT20_0); |
+ |
+ delta = abs((int) ah->paprd_target_power - (int) power); |
+ if (delta > scale) |
+ return -1; |
+ |
+ if (delta < 4) |
+ power -= 4 - delta; |
+ |
+ return power; |
+} |
+ |
+static int ar9003_get_training_power_5g(struct ath_hw *ah) |
{ |
+ struct ath_common *common = ath9k_hw_common(ah); |
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
- struct ar9300_modal_eep_header *hdr; |
+ struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G; |
+ struct ath9k_channel *chan = ah->curchan; |
+ unsigned int power, scale, delta; |
+ |
+ if (chan->channel >= 5700) |
+ scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), |
+ AR9300_PAPRD_SCALE_1); |
+ else if (chan->channel >= 5400) |
+ scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), |
+ AR9300_PAPRD_SCALE_2); |
+ else |
+ scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), |
+ AR9300_PAPRD_SCALE_1); |
+ |
+ if (IS_CHAN_HT40(chan)) |
+ power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8, |
+ AR_PHY_POWERTX_RATE8_POWERTXHT40_5); |
+ else |
+ power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6, |
+ AR_PHY_POWERTX_RATE6_POWERTXHT20_5); |
+ |
+ power += scale; |
+ delta = abs((int) ah->paprd_target_power - (int) power); |
+ if (delta > scale) |
+ return -1; |
+ |
+ power += 2 * get_streams(common->tx_chainmask); |
+ return power; |
+} |
+ |
+static int ar9003_paprd_setup_single_table(struct ath_hw *ah) |
+{ |
+ struct ath_common *common = ath9k_hw_common(ah); |
const u32 ctrl0[3] = { |
AR_PHY_PAPRD_CTRL0_B0, |
AR_PHY_PAPRD_CTRL0_B1, |
@@ -42,20 +109,30 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) |
AR_PHY_PAPRD_CTRL1_B1, |
AR_PHY_PAPRD_CTRL1_B2 |
}; |
- u32 am_mask, ht40_mask; |
+ int training_power; |
int i; |
- if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) |
- hdr = &eep->modalHeader5G; |
+ if (IS_CHAN_2GHZ(ah->curchan)) |
+ training_power = ar9003_get_training_power_2g(ah); |
else |
- hdr = &eep->modalHeader2G; |
+ training_power = ar9003_get_training_power_5g(ah); |
- am_mask = le32_to_cpu(hdr->papdRateMaskHt20); |
- ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); |
- |
- REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); |
- REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); |
- REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); |
+ if (training_power < 0) { |
+ ath_print(common, ATH_DBG_CALIBRATE, |
+ "PAPRD target power delta out of range"); |
+ return -ERANGE; |
+ } |
+ ah->paprd_training_power = training_power; |
+ ath_print(common, ATH_DBG_CALIBRATE, |
+ "Training power: %d, Target power: %d\n", |
+ ah->paprd_training_power, ah->paprd_target_power); |
+ |
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, |
+ ah->paprd_ratemask); |
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, |
+ ah->paprd_ratemask); |
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, |
+ ah->paprd_ratemask_ht40); |
for (i = 0; i < 3; i++) { |
REG_RMW_FIELD(ah, ctrl0[i], |
@@ -132,6 +209,7 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) |
AR_PHY_PAPRD_PRE_POST_SCALING, 185706); |
REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, |
AR_PHY_PAPRD_PRE_POST_SCALING, 175487); |
+ return 0; |
} |
static void ar9003_paprd_get_gain_table(struct ath_hw *ah) |
@@ -586,15 +664,10 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
{ |
u32 *paprd_table_val = caldata->pa_table[chain]; |
u32 small_signal_gain = caldata->small_signal_gain[chain]; |
- u32 training_power; |
+ u32 training_power = ah->paprd_training_power; |
u32 reg = 0; |
int i; |
- training_power = |
- REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, |
- AR_PHY_POWERTX_RATE5_POWERTXHT20_0); |
- training_power -= 4; |
- |
if (chain == 0) |
reg = AR_PHY_PAPRD_MEM_TAB_B0; |
else if (chain == 1) |
@@ -632,14 +705,8 @@ EXPORT_SYMBOL(ar9003_paprd_populate_single_table); |
int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) |
{ |
- |
unsigned int i, desired_gain, gain_index; |
- unsigned int train_power; |
- |
- train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, |
- AR_PHY_POWERTX_RATE5_POWERTXHT20_0); |
- |
- train_power = train_power - 4; |
+ unsigned int train_power = ah->paprd_training_power; |
desired_gain = ar9003_get_desired_gain(ah, chain, train_power); |
@@ -705,7 +772,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve); |
int ar9003_paprd_init_table(struct ath_hw *ah) |
{ |
- ar9003_paprd_setup_single_table(ah); |
+ int ret; |
+ |
+ ret = ar9003_paprd_setup_single_table(ah); |
+ if (ret < 0) |
+ return ret; |
+ |
ar9003_paprd_get_gain_table(ah); |
return 0; |
} |