aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Albert <jal2@gmx.de>2009-09-15 16:23:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:38 -0400
commit7c52c07de8bd0433db6b3e0147544e5a2f01b786 (patch)
tree1888ac9a234eb64fb53dd1d0f8b84be9d040b138
parent90f2908d3263e5c84c8408ce382a669b528b10e3 (diff)
ar9170: add heavy clip handling
add heavy clip handling for 2.4GHz only (similar to the vendor driver). Signed-off-by: Joerg Albert <jal2@gmx.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ar9170/ar9170.h2
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c71
2 files changed, 69 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index c5576eec12ae..ec034af26980 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -202,6 +202,8 @@ struct ar9170 {
202 u8 power_2G_ht20[8]; 202 u8 power_2G_ht20[8];
203 u8 power_2G_ht40[8]; 203 u8 power_2G_ht40[8];
204 204
205 u8 phy_heavy_clip;
206
205#ifdef CONFIG_AR9170_LEDS 207#ifdef CONFIG_AR9170_LEDS
206 struct delayed_work led_work; 208 struct delayed_work led_work;
207 struct ar9170_led leds[AR9170_NUM_LEDS]; 209 struct ar9170_led leds[AR9170_NUM_LEDS];
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index 07625a97851c..45a415ea809a 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -1278,8 +1278,38 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
1278 return rc; 1278 return rc;
1279} 1279}
1280 1280
1281/* calculate the conformance test limits and apply them to ar->power* 1281static u8 ar9170_get_heavy_clip(struct ar9170 *ar,
1282 * (derived from otus hal/hpmain.c, line 3706 ff.) 1282 struct ar9170_calctl_edges edges[],
1283 u32 freq, enum ar9170_bw bw)
1284{
1285 u8 f;
1286 int i;
1287 u8 rc = 0;
1288
1289 if (freq < 3000)
1290 f = freq - 2300;
1291 else
1292 f = (freq - 4800) / 5;
1293
1294 if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE)
1295 rc |= 0xf0;
1296
1297 for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
1298 if (edges[i].channel == 0xff)
1299 break;
1300 if (f == edges[i].channel) {
1301 if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS))
1302 rc |= 0x0f;
1303 break;
1304 }
1305 }
1306
1307 return rc;
1308}
1309
1310/*
1311 * calculate the conformance test limits and the heavy clip parameter
1312 * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706)
1283 */ 1313 */
1284static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) 1314static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1285{ 1315{
@@ -1312,6 +1342,8 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1312 1342
1313#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) 1343#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
1314 1344
1345 ar->phy_heavy_clip = 0;
1346
1315 /* 1347 /*
1316 * TODO: investigate the differences between OTUS' 1348 * TODO: investigate the differences between OTUS'
1317 * hpreg.c::zfHpGetRegulatoryDomain() and 1349 * hpreg.c::zfHpGetRegulatoryDomain() and
@@ -1347,6 +1379,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1347 if (ctl_idx < AR5416_NUM_CTLS) { 1379 if (ctl_idx < AR5416_NUM_CTLS) {
1348 int f_off = 0; 1380 int f_off = 0;
1349 1381
1382 /* determine heav clip parameter from
1383 the 11G edges array */
1384 if (modes[i].ctl_mode == CTL_11G) {
1385 ar->phy_heavy_clip =
1386 ar9170_get_heavy_clip(ar,
1387 EDGES(ctl_idx, 1),
1388 freq, bw);
1389 }
1390
1350 /* adjust freq for 40MHz */ 1391 /* adjust freq for 40MHz */
1351 if (modes[i].ctl_mode == CTL_2GHT40 || 1392 if (modes[i].ctl_mode == CTL_2GHT40 ||
1352 modes[i].ctl_mode == CTL_5GHT40) { 1393 modes[i].ctl_mode == CTL_5GHT40) {
@@ -1392,6 +1433,19 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1392 modes[i].max_power); 1433 modes[i].max_power);
1393 } 1434 }
1394 } 1435 }
1436
1437 if (ar->phy_heavy_clip & 0xf0) {
1438 ar->power_2G_ht40[0]--;
1439 ar->power_2G_ht40[1]--;
1440 ar->power_2G_ht40[2]--;
1441 }
1442 if (ar->phy_heavy_clip & 0xf) {
1443 ar->power_2G_ht20[0]++;
1444 ar->power_2G_ht20[1]++;
1445 ar->power_2G_ht20[2]++;
1446 }
1447
1448
1395#undef EDGES 1449#undef EDGES
1396} 1450}
1397 1451
@@ -1501,8 +1555,6 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1501 /* calc. conformance test limits and apply to ar->power*[] */ 1555 /* calc. conformance test limits and apply to ar->power*[] */
1502 ar9170_calc_ctl(ar, freq, bw); 1556 ar9170_calc_ctl(ar, freq, bw);
1503 1557
1504 /* TODO: (heavy clip) regulatory domain power level fine-tuning. */
1505
1506 /* set ACK/CTS TX power */ 1558 /* set ACK/CTS TX power */
1507 ar9170_regwrite_begin(ar); 1559 ar9170_regwrite_begin(ar);
1508 1560
@@ -1645,6 +1697,17 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
1645 if (err) 1697 if (err)
1646 return err; 1698 return err;
1647 1699
1700 if (ar->phy_heavy_clip) {
1701 err = ar9170_write_reg(ar, 0x1c59e0,
1702 0x200 | ar->phy_heavy_clip);
1703 if (err) {
1704 if (ar9170_nag_limiter(ar))
1705 printk(KERN_ERR "%s: failed to set "
1706 "heavy clip\n",
1707 wiphy_name(ar->hw->wiphy));
1708 }
1709 }
1710
1648 for (i = 0; i < 2; i++) { 1711 for (i = 0; i < 2; i++) {
1649 ar->noise[i] = ar9170_calc_noise_dbm( 1712 ar->noise[i] = ar9170_calc_noise_dbm(
1650 (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); 1713 (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);