aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-02-06 23:59:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:08 -0500
commite3d7556b7743b56e14362e43de84f30174138c73 (patch)
treee037724cb249af6921f77c258b6efed7094c95bf
parent4357a81d8af1fb5a6ece2fbfbd3540622fea2548 (diff)
ath9k: Calculate IQ-CAL median
This patch adds a routine to calculate the median IQ correction values for AR955x, which is used for outlier detection. The normal method which is used for all other chips is bypassed for AR955x. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c91
1 files changed, 79 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 6946e72d7ee9..ac8301ef5242 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -920,15 +920,22 @@ static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
920 if (nmeasurement > MAX_MEASUREMENT) 920 if (nmeasurement > MAX_MEASUREMENT)
921 nmeasurement = MAX_MEASUREMENT; 921 nmeasurement = MAX_MEASUREMENT;
922 922
923 /* detect outlier only if nmeasurement > 1 */ 923 /*
924 if (nmeasurement > 1) { 924 * Skip normal outlier detection for AR9550.
925 /* Detect magnitude outlier */ 925 */
926 ar9003_hw_detect_outlier(coeff->mag_coeff[i], 926 if (!AR_SREV_9550(ah)) {
927 nmeasurement, MAX_MAG_DELTA); 927 /* detect outlier only if nmeasurement > 1 */
928 928 if (nmeasurement > 1) {
929 /* Detect phase outlier */ 929 /* Detect magnitude outlier */
930 ar9003_hw_detect_outlier(coeff->phs_coeff[i], 930 ar9003_hw_detect_outlier(coeff->mag_coeff[i],
931 nmeasurement, MAX_PHS_DELTA); 931 nmeasurement,
932 MAX_MAG_DELTA);
933
934 /* Detect phase outlier */
935 ar9003_hw_detect_outlier(coeff->phs_coeff[i],
936 nmeasurement,
937 MAX_PHS_DELTA);
938 }
932 } 939 }
933 940
934 for (im = 0; im < nmeasurement; im++) { 941 for (im = 0; im < nmeasurement; im++) {
@@ -993,6 +1000,60 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
993 return true; 1000 return true;
994} 1001}
995 1002
1003static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
1004 struct coeff *coeff,
1005 int i, int nmeasurement)
1006{
1007 struct ath_common *common = ath9k_hw_common(ah);
1008 int im, ix, iy, temp;
1009
1010 for (im = 0; im < nmeasurement; im++) {
1011 for (ix = 0; ix < MAXIQCAL - 1; ix++) {
1012 for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
1013 if (coeff->mag_coeff[i][im][iy] <
1014 coeff->mag_coeff[i][im][ix]) {
1015 temp = coeff->mag_coeff[i][im][ix];
1016 coeff->mag_coeff[i][im][ix] =
1017 coeff->mag_coeff[i][im][iy];
1018 coeff->mag_coeff[i][im][iy] = temp;
1019 }
1020 if (coeff->phs_coeff[i][im][iy] <
1021 coeff->phs_coeff[i][im][ix]) {
1022 temp = coeff->phs_coeff[i][im][ix];
1023 coeff->phs_coeff[i][im][ix] =
1024 coeff->phs_coeff[i][im][iy];
1025 coeff->phs_coeff[i][im][iy] = temp;
1026 }
1027 }
1028 }
1029 coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
1030 coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
1031
1032 ath_dbg(common, CALIBRATE,
1033 "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
1034 i, im,
1035 coeff->mag_coeff[i][im][0],
1036 coeff->phs_coeff[i][im][0]);
1037 }
1038}
1039
1040static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
1041 struct coeff *coeff,
1042 int iqcal_idx,
1043 int nmeasurement)
1044{
1045 int i;
1046
1047 if ((iqcal_idx + 1) != MAXIQCAL)
1048 return false;
1049
1050 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1051 __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
1052 }
1053
1054 return true;
1055}
1056
996static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, 1057static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
997 int iqcal_idx, 1058 int iqcal_idx,
998 bool is_reusable) 1059 bool is_reusable)
@@ -1008,10 +1069,11 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
1008 AR_PHY_CHAN_INFO_TAB_1, 1069 AR_PHY_CHAN_INFO_TAB_1,
1009 AR_PHY_CHAN_INFO_TAB_2, 1070 AR_PHY_CHAN_INFO_TAB_2,
1010 }; 1071 };
1011 struct coeff coeff; 1072 static struct coeff coeff;
1012 s32 iq_res[6]; 1073 s32 iq_res[6];
1013 int i, im, j; 1074 int i, im, j;
1014 int nmeasurement; 1075 int nmeasurement = 0;
1076 bool outlier_detect = true;
1015 1077
1016 for (i = 0; i < AR9300_MAX_CHAINS; i++) { 1078 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1017 if (!(ah->txchainmask & (1 << i))) 1079 if (!(ah->txchainmask & (1 << i)))
@@ -1080,7 +1142,12 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
1080 coeff.phs_coeff[i][im][iqcal_idx] -= 128; 1142 coeff.phs_coeff[i][im][iqcal_idx] -= 128;
1081 } 1143 }
1082 } 1144 }
1083 ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable); 1145
1146 if (AR_SREV_9550(ah))
1147 outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
1148 iqcal_idx, nmeasurement);
1149 if (outlier_detect)
1150 ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
1084 1151
1085 return; 1152 return;
1086 1153