diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2014-02-06 23:59:55 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-12 15:36:08 -0500 |
commit | e3d7556b7743b56e14362e43de84f30174138c73 (patch) | |
tree | e037724cb249af6921f77c258b6efed7094c95bf | |
parent | 4357a81d8af1fb5a6ece2fbfbd3540622fea2548 (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.c | 91 |
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 | ||
1003 | static 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 | |||
1040 | static 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 | |||
996 | static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, | 1057 | static 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 | ||