From b860f4a0da49ef909e7c065ec553736496b30c60 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Mon, 6 Aug 2012 22:11:30 +0000
Subject: ath9k: extend and enable PA predistortion

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33031 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../patches/570-ath9k_paprd_hornet_mask.patch      |  25 ++++
 .../patches/571-ath9k_paprd_retrain_pa_in.patch    | 153 +++++++++++++++++++++
 .../mac80211/patches/572-ath9k_enable_paprd.patch  |  12 ++
 3 files changed, 190 insertions(+)
 create mode 100644 package/mac80211/patches/570-ath9k_paprd_hornet_mask.patch
 create mode 100644 package/mac80211/patches/571-ath9k_paprd_retrain_pa_in.patch
 create mode 100644 package/mac80211/patches/572-ath9k_enable_paprd.patch

(limited to 'package')

diff --git a/package/mac80211/patches/570-ath9k_paprd_hornet_mask.patch b/package/mac80211/patches/570-ath9k_paprd_hornet_mask.patch
new file mode 100644
index 000000000..90e3ef2ac
--- /dev/null
+++ b/package/mac80211/patches/570-ath9k_paprd_hornet_mask.patch
@@ -0,0 +1,25 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_tab
+ 	};
+ 	int training_power;
+ 	int i, val;
++	u32 am2pm_mask = ah->paprd_ratemask;
+ 
+ 	if (IS_CHAN_2GHZ(ah->curchan))
+ 		training_power = ar9003_get_training_power_2g(ah);
+@@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_tab
+ 	}
+ 	ah->paprd_training_power = training_power;
+ 
++	if (AR_SREV_9330(ah))
++		am2pm_mask = 0;
++
+ 	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);
++		      am2pm_mask);
+ 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
+ 		      ah->paprd_ratemask_ht40);
+ 
diff --git a/package/mac80211/patches/571-ath9k_paprd_retrain_pa_in.patch b/package/mac80211/patches/571-ath9k_paprd_retrain_pa_in.patch
new file mode 100644
index 000000000..4a366e330
--- /dev/null
+++ b/package/mac80211/patches/571-ath9k_paprd_retrain_pa_in.patch
@@ -0,0 +1,153 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -786,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct
+ }
+ EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
+ 
++static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
++				       struct ath9k_hw_cal_data *caldata,
++				       int chain)
++{
++	u32 *pa_in = caldata->pa_table[chain];
++	int capdiv_offset, quick_drop_offset;
++	int capdiv2g, quick_drop;
++	int count = 0;
++	int i;
++
++	if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
++		return false;
++
++	capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
++				  AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
++
++	quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
++				    AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
++
++	if (quick_drop)
++		quick_drop -= 0x40;
++
++	for (i = 0; i < NUM_BIN + 1; i++) {
++		if (pa_in[i] == 1400)
++			count++;
++	}
++
++	if (AR_SREV_9485(ah)) {
++		if (pa_in[23] < 800) {
++			capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
++			capdiv2g += capdiv_offset;
++			if (capdiv2g > 7) {
++				capdiv2g = 7;
++				if (pa_in[23] < 600) {
++					quick_drop++;
++					if (quick_drop > 0)
++						quick_drop = 0;
++				}
++			}
++		} else if (pa_in[23] == 1400) {
++			quick_drop_offset = min_t(int, count / 3, 2);
++			quick_drop += quick_drop_offset;
++			capdiv2g += quick_drop_offset / 2;
++
++			if (capdiv2g > 7)
++				capdiv2g = 7;
++
++			if (quick_drop > 0) {
++				quick_drop = 0;
++				capdiv2g -= quick_drop_offset;
++				if (capdiv2g < 0)
++					capdiv2g = 0;
++			}
++		} else {
++			return false;
++		}
++	} else if (AR_SREV_9330(ah)) {
++		if (pa_in[23] < 1000) {
++			capdiv_offset = (1000 - pa_in[23]) / 100;
++			capdiv2g += capdiv_offset;
++			if (capdiv_offset > 3) {
++				capdiv_offset = 1;
++				quick_drop--;
++			}
++
++			capdiv2g += capdiv_offset;
++			if (capdiv2g > 6)
++				capdiv2g = 6;
++			if (quick_drop < -4)
++				quick_drop = -4;
++		} else if (pa_in[23] == 1400) {
++			if (count > 3) {
++				quick_drop++;
++				capdiv2g -= count / 4;
++				if (quick_drop > -2)
++					quick_drop = -2;
++			} else {
++				capdiv2g--;
++			}
++
++			if (capdiv2g < 0)
++				capdiv2g = 0;
++		} else {
++			return false;
++		}
++	}
++
++	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
++		      AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
++	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
++		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
++		      quick_drop);
++
++	return true;
++}
++
+ int ar9003_paprd_create_curve(struct ath_hw *ah,
+ 			      struct ath9k_hw_cal_data *caldata, int chain)
+ {
+@@ -821,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath
+ 	if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
+ 		status = -2;
+ 
++	if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
++		status = -EINPROGRESS;
++
+ 	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ 		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+ 
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+@@ -625,6 +625,10 @@
+ #define AR_PHY_AIC_CTRL_4_B0	(AR_SM_BASE + 0x4c0)
+ #define AR_PHY_AIC_STAT_2_B0	(AR_SM_BASE + 0x4cc)
+ 
++#define AR_PHY_65NM_CH0_TXRF3       0x16048
++#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G		0x0000001e
++#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S	1
++
+ #define AR_PHY_65NM_CH0_SYNTH4      0x1608c
+ #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
+ #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -254,6 +254,7 @@ void ath_paprd_calibrate(struct work_str
+ 	int chain_ok = 0;
+ 	int chain;
+ 	int len = 1800;
++	int ret;
+ 
+ 	if (!caldata)
+ 		return;
+@@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_str
+ 			break;
+ 		}
+ 
+-		if (ar9003_paprd_create_curve(ah, caldata, chain)) {
++		ret = ar9003_paprd_create_curve(ah, caldata, chain);
++		if (ret == -EINPROGRESS) {
++			ath_dbg(common, CALIBRATE,
++				"PAPRD curve on chain %d needs to be re-trained\n",
++				chain);
++			break;
++		} else if (ret) {
+ 			ath_dbg(common, CALIBRATE,
+ 				"PAPRD create curve failed on chain %d\n",
+ 				chain);
diff --git a/package/mac80211/patches/572-ath9k_enable_paprd.patch b/package/mac80211/patches/572-ath9k_enable_paprd.patch
new file mode 100644
index 000000000..ff39587f6
--- /dev/null
+++ b/package/mac80211/patches/572-ath9k_enable_paprd.patch
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -464,9 +464,6 @@ static void ath9k_hw_init_config(struct 
+ 		ah->config.spurchans[i][1] = AR_NO_SPUR;
+ 	}
+ 
+-	/* PAPRD needs some more work to be enabled */
+-	ah->config.paprd_disable = 1;
+-
+ 	ah->config.rx_intr_mitigation = true;
+ 	ah->config.pcieSerDesWrite = true;
+ 
-- 
cgit v1.2.3