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:
Родитель
6d5eaafa55
Коммит
8f655dde24
|
@ -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;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче