ath5k: Add tx power calibration support

* Add tx power calibration support
* Add a few tx power limits
* Hardcode default power to 12.5dB
* Disable TPC for now

v2: Address Jiri's comments

Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Nick Kossifidis 2009-03-15 22:20:35 +02:00 коммит произвёл John W. Linville
Родитель 6d5eaafa55
Коммит 8f655dde24
7 изменённых файлов: 1177 добавлений и 94 удалений

Просмотреть файл

@ -204,9 +204,9 @@
#define AR5K_TUNE_CWMAX_11B 1023 #define AR5K_TUNE_CWMAX_11B 1023
#define AR5K_TUNE_CWMAX_XR 7 #define AR5K_TUNE_CWMAX_XR 7
#define AR5K_TUNE_NOISE_FLOOR -72 #define AR5K_TUNE_NOISE_FLOOR -72
#define AR5K_TUNE_MAX_TXPOWER 60 #define AR5K_TUNE_MAX_TXPOWER 63
#define AR5K_TUNE_DEFAULT_TXPOWER 30 #define AR5K_TUNE_DEFAULT_TXPOWER 25
#define AR5K_TUNE_TPC_TXPOWER true #define AR5K_TUNE_TPC_TXPOWER false
#define AR5K_TUNE_ANT_DIVERSITY true #define AR5K_TUNE_ANT_DIVERSITY true
#define AR5K_TUNE_HWTXTRIES 4 #define AR5K_TUNE_HWTXTRIES 4
@ -551,11 +551,11 @@ enum ath5k_pkt_type {
*/ */
#define AR5K_TXPOWER_OFDM(_r, _v) ( \ #define AR5K_TXPOWER_OFDM(_r, _v) ( \
((0 & 1) << ((_v) + 6)) | \ ((0 & 1) << ((_v) + 6)) | \
(((ah->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v)) \ (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \
) )
#define AR5K_TXPOWER_CCK(_r, _v) ( \ #define AR5K_TXPOWER_CCK(_r, _v) ( \
(ah->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v) \ (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \
) )
/* /*
@ -1085,13 +1085,25 @@ struct ath5k_hw {
struct ath5k_gain ah_gain; struct ath5k_gain ah_gain;
u8 ah_offset[AR5K_MAX_RF_BANKS]; u8 ah_offset[AR5K_MAX_RF_BANKS];
struct { struct {
u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE]; /* Temporary tables used for interpolation */
u16 txp_rates[AR5K_MAX_RATES]; u8 tmpL[AR5K_EEPROM_N_PD_GAINS]
s16 txp_min; [AR5K_EEPROM_POWER_TABLE_SIZE];
s16 txp_max; u8 tmpR[AR5K_EEPROM_N_PD_GAINS]
[AR5K_EEPROM_POWER_TABLE_SIZE];
u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
u16 txp_rates_power_table[AR5K_MAX_RATES];
u8 txp_min_idx;
bool txp_tpc; bool txp_tpc;
/* Values in 0.25dB units */
s16 txp_min_pwr;
s16 txp_max_pwr;
s16 txp_offset;
s16 txp_ofdm; s16 txp_ofdm;
/* Values in dB units */
s16 txp_cck_ofdm_pwr_delta;
s16 txp_cck_ofdm_gainf_delta;
} ah_txpower; } ah_txpower;
struct { struct {
@ -1161,6 +1173,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
/* EEPROM access functions */ /* EEPROM access functions */
extern int ath5k_eeprom_init(struct ath5k_hw *ah); extern int ath5k_eeprom_init(struct ath5k_hw *ah);
extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
@ -1256,8 +1269,8 @@ extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* TX power setup */ /* TX power setup */
extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower); extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power); extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower);
/* /*
* Functions used internaly * Functions used internaly

Просмотреть файл

@ -341,6 +341,8 @@ void ath5k_hw_detach(struct ath5k_hw *ah)
if (ah->ah_rf_banks != NULL) if (ah->ah_rf_banks != NULL)
kfree(ah->ah_rf_banks); kfree(ah->ah_rf_banks);
ath5k_eeprom_detach(ah);
/* assume interrupts are down */ /* assume interrupts are down */
kfree(ah); kfree(ah);
} }

Просмотреть файл

@ -1209,6 +1209,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
pktlen = skb->len; pktlen = skb->len;
/* FIXME: If we are in g mode and rate is a CCK rate
* subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
* from tx power (value is in dB units already) */
if (info->control.hw_key) { if (info->control.hw_key) {
keyidx = info->control.hw_key->hw_key_idx; keyidx = info->control.hw_key->hw_key_idx;
pktlen += info->control.hw_key->icv_len; pktlen += info->control.hw_key->icv_len;
@ -2037,6 +2040,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
antenna = sc->bsent & 4 ? 2 : 1; antenna = sc->bsent & 4 ? 2 : 1;
} }
/* FIXME: If we are in g mode and rate is a CCK rate
* subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
* from tx power (value is in dB units already) */
ds->ds_data = bf->skbaddr; ds->ds_data = bf->skbaddr;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb), ieee80211_get_hdrlen_from_skb(skb),
@ -2601,12 +2607,6 @@ ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel)
goto err; goto err;
} }
/*
* This is needed only to setup initial state
* but it's best done after a reset.
*/
ath5k_hw_set_txpower_limit(sc->ah, 0);
ret = ath5k_rx_start(sc); ret = ath5k_rx_start(sc);
if (ret) { if (ret) {
ATH5K_ERR(sc, "can't start recv logic\n"); ATH5K_ERR(sc, "can't start recv logic\n");

Просмотреть файл

@ -194,6 +194,10 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
return -EINVAL; return -EINVAL;
} }
tx_power += ah->ah_txpower.txp_offset;
if (tx_power > AR5K_TUNE_MAX_TXPOWER)
tx_power = AR5K_TUNE_MAX_TXPOWER;
/* Clear descriptor */ /* Clear descriptor */
memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1553,6 +1553,19 @@
/*===5212 Specific PCU registers===*/ /*===5212 Specific PCU registers===*/
/*
* Transmit power control register
*/
#define AR5K_TPC 0x80e8
#define AR5K_TPC_ACK 0x0000003f /* ack frames */
#define AR5K_TPC_ACK_S 0
#define AR5K_TPC_CTS 0x00003f00 /* cts frames */
#define AR5K_TPC_CTS_S 8
#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */
#define AR5K_TPC_CHIRP_S 16
#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */
#define AR5K_TPC_DOPPLER_S 24
/* /*
* XR (eXtended Range) mode register * XR (eXtended Range) mode register
*/ */
@ -2550,6 +2563,12 @@
#define AR5K_PHY_TPC_RG1 0xa258 #define AR5K_PHY_TPC_RG1 0xa258
#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 #define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 #define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14
#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000
#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16
#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000
#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18
#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000
#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20
#define AR5K_PHY_TPC_RG5 0xa26C #define AR5K_PHY_TPC_RG5 0xa26C
#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F #define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F

Просмотреть файл

@ -664,29 +664,35 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
{ {
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
s16 cck_ofdm_pwr_delta;
/* Set CCK to OFDM power delta */ /* Adjust power delta for channel 14 */
if (channel->center_freq == 2484)
cck_ofdm_pwr_delta =
((ee->ee_cck_ofdm_power_delta -
ee->ee_scaled_cck_delta) * 2) / 10;
else
cck_ofdm_pwr_delta =
(ee->ee_cck_ofdm_power_delta * 2) / 10;
/* Set CCK to OFDM power delta on tx power
* adjustment register */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
int16_t cck_ofdm_pwr_delta;
/* Adjust power delta for channel 14 */
if (channel->center_freq == 2484)
cck_ofdm_pwr_delta =
((ee->ee_cck_ofdm_power_delta -
ee->ee_scaled_cck_delta) * 2) / 10;
else
cck_ofdm_pwr_delta =
(ee->ee_cck_ofdm_power_delta * 2) / 10;
if (channel->hw_value == CHANNEL_G) if (channel->hw_value == CHANNEL_G)
ath5k_hw_reg_write(ah, ath5k_hw_reg_write(ah,
AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1), AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
AR5K_REG_SM((cck_ofdm_pwr_delta * -1), AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
AR5K_PHY_TX_PWR_ADJ); AR5K_PHY_TX_PWR_ADJ);
else else
ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
} else {
/* For older revs we scale power on sw during tx power
* setup */
ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
ah->ah_txpower.txp_cck_ofdm_gainf_delta =
ee->ee_cck_ofdm_gain_delta;
} }
/* Set antenna idle switch table */ /* Set antenna idle switch table */
@ -994,7 +1000,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* /*
* Set TX power (FIXME) * Set TX power (FIXME)
*/ */
ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER); ret = ath5k_hw_txpower(ah, channel, ee_mode,
AR5K_TUNE_DEFAULT_TXPOWER);
if (ret) if (ret)
return ret; return ret;