aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2009-09-03 14:25:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-08 16:31:05 -0400
commitd9c35a506ed7770301f705a9070e05f0c5fae4bd (patch)
tree3303836f0b9e938da37c68a3a2b5bfd96a3dd8b9 /drivers/net/wireless/ath
parent8813262ea79acf9daa0e03901bdfe93db4dc4ca5 (diff)
ar9170: implement frequency calibration for one-stage/openfw
This patch ports some code from the vendor driver, which is supposed to upload the right calibration values for the chosen frequency. In theory, this should give a better range and throughput for all users with the open, or one-stage firmware. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index 3ace58ab40c8..108ebfe21fcf 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -1120,6 +1120,124 @@ static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
1120#undef SHIFT 1120#undef SHIFT
1121} 1121}
1122 1122
1123static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array)
1124{
1125 int i;
1126
1127 for (i = 0; i < 3; i++)
1128 if (x <= x_array[i + 1])
1129 break;
1130
1131 return ar9170_interpolate_u8(x,
1132 x_array[i],
1133 y_array[i],
1134 x_array[i + 1],
1135 y_array[i + 1]);
1136}
1137
1138static int ar9170_set_freq_cal_data(struct ar9170 *ar,
1139 struct ieee80211_channel *channel)
1140{
1141 u8 *cal_freq_pier;
1142 u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
1143 u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
1144 int chain, idx, i;
1145 u8 f;
1146
1147 switch (channel->band) {
1148 case IEEE80211_BAND_2GHZ:
1149 f = channel->center_freq - 2300;
1150 cal_freq_pier = ar->eeprom.cal_freq_pier_2G;
1151 i = AR5416_NUM_2G_CAL_PIERS - 1;
1152 break;
1153
1154 case IEEE80211_BAND_5GHZ:
1155 f = (channel->center_freq - 4800) / 5;
1156 cal_freq_pier = ar->eeprom.cal_freq_pier_5G;
1157 i = AR5416_NUM_5G_CAL_PIERS - 1;
1158 break;
1159
1160 default:
1161 return -EINVAL;
1162 break;
1163 }
1164
1165 for (; i >= 0; i--) {
1166 if (cal_freq_pier[i] != 0xff)
1167 break;
1168 }
1169 if (i < 0)
1170 return -EINVAL;
1171
1172 idx = ar9170_find_freq_idx(i, cal_freq_pier, f);
1173
1174 ar9170_regwrite_begin(ar);
1175
1176 for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) {
1177 for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) {
1178 struct ar9170_calibration_data_per_freq *cal_pier_data;
1179 int j;
1180
1181 switch (channel->band) {
1182 case IEEE80211_BAND_2GHZ:
1183 cal_pier_data = &ar->eeprom.
1184 cal_pier_data_2G[chain][idx];
1185 break;
1186
1187 case IEEE80211_BAND_5GHZ:
1188 cal_pier_data = &ar->eeprom.
1189 cal_pier_data_5G[chain][idx];
1190 break;
1191
1192 default:
1193 return -EINVAL;
1194 }
1195
1196 for (j = 0; j < 2; j++) {
1197 vpds[j][i] = ar9170_interpolate_u8(f,
1198 cal_freq_pier[idx],
1199 cal_pier_data->vpd_pdg[j][i],
1200 cal_freq_pier[idx + 1],
1201 cal_pier_data[1].vpd_pdg[j][i]);
1202
1203 pwrs[j][i] = ar9170_interpolate_u8(f,
1204 cal_freq_pier[idx],
1205 cal_pier_data->pwr_pdg[j][i],
1206 cal_freq_pier[idx + 1],
1207 cal_pier_data[1].pwr_pdg[j][i]) / 2;
1208 }
1209 }
1210
1211 for (i = 0; i < 76; i++) {
1212 u32 phy_data;
1213 u8 tmp;
1214
1215 if (i < 25) {
1216 tmp = ar9170_interpolate_val(i, &pwrs[0][0],
1217 &vpds[0][0]);
1218 } else {
1219 tmp = ar9170_interpolate_val(i - 12,
1220 &pwrs[1][0],
1221 &vpds[1][0]);
1222 }
1223
1224 phy_data |= tmp << ((i & 3) << 3);
1225 if ((i & 3) == 3) {
1226 ar9170_regwrite(0x1c6280 + chain * 0x1000 +
1227 (i & ~3), phy_data);
1228 phy_data = 0;
1229 }
1230 }
1231
1232 for (i = 19; i < 32; i++)
1233 ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2),
1234 0x0);
1235 }
1236
1237 ar9170_regwrite_finish();
1238 return ar9170_regwrite_result();
1239}
1240
1123static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) 1241static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1124{ 1242{
1125 struct ar9170_calibration_target_power_legacy *ctpl; 1243 struct ar9170_calibration_target_power_legacy *ctpl;
@@ -1340,6 +1458,10 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
1340 if (err) 1458 if (err)
1341 return err; 1459 return err;
1342 1460
1461 err = ar9170_set_freq_cal_data(ar, channel);
1462 if (err)
1463 return err;
1464
1343 err = ar9170_set_power_cal(ar, channel->center_freq, bw); 1465 err = ar9170_set_power_cal(ar, channel->center_freq, bw);
1344 if (err) 1466 if (err)
1345 return err; 1467 return err;