Commit 8f655dde authored by Nick Kossifidis's avatar Nick Kossifidis Committed by John W. Linville

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: default avatarNick Kossifidis <mickflemm@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6d5eaafa
......@@ -204,9 +204,9 @@
#define AR5K_TUNE_CWMAX_11B 1023
#define AR5K_TUNE_CWMAX_XR 7
#define AR5K_TUNE_NOISE_FLOOR -72
#define AR5K_TUNE_MAX_TXPOWER 60
#define AR5K_TUNE_DEFAULT_TXPOWER 30
#define AR5K_TUNE_TPC_TXPOWER true
#define AR5K_TUNE_MAX_TXPOWER 63
#define AR5K_TUNE_DEFAULT_TXPOWER 25
#define AR5K_TUNE_TPC_TXPOWER false
#define AR5K_TUNE_ANT_DIVERSITY true
#define AR5K_TUNE_HWTXTRIES 4
......@@ -551,11 +551,11 @@ enum ath5k_pkt_type {
*/
#define AR5K_TXPOWER_OFDM(_r, _v) ( \
((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) ( \
(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;
u8 ah_offset[AR5K_MAX_RF_BANKS];
struct {
u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
u16 txp_rates[AR5K_MAX_RATES];
s16 txp_min;
s16 txp_max;
/* Temporary tables used for interpolation */
u8 tmpL[AR5K_EEPROM_N_PD_GAINS]
[AR5K_EEPROM_POWER_TABLE_SIZE];
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;
/* Values in 0.25dB units */
s16 txp_min_pwr;
s16 txp_max_pwr;
s16 txp_offset;
s16 txp_ofdm;
/* Values in dB units */
s16 txp_cck_ofdm_pwr_delta;
s16 txp_cck_ofdm_gainf_delta;
} ah_txpower;
struct {
......@@ -1161,6 +1173,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
/* EEPROM access functions */
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 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 int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* TX power setup */
extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower);
extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
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, u8 ee_mode, u8 txpower);
/*
* Functions used internaly
......
......@@ -341,6 +341,8 @@ void ath5k_hw_detach(struct ath5k_hw *ah)
if (ah->ah_rf_banks != NULL)
kfree(ah->ah_rf_banks);
ath5k_eeprom_detach(ah);
/* assume interrupts are down */
kfree(ah);
}
......@@ -1209,6 +1209,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
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) {
keyidx = info->control.hw_key->hw_key_idx;
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;
}
/* 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;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb),
......@@ -2601,12 +2607,6 @@ ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel)
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);
if (ret) {
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;
}
tx_power += ah->ah_txpower.txp_offset;
if (tx_power > AR5K_TUNE_MAX_TXPOWER)
tx_power = AR5K_TUNE_MAX_TXPOWER;
/* Clear descriptor */
memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
......
This diff is collapsed.
......@@ -1553,6 +1553,19 @@
/*===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
*/
......@@ -2550,6 +2563,12 @@
#define AR5K_PHY_TPC_RG1 0xa258
#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
#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_PD_GAIN_OVERLAP 0x0000000F
......
......@@ -664,10 +664,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
/* Set CCK to OFDM power delta */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
int16_t cck_ofdm_pwr_delta;
s16 cck_ofdm_pwr_delta;
/* Adjust power delta for channel 14 */
if (channel->center_freq == 2484)
......@@ -678,15 +675,24 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
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 (channel->hw_value == CHANNEL_G)
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_REG_SM((cck_ofdm_pwr_delta * -1),
AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
AR5K_PHY_TX_PWR_ADJ);
else
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 */
......@@ -994,7 +1000,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/*
* 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)
return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment