aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/phy.c
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi-project.org>2009-04-30 15:55:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:56 -0400
commit2bed03ebf62f9d013a455209bf30d7e086120443 (patch)
tree35592ca12f0e4425213e317895612c3ce15ad3a5 /drivers/net/wireless/ath/ath5k/phy.c
parent6f5f39c95af519c24c0187950147eb79d07d1940 (diff)
ath5k: Implement antenna control
* Add code to support the various antenna scenarios supported by hw * For now hardcode the default scenario (single or dual omnis with tx/rx diversity working and tx antenna handled by session -hw keeps track on which antenna it got ack from each ap/station and maps each ap/station to one of the antennas-). Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c174
1 files changed, 169 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index bb61b8e2dce9..fd93c4e20214 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1414,25 +1414,189 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
1414 return ret; 1414 return ret;
1415} 1415}
1416 1416
1417/*****************\
1418* Antenna control *
1419\*****************/
1420
1417void /*TODO:Boundary check*/ 1421void /*TODO:Boundary check*/
1418ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) 1422ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
1419{ 1423{
1420 ATH5K_TRACE(ah->ah_sc); 1424 ATH5K_TRACE(ah->ah_sc);
1421 /*Just a try M.F.*/ 1425
1422 if (ah->ah_version != AR5K_AR5210) 1426 if (ah->ah_version != AR5K_AR5210)
1423 ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); 1427 ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
1424} 1428}
1425 1429
1426unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) 1430unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
1427{ 1431{
1428 ATH5K_TRACE(ah->ah_sc); 1432 ATH5K_TRACE(ah->ah_sc);
1429 /*Just a try M.F.*/ 1433
1430 if (ah->ah_version != AR5K_AR5210) 1434 if (ah->ah_version != AR5K_AR5210)
1431 return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); 1435 return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7;
1432 1436
1433 return false; /*XXX: What do we return for 5210 ?*/ 1437 return false; /*XXX: What do we return for 5210 ?*/
1434} 1438}
1435 1439
1440/*
1441 * Enable/disable fast rx antenna diversity
1442 */
1443static void
1444ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
1445{
1446 switch (ee_mode) {
1447 case AR5K_EEPROM_MODE_11G:
1448 /* XXX: This is set to
1449 * disabled on initvals !!! */
1450 case AR5K_EEPROM_MODE_11A:
1451 if (enable)
1452 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL,
1453 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
1454 else
1455 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
1456 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
1457 break;
1458 case AR5K_EEPROM_MODE_11B:
1459 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
1460 AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
1461 break;
1462 default:
1463 return;
1464 }
1465
1466 if (enable) {
1467 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
1468 AR5K_PHY_RESTART_DIV_GC, 0xc);
1469
1470 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
1471 AR5K_PHY_FAST_ANT_DIV_EN);
1472 } else {
1473 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
1474 AR5K_PHY_RESTART_DIV_GC, 0x8);
1475
1476 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
1477 AR5K_PHY_FAST_ANT_DIV_EN);
1478 }
1479}
1480
1481/*
1482 * Set antenna operating mode
1483 */
1484void
1485ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
1486{
1487 struct ieee80211_channel *channel = &ah->ah_current_channel;
1488 bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div;
1489 bool use_def_for_sg;
1490 u8 def_ant, tx_ant, ee_mode;
1491 u32 sta_id1 = 0;
1492
1493 def_ant = ah->ah_def_ant;
1494
1495 ATH5K_TRACE(ah->ah_sc);
1496
1497 switch (channel->hw_value & CHANNEL_MODES) {
1498 case CHANNEL_A:
1499 case CHANNEL_T:
1500 case CHANNEL_XR:
1501 ee_mode = AR5K_EEPROM_MODE_11A;
1502 break;
1503 case CHANNEL_G:
1504 case CHANNEL_TG:
1505 ee_mode = AR5K_EEPROM_MODE_11G;
1506 break;
1507 case CHANNEL_B:
1508 ee_mode = AR5K_EEPROM_MODE_11B;
1509 break;
1510 default:
1511 ATH5K_ERR(ah->ah_sc,
1512 "invalid channel: %d\n", channel->center_freq);
1513 return;
1514 }
1515
1516 switch (ant_mode) {
1517 case AR5K_ANTMODE_DEFAULT:
1518 tx_ant = 0;
1519 use_def_for_tx = false;
1520 update_def_on_tx = false;
1521 use_def_for_rts = false;
1522 use_def_for_sg = false;
1523 fast_div = true;
1524 break;
1525 case AR5K_ANTMODE_FIXED_A:
1526 def_ant = 1;
1527 tx_ant = 0;
1528 use_def_for_tx = true;
1529 update_def_on_tx = false;
1530 use_def_for_rts = true;
1531 use_def_for_sg = true;
1532 fast_div = false;
1533 break;
1534 case AR5K_ANTMODE_FIXED_B:
1535 def_ant = 2;
1536 tx_ant = 0;
1537 use_def_for_tx = true;
1538 update_def_on_tx = false;
1539 use_def_for_rts = true;
1540 use_def_for_sg = true;
1541 fast_div = false;
1542 break;
1543 case AR5K_ANTMODE_SINGLE_AP:
1544 def_ant = 1; /* updated on tx */
1545 tx_ant = 0;
1546 use_def_for_tx = true;
1547 update_def_on_tx = true;
1548 use_def_for_rts = true;
1549 use_def_for_sg = true;
1550 fast_div = true;
1551 break;
1552 case AR5K_ANTMODE_SECTOR_AP:
1553 tx_ant = 1; /* variable */
1554 use_def_for_tx = false;
1555 update_def_on_tx = false;
1556 use_def_for_rts = true;
1557 use_def_for_sg = false;
1558 fast_div = false;
1559 break;
1560 case AR5K_ANTMODE_SECTOR_STA:
1561 tx_ant = 1; /* variable */
1562 use_def_for_tx = true;
1563 update_def_on_tx = false;
1564 use_def_for_rts = true;
1565 use_def_for_sg = false;
1566 fast_div = true;
1567 break;
1568 case AR5K_ANTMODE_DEBUG:
1569 def_ant = 1;
1570 tx_ant = 2;
1571 use_def_for_tx = false;
1572 update_def_on_tx = false;
1573 use_def_for_rts = false;
1574 use_def_for_sg = false;
1575 fast_div = false;
1576 break;
1577 default:
1578 return;
1579 }
1580
1581 ah->ah_tx_ant = tx_ant;
1582 ah->ah_ant_mode = ant_mode;
1583
1584 sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0;
1585 sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0;
1586 sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0;
1587 sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0;
1588
1589 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS);
1590
1591 if (sta_id1)
1592 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1);
1593
1594 /* Note: set diversity before default antenna
1595 * because it won't work correctly */
1596 ath5k_hw_set_fast_div(ah, ee_mode, fast_div);
1597 ath5k_hw_set_def_antenna(ah, def_ant);
1598}
1599
1436 1600
1437/****************\ 1601/****************\
1438* TX power setup * 1602* TX power setup *