diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 493 |
1 files changed, 464 insertions, 29 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index b48b29dca3d2..d0d1c350025a 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -168,9 +168,6 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | |||
168 | * tx power and a Peak to Average Power Detector (PAPD) will try | 168 | * tx power and a Peak to Average Power Detector (PAPD) will try |
169 | * to measure the gain. | 169 | * to measure the gain. |
170 | * | 170 | * |
171 | * TODO: Use propper tx power setting for the probe packet so | ||
172 | * that we don't observe a serious power drop on the receiver | ||
173 | * | ||
174 | * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) | 171 | * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) |
175 | * just after we enable the probe so that we don't mess with | 172 | * just after we enable the probe so that we don't mess with |
176 | * standard traffic ? Maybe it's time to use sw interrupts and | 173 | * standard traffic ? Maybe it's time to use sw interrupts and |
@@ -186,7 +183,7 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) | |||
186 | 183 | ||
187 | /* Send the packet with 2dB below max power as | 184 | /* Send the packet with 2dB below max power as |
188 | * patent doc suggest */ | 185 | * patent doc suggest */ |
189 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, | 186 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4, |
190 | AR5K_PHY_PAPD_PROBE_TXPOWER) | | 187 | AR5K_PHY_PAPD_PROBE_TXPOWER) | |
191 | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); | 188 | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); |
192 | 189 | ||
@@ -1356,6 +1353,257 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1356 | return ret; | 1353 | return ret; |
1357 | } | 1354 | } |
1358 | 1355 | ||
1356 | /***************************\ | ||
1357 | * Spur mitigation functions * | ||
1358 | \***************************/ | ||
1359 | |||
1360 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
1361 | struct ieee80211_channel *channel) | ||
1362 | { | ||
1363 | u8 refclk_freq; | ||
1364 | |||
1365 | if ((ah->ah_radio == AR5K_RF5112) || | ||
1366 | (ah->ah_radio == AR5K_RF5413) || | ||
1367 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
1368 | refclk_freq = 40; | ||
1369 | else | ||
1370 | refclk_freq = 32; | ||
1371 | |||
1372 | if ((channel->center_freq % refclk_freq != 0) && | ||
1373 | ((channel->center_freq % refclk_freq < 10) || | ||
1374 | (channel->center_freq % refclk_freq > 22))) | ||
1375 | return true; | ||
1376 | else | ||
1377 | return false; | ||
1378 | } | ||
1379 | |||
1380 | void | ||
1381 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | ||
1382 | struct ieee80211_channel *channel) | ||
1383 | { | ||
1384 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1385 | u32 mag_mask[4] = {0, 0, 0, 0}; | ||
1386 | u32 pilot_mask[2] = {0, 0}; | ||
1387 | /* Note: fbin values are scaled up by 2 */ | ||
1388 | u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window; | ||
1389 | s32 spur_delta_phase, spur_freq_sigma_delta; | ||
1390 | s32 spur_offset, num_symbols_x16; | ||
1391 | u8 num_symbol_offsets, i, freq_band; | ||
1392 | |||
1393 | /* Convert current frequency to fbin value (the same way channels | ||
1394 | * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale | ||
1395 | * up by 2 so we can compare it later */ | ||
1396 | if (channel->hw_value & CHANNEL_2GHZ) { | ||
1397 | chan_fbin = (channel->center_freq - 2300) * 10; | ||
1398 | freq_band = AR5K_EEPROM_BAND_2GHZ; | ||
1399 | } else { | ||
1400 | chan_fbin = (channel->center_freq - 4900) * 10; | ||
1401 | freq_band = AR5K_EEPROM_BAND_5GHZ; | ||
1402 | } | ||
1403 | |||
1404 | /* Check if any spur_chan_fbin from EEPROM is | ||
1405 | * within our current channel's spur detection range */ | ||
1406 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; | ||
1407 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; | ||
1408 | /* XXX: Half/Quarter channels ?*/ | ||
1409 | if (channel->hw_value & CHANNEL_TURBO) | ||
1410 | spur_detection_window *= 2; | ||
1411 | |||
1412 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { | ||
1413 | spur_chan_fbin = ee->ee_spur_chans[i][freq_band]; | ||
1414 | |||
1415 | /* Note: mask cleans AR5K_EEPROM_NO_SPUR flag | ||
1416 | * so it's zero if we got nothing from EEPROM */ | ||
1417 | if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) { | ||
1418 | spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; | ||
1419 | break; | ||
1420 | } | ||
1421 | |||
1422 | if ((chan_fbin - spur_detection_window <= | ||
1423 | (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) && | ||
1424 | (chan_fbin + spur_detection_window >= | ||
1425 | (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) { | ||
1426 | spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; | ||
1427 | break; | ||
1428 | } | ||
1429 | } | ||
1430 | |||
1431 | /* We need to enable spur filter for this channel */ | ||
1432 | if (spur_chan_fbin) { | ||
1433 | spur_offset = spur_chan_fbin - chan_fbin; | ||
1434 | /* | ||
1435 | * Calculate deltas: | ||
1436 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 | ||
1437 | * spur_delta_phase -> spur_offset / chip_freq << 11 | ||
1438 | * Note: Both values have 100KHz resolution | ||
1439 | */ | ||
1440 | /* XXX: Half/Quarter rate channels ? */ | ||
1441 | switch (channel->hw_value) { | ||
1442 | case CHANNEL_A: | ||
1443 | /* Both sample_freq and chip_freq are 40MHz */ | ||
1444 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1445 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1446 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1447 | break; | ||
1448 | case CHANNEL_G: | ||
1449 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
1450 | * (for b compatibility) */ | ||
1451 | spur_freq_sigma_delta = (spur_offset << 8) / 55; | ||
1452 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1453 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1454 | break; | ||
1455 | case CHANNEL_T: | ||
1456 | case CHANNEL_TG: | ||
1457 | /* Both sample_freq and chip_freq are 80MHz */ | ||
1458 | spur_delta_phase = (spur_offset << 16) / 25; | ||
1459 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1460 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; | ||
1461 | break; | ||
1462 | default: | ||
1463 | return; | ||
1464 | } | ||
1465 | |||
1466 | /* Calculate pilot and magnitude masks */ | ||
1467 | |||
1468 | /* Scale up spur_offset by 1000 to switch to 100HZ resolution | ||
1469 | * and divide by symbol_width to find how many symbols we have | ||
1470 | * Note: number of symbols is scaled up by 16 */ | ||
1471 | num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width; | ||
1472 | |||
1473 | /* Spur is on a symbol if num_symbols_x16 % 16 is zero */ | ||
1474 | if (!(num_symbols_x16 & 0xF)) | ||
1475 | /* _X_ */ | ||
1476 | num_symbol_offsets = 3; | ||
1477 | else | ||
1478 | /* _xx_ */ | ||
1479 | num_symbol_offsets = 4; | ||
1480 | |||
1481 | for (i = 0; i < num_symbol_offsets; i++) { | ||
1482 | |||
1483 | /* Calculate pilot mask */ | ||
1484 | s32 curr_sym_off = | ||
1485 | (num_symbols_x16 / 16) + i + 25; | ||
1486 | |||
1487 | /* Pilot magnitude mask seems to be a way to | ||
1488 | * declare the boundaries for our detection | ||
1489 | * window or something, it's 2 for the middle | ||
1490 | * value(s) where the symbol is expected to be | ||
1491 | * and 1 on the boundary values */ | ||
1492 | u8 plt_mag_map = | ||
1493 | (i == 0 || i == (num_symbol_offsets - 1)) | ||
1494 | ? 1 : 2; | ||
1495 | |||
1496 | if (curr_sym_off >= 0 && curr_sym_off <= 32) { | ||
1497 | if (curr_sym_off <= 25) | ||
1498 | pilot_mask[0] |= 1 << curr_sym_off; | ||
1499 | else if (curr_sym_off >= 27) | ||
1500 | pilot_mask[0] |= 1 << (curr_sym_off - 1); | ||
1501 | } else if (curr_sym_off >= 33 && curr_sym_off <= 52) | ||
1502 | pilot_mask[1] |= 1 << (curr_sym_off - 33); | ||
1503 | |||
1504 | /* Calculate magnitude mask (for viterbi decoder) */ | ||
1505 | if (curr_sym_off >= -1 && curr_sym_off <= 14) | ||
1506 | mag_mask[0] |= | ||
1507 | plt_mag_map << (curr_sym_off + 1) * 2; | ||
1508 | else if (curr_sym_off >= 15 && curr_sym_off <= 30) | ||
1509 | mag_mask[1] |= | ||
1510 | plt_mag_map << (curr_sym_off - 15) * 2; | ||
1511 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) | ||
1512 | mag_mask[2] |= | ||
1513 | plt_mag_map << (curr_sym_off - 31) * 2; | ||
1514 | else if (curr_sym_off >= 46 && curr_sym_off <= 53) | ||
1515 | mag_mask[3] |= | ||
1516 | plt_mag_map << (curr_sym_off - 47) * 2; | ||
1517 | |||
1518 | } | ||
1519 | |||
1520 | /* Write settings on hw to enable spur filter */ | ||
1521 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, | ||
1522 | AR5K_PHY_BIN_MASK_CTL_RATE, 0xff); | ||
1523 | /* XXX: Self correlator also ? */ | ||
1524 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
1525 | AR5K_PHY_IQ_PILOT_MASK_EN | | ||
1526 | AR5K_PHY_IQ_CHAN_MASK_EN | | ||
1527 | AR5K_PHY_IQ_SPUR_FILT_EN); | ||
1528 | |||
1529 | /* Set delta phase and freq sigma delta */ | ||
1530 | ath5k_hw_reg_write(ah, | ||
1531 | AR5K_REG_SM(spur_delta_phase, | ||
1532 | AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) | | ||
1533 | AR5K_REG_SM(spur_freq_sigma_delta, | ||
1534 | AR5K_PHY_TIMING_11_SPUR_FREQ_SD) | | ||
1535 | AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC, | ||
1536 | AR5K_PHY_TIMING_11); | ||
1537 | |||
1538 | /* Write pilot masks */ | ||
1539 | ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7); | ||
1540 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, | ||
1541 | AR5K_PHY_TIMING_8_PILOT_MASK_2, | ||
1542 | pilot_mask[1]); | ||
1543 | |||
1544 | ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9); | ||
1545 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, | ||
1546 | AR5K_PHY_TIMING_10_PILOT_MASK_2, | ||
1547 | pilot_mask[1]); | ||
1548 | |||
1549 | /* Write magnitude masks */ | ||
1550 | ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1); | ||
1551 | ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2); | ||
1552 | ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3); | ||
1553 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, | ||
1554 | AR5K_PHY_BIN_MASK_CTL_MASK_4, | ||
1555 | mag_mask[3]); | ||
1556 | |||
1557 | ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1); | ||
1558 | ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2); | ||
1559 | ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3); | ||
1560 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, | ||
1561 | AR5K_PHY_BIN_MASK2_4_MASK_4, | ||
1562 | mag_mask[3]); | ||
1563 | |||
1564 | } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & | ||
1565 | AR5K_PHY_IQ_SPUR_FILT_EN) { | ||
1566 | /* Clean up spur mitigation settings and disable fliter */ | ||
1567 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, | ||
1568 | AR5K_PHY_BIN_MASK_CTL_RATE, 0); | ||
1569 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ, | ||
1570 | AR5K_PHY_IQ_PILOT_MASK_EN | | ||
1571 | AR5K_PHY_IQ_CHAN_MASK_EN | | ||
1572 | AR5K_PHY_IQ_SPUR_FILT_EN); | ||
1573 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11); | ||
1574 | |||
1575 | /* Clear pilot masks */ | ||
1576 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7); | ||
1577 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, | ||
1578 | AR5K_PHY_TIMING_8_PILOT_MASK_2, | ||
1579 | 0); | ||
1580 | |||
1581 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9); | ||
1582 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, | ||
1583 | AR5K_PHY_TIMING_10_PILOT_MASK_2, | ||
1584 | 0); | ||
1585 | |||
1586 | /* Clear magnitude masks */ | ||
1587 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1); | ||
1588 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2); | ||
1589 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3); | ||
1590 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, | ||
1591 | AR5K_PHY_BIN_MASK_CTL_MASK_4, | ||
1592 | 0); | ||
1593 | |||
1594 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1); | ||
1595 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2); | ||
1596 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3); | ||
1597 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, | ||
1598 | AR5K_PHY_BIN_MASK2_4_MASK_4, | ||
1599 | 0); | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | /********************\ | ||
1604 | Misc PHY functions | ||
1605 | \********************/ | ||
1606 | |||
1359 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | 1607 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) |
1360 | { | 1608 | { |
1361 | ATH5K_TRACE(ah->ah_sc); | 1609 | ATH5K_TRACE(ah->ah_sc); |
@@ -1365,10 +1613,6 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) | |||
1365 | return 0; | 1613 | return 0; |
1366 | } | 1614 | } |
1367 | 1615 | ||
1368 | /********************\ | ||
1369 | Misc PHY functions | ||
1370 | \********************/ | ||
1371 | |||
1372 | /* | 1616 | /* |
1373 | * Get the PHY Chip revision | 1617 | * Get the PHY Chip revision |
1374 | */ | 1618 | */ |
@@ -1417,25 +1661,189 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1417 | return ret; | 1661 | return ret; |
1418 | } | 1662 | } |
1419 | 1663 | ||
1664 | /*****************\ | ||
1665 | * Antenna control * | ||
1666 | \*****************/ | ||
1667 | |||
1420 | void /*TODO:Boundary check*/ | 1668 | void /*TODO:Boundary check*/ |
1421 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) | 1669 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1422 | { | 1670 | { |
1423 | ATH5K_TRACE(ah->ah_sc); | 1671 | ATH5K_TRACE(ah->ah_sc); |
1424 | /*Just a try M.F.*/ | 1672 | |
1425 | if (ah->ah_version != AR5K_AR5210) | 1673 | if (ah->ah_version != AR5K_AR5210) |
1426 | ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); | 1674 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1427 | } | 1675 | } |
1428 | 1676 | ||
1429 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) | 1677 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) |
1430 | { | 1678 | { |
1431 | ATH5K_TRACE(ah->ah_sc); | 1679 | ATH5K_TRACE(ah->ah_sc); |
1432 | /*Just a try M.F.*/ | 1680 | |
1433 | if (ah->ah_version != AR5K_AR5210) | 1681 | if (ah->ah_version != AR5K_AR5210) |
1434 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | 1682 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; |
1435 | 1683 | ||
1436 | return false; /*XXX: What do we return for 5210 ?*/ | 1684 | return false; /*XXX: What do we return for 5210 ?*/ |
1437 | } | 1685 | } |
1438 | 1686 | ||
1687 | /* | ||
1688 | * Enable/disable fast rx antenna diversity | ||
1689 | */ | ||
1690 | static void | ||
1691 | ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) | ||
1692 | { | ||
1693 | switch (ee_mode) { | ||
1694 | case AR5K_EEPROM_MODE_11G: | ||
1695 | /* XXX: This is set to | ||
1696 | * disabled on initvals !!! */ | ||
1697 | case AR5K_EEPROM_MODE_11A: | ||
1698 | if (enable) | ||
1699 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1700 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1701 | else | ||
1702 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1703 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1704 | break; | ||
1705 | case AR5K_EEPROM_MODE_11B: | ||
1706 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1707 | AR5K_PHY_AGCCTL_OFDM_DIV_DIS); | ||
1708 | break; | ||
1709 | default: | ||
1710 | return; | ||
1711 | } | ||
1712 | |||
1713 | if (enable) { | ||
1714 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | ||
1715 | AR5K_PHY_RESTART_DIV_GC, 0xc); | ||
1716 | |||
1717 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | ||
1718 | AR5K_PHY_FAST_ANT_DIV_EN); | ||
1719 | } else { | ||
1720 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | ||
1721 | AR5K_PHY_RESTART_DIV_GC, 0x8); | ||
1722 | |||
1723 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | ||
1724 | AR5K_PHY_FAST_ANT_DIV_EN); | ||
1725 | } | ||
1726 | } | ||
1727 | |||
1728 | /* | ||
1729 | * Set antenna operating mode | ||
1730 | */ | ||
1731 | void | ||
1732 | ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | ||
1733 | { | ||
1734 | struct ieee80211_channel *channel = &ah->ah_current_channel; | ||
1735 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; | ||
1736 | bool use_def_for_sg; | ||
1737 | u8 def_ant, tx_ant, ee_mode; | ||
1738 | u32 sta_id1 = 0; | ||
1739 | |||
1740 | def_ant = ah->ah_def_ant; | ||
1741 | |||
1742 | ATH5K_TRACE(ah->ah_sc); | ||
1743 | |||
1744 | switch (channel->hw_value & CHANNEL_MODES) { | ||
1745 | case CHANNEL_A: | ||
1746 | case CHANNEL_T: | ||
1747 | case CHANNEL_XR: | ||
1748 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1749 | break; | ||
1750 | case CHANNEL_G: | ||
1751 | case CHANNEL_TG: | ||
1752 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1753 | break; | ||
1754 | case CHANNEL_B: | ||
1755 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1756 | break; | ||
1757 | default: | ||
1758 | ATH5K_ERR(ah->ah_sc, | ||
1759 | "invalid channel: %d\n", channel->center_freq); | ||
1760 | return; | ||
1761 | } | ||
1762 | |||
1763 | switch (ant_mode) { | ||
1764 | case AR5K_ANTMODE_DEFAULT: | ||
1765 | tx_ant = 0; | ||
1766 | use_def_for_tx = false; | ||
1767 | update_def_on_tx = false; | ||
1768 | use_def_for_rts = false; | ||
1769 | use_def_for_sg = false; | ||
1770 | fast_div = true; | ||
1771 | break; | ||
1772 | case AR5K_ANTMODE_FIXED_A: | ||
1773 | def_ant = 1; | ||
1774 | tx_ant = 0; | ||
1775 | use_def_for_tx = true; | ||
1776 | update_def_on_tx = false; | ||
1777 | use_def_for_rts = true; | ||
1778 | use_def_for_sg = true; | ||
1779 | fast_div = false; | ||
1780 | break; | ||
1781 | case AR5K_ANTMODE_FIXED_B: | ||
1782 | def_ant = 2; | ||
1783 | tx_ant = 0; | ||
1784 | use_def_for_tx = true; | ||
1785 | update_def_on_tx = false; | ||
1786 | use_def_for_rts = true; | ||
1787 | use_def_for_sg = true; | ||
1788 | fast_div = false; | ||
1789 | break; | ||
1790 | case AR5K_ANTMODE_SINGLE_AP: | ||
1791 | def_ant = 1; /* updated on tx */ | ||
1792 | tx_ant = 0; | ||
1793 | use_def_for_tx = true; | ||
1794 | update_def_on_tx = true; | ||
1795 | use_def_for_rts = true; | ||
1796 | use_def_for_sg = true; | ||
1797 | fast_div = true; | ||
1798 | break; | ||
1799 | case AR5K_ANTMODE_SECTOR_AP: | ||
1800 | tx_ant = 1; /* variable */ | ||
1801 | use_def_for_tx = false; | ||
1802 | update_def_on_tx = false; | ||
1803 | use_def_for_rts = true; | ||
1804 | use_def_for_sg = false; | ||
1805 | fast_div = false; | ||
1806 | break; | ||
1807 | case AR5K_ANTMODE_SECTOR_STA: | ||
1808 | tx_ant = 1; /* variable */ | ||
1809 | use_def_for_tx = true; | ||
1810 | update_def_on_tx = false; | ||
1811 | use_def_for_rts = true; | ||
1812 | use_def_for_sg = false; | ||
1813 | fast_div = true; | ||
1814 | break; | ||
1815 | case AR5K_ANTMODE_DEBUG: | ||
1816 | def_ant = 1; | ||
1817 | tx_ant = 2; | ||
1818 | use_def_for_tx = false; | ||
1819 | update_def_on_tx = false; | ||
1820 | use_def_for_rts = false; | ||
1821 | use_def_for_sg = false; | ||
1822 | fast_div = false; | ||
1823 | break; | ||
1824 | default: | ||
1825 | return; | ||
1826 | } | ||
1827 | |||
1828 | ah->ah_tx_ant = tx_ant; | ||
1829 | ah->ah_ant_mode = ant_mode; | ||
1830 | |||
1831 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; | ||
1832 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; | ||
1833 | sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0; | ||
1834 | sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0; | ||
1835 | |||
1836 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS); | ||
1837 | |||
1838 | if (sta_id1) | ||
1839 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); | ||
1840 | |||
1841 | /* Note: set diversity before default antenna | ||
1842 | * because it won't work correctly */ | ||
1843 | ath5k_hw_set_fast_div(ah, ee_mode, fast_div); | ||
1844 | ath5k_hw_set_def_antenna(ah, def_ant); | ||
1845 | } | ||
1846 | |||
1439 | 1847 | ||
1440 | /****************\ | 1848 | /****************\ |
1441 | * TX power setup * | 1849 | * TX power setup * |
@@ -1750,8 +2158,6 @@ done: | |||
1750 | * Get the max edge power for this channel if | 2158 | * Get the max edge power for this channel if |
1751 | * we have such data from EEPROM's Conformance Test | 2159 | * we have such data from EEPROM's Conformance Test |
1752 | * Limits (CTL), and limit max power if needed. | 2160 | * Limits (CTL), and limit max power if needed. |
1753 | * | ||
1754 | * FIXME: Only works for world regulatory domains | ||
1755 | */ | 2161 | */ |
1756 | static void | 2162 | static void |
1757 | ath5k_get_max_ctl_power(struct ath5k_hw *ah, | 2163 | ath5k_get_max_ctl_power(struct ath5k_hw *ah, |
@@ -1767,26 +2173,23 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
1767 | u8 ctl_idx = 0xFF; | 2173 | u8 ctl_idx = 0xFF; |
1768 | u32 target = channel->center_freq; | 2174 | u32 target = channel->center_freq; |
1769 | 2175 | ||
1770 | /* Find out a CTL for our mode that's not mapped | 2176 | ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); |
1771 | * on a specific reg domain. | 2177 | |
1772 | * | ||
1773 | * TODO: Map our current reg domain to one of the 3 available | ||
1774 | * reg domain ids so that we can support more CTLs. */ | ||
1775 | switch (channel->hw_value & CHANNEL_MODES) { | 2178 | switch (channel->hw_value & CHANNEL_MODES) { |
1776 | case CHANNEL_A: | 2179 | case CHANNEL_A: |
1777 | ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; | 2180 | ctl_mode |= AR5K_CTL_11A; |
1778 | break; | 2181 | break; |
1779 | case CHANNEL_G: | 2182 | case CHANNEL_G: |
1780 | ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; | 2183 | ctl_mode |= AR5K_CTL_11G; |
1781 | break; | 2184 | break; |
1782 | case CHANNEL_B: | 2185 | case CHANNEL_B: |
1783 | ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; | 2186 | ctl_mode |= AR5K_CTL_11B; |
1784 | break; | 2187 | break; |
1785 | case CHANNEL_T: | 2188 | case CHANNEL_T: |
1786 | ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; | 2189 | ctl_mode |= AR5K_CTL_TURBO; |
1787 | break; | 2190 | break; |
1788 | case CHANNEL_TG: | 2191 | case CHANNEL_TG: |
1789 | ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; | 2192 | ctl_mode |= AR5K_CTL_TURBOG; |
1790 | break; | 2193 | break; |
1791 | case CHANNEL_XR: | 2194 | case CHANNEL_XR: |
1792 | /* Fall through */ | 2195 | /* Fall through */ |
@@ -2482,8 +2885,19 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
2482 | for (i = 8; i <= 15; i++) | 2885 | for (i = 8; i <= 15; i++) |
2483 | rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; | 2886 | rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; |
2484 | 2887 | ||
2485 | ah->ah_txpower.txp_min_pwr = rates[7]; | 2888 | /* Now that we have all rates setup use table offset to |
2486 | ah->ah_txpower.txp_max_pwr = rates[0]; | 2889 | * match the power range set by user with the power indices |
2890 | * on PCDAC/PDADC table */ | ||
2891 | for (i = 0; i < 16; i++) { | ||
2892 | rates[i] += ah->ah_txpower.txp_offset; | ||
2893 | /* Don't get out of bounds */ | ||
2894 | if (rates[i] > 63) | ||
2895 | rates[i] = 63; | ||
2896 | } | ||
2897 | |||
2898 | /* Min/max in 0.25dB units */ | ||
2899 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; | ||
2900 | ah->ah_txpower.txp_max_pwr = 2 * rates[0]; | ||
2487 | ah->ah_txpower.txp_ofdm = rates[7]; | 2901 | ah->ah_txpower.txp_ofdm = rates[7]; |
2488 | } | 2902 | } |
2489 | 2903 | ||
@@ -2591,16 +3005,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2591 | return 0; | 3005 | return 0; |
2592 | } | 3006 | } |
2593 | 3007 | ||
2594 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) | 3008 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) |
2595 | { | 3009 | { |
2596 | /*Just a try M.F.*/ | 3010 | /*Just a try M.F.*/ |
2597 | struct ieee80211_channel *channel = &ah->ah_current_channel; | 3011 | struct ieee80211_channel *channel = &ah->ah_current_channel; |
3012 | u8 ee_mode; | ||
2598 | 3013 | ||
2599 | ATH5K_TRACE(ah->ah_sc); | 3014 | ATH5K_TRACE(ah->ah_sc); |
3015 | |||
3016 | switch (channel->hw_value & CHANNEL_MODES) { | ||
3017 | case CHANNEL_A: | ||
3018 | case CHANNEL_T: | ||
3019 | case CHANNEL_XR: | ||
3020 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
3021 | break; | ||
3022 | case CHANNEL_G: | ||
3023 | case CHANNEL_TG: | ||
3024 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
3025 | break; | ||
3026 | case CHANNEL_B: | ||
3027 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
3028 | break; | ||
3029 | default: | ||
3030 | ATH5K_ERR(ah->ah_sc, | ||
3031 | "invalid channel: %d\n", channel->center_freq); | ||
3032 | return -EINVAL; | ||
3033 | } | ||
3034 | |||
2600 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, | 3035 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, |
2601 | "changing txpower to %d\n", txpower); | 3036 | "changing txpower to %d\n", txpower); |
2602 | 3037 | ||
2603 | return ath5k_hw_txpower(ah, channel, mode, txpower); | 3038 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); |
2604 | } | 3039 | } |
2605 | 3040 | ||
2606 | #undef _ATH5K_PHY | 3041 | #undef _ATH5K_PHY |