Static void ar9287_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { const struct ar9287_eeprom *eep = sc->sc_eep; const struct ar9287_modal_eep_header *modal = &eep->modalHeader; uint8_t tpow_cck[4], tpow_ofdm[4]; #ifndef IEEE80211_NO_HT uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4]; uint8_t tpow_ht20[8], tpow_ht40[8]; uint8_t ht40inc; #endif int16_t pwr = 0, max_ant_gain, power[ATHN_POWER_COUNT]; int i; ar9287_set_power_calib(sc, c); /* Compute transmit power reduction due to antenna gain. */ max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]); /* XXX */ /* * Reduce scaled power by number of active chains to get per-chain * transmit power level. */ if (sc->sc_ntxchains == 2) pwr -= AR_PWR_DECREASE_FOR_2_CHAIN; if (pwr < 0) pwr = 0; /* Get CCK target powers. */ ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck, AR9287_NUM_2G_CCK_TARGET_POWERS, tpow_cck); /* Get OFDM target powers. */ ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G, AR9287_NUM_2G_20_TARGET_POWERS, tpow_ofdm); #ifndef IEEE80211_NO_HT /* Get HT-20 target powers. */ ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20, AR9287_NUM_2G_20_TARGET_POWERS, tpow_ht20); if (extc != NULL) { /* Get HT-40 target powers. */ ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40, eep->calTargetPower2GHT40, AR9287_NUM_2G_40_TARGET_POWERS, tpow_ht40); /* Get secondary channel CCK target powers. */ ar5008_get_lg_tpow(sc, extc, AR_CTL_11B, eep->calTargetPowerCck, AR9287_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext); /* Get secondary channel OFDM target powers. */ ar5008_get_lg_tpow(sc, extc, AR_CTL_11G, eep->calTargetPower2G, AR9287_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext); } #endif memset(power, 0, sizeof(power)); /* Shuffle target powers accross transmit rates. */ power[ATHN_POWER_OFDM6 ] = power[ATHN_POWER_OFDM9 ] = power[ATHN_POWER_OFDM12 ] = power[ATHN_POWER_OFDM18 ] = power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0]; power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1]; power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2]; power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3]; power[ATHN_POWER_XR ] = tpow_ofdm[0]; power[ATHN_POWER_CCK1_LP ] = tpow_cck[0]; power[ATHN_POWER_CCK2_LP ] = power[ATHN_POWER_CCK2_SP ] = tpow_cck[1]; power[ATHN_POWER_CCK55_LP] = power[ATHN_POWER_CCK55_SP] = tpow_cck[2]; power[ATHN_POWER_CCK11_LP] = power[ATHN_POWER_CCK11_SP] = tpow_cck[3]; #ifndef IEEE80211_NO_HT for (i = 0; i < nitems(tpow_ht20); i++) power[ATHN_POWER_HT20(i)] = tpow_ht20[i]; if (extc != NULL) { /* Correct PAR difference between HT40 and HT20/Legacy. */ if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) ht40inc = modal->ht40PowerIncForPdadc; else ht40inc = AR_HT40_POWER_INC_FOR_PDADC; for (i = 0; i < nitems(tpow_ht40); i++) power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc; power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0]; power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0]; power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0]; if (IEEE80211_IS_CHAN_2GHZ(c)) power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0]; } #endif for (i = 0; i < ATHN_POWER_COUNT; i++) { power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */ if (power[i] > AR_MAX_RATE_POWER) power[i] = AR_MAX_RATE_POWER; } /* Commit transmit power values to hardware. */ ar5008_write_txpower(sc, power); }
void ar9380_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { const struct ar9380_eeprom *eep = sc->eep; uint8_t tpow_cck[4], tpow_ofdm[4]; uint8_t tpow_ht20[14], tpow_ht40[14]; int16_t power[ATHN_POWER_COUNT]; if (IEEE80211_IS_CHAN_2GHZ(c)) { /* Get CCK target powers. */ ar9003_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetFbinCck, eep->calTargetPowerCck, AR9380_NUM_2G_CCK_TARGET_POWERS, tpow_cck); /* Get OFDM target powers. */ ar9003_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetFbin2G, eep->calTargetPower2G, AR9380_NUM_2G_20_TARGET_POWERS, tpow_ofdm); /* Get HT-20 target powers. */ ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetFbin2GHT20, eep->calTargetPower2GHT20, AR9380_NUM_2G_20_TARGET_POWERS, tpow_ht20); if (extc != NULL) { /* Get HT-40 target powers. */ ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT40, eep->calTargetFbin2GHT40, eep->calTargetPower2GHT40, AR9380_NUM_2G_40_TARGET_POWERS, tpow_ht40); } } else { /* Get OFDM target powers. */ ar9003_get_lg_tpow(sc, c, AR_CTL_11A, eep->calTargetFbin5G, eep->calTargetPower5G, AR9380_NUM_5G_20_TARGET_POWERS, tpow_ofdm); /* Get HT-20 target powers. */ ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT20, eep->calTargetFbin5GHT20, eep->calTargetPower5GHT20, AR9380_NUM_5G_20_TARGET_POWERS, tpow_ht20); if (extc != NULL) { /* Get HT-40 target powers. */ ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT40, eep->calTargetFbin5GHT40, eep->calTargetPower5GHT40, AR9380_NUM_5G_40_TARGET_POWERS, tpow_ht40); } } memset(power, 0, sizeof(power)); /* Shuffle target powers accross transmit rates. */ power[ATHN_POWER_OFDM6 ] = power[ATHN_POWER_OFDM9 ] = power[ATHN_POWER_OFDM12] = power[ATHN_POWER_OFDM18] = power[ATHN_POWER_OFDM24] = tpow_ofdm[0]; power[ATHN_POWER_OFDM36] = tpow_ofdm[1]; power[ATHN_POWER_OFDM48] = tpow_ofdm[2]; power[ATHN_POWER_OFDM54] = tpow_ofdm[3]; if (IEEE80211_IS_CHAN_2GHZ(c)) { power[ATHN_POWER_CCK1_LP ] = power[ATHN_POWER_CCK2_LP ] = power[ATHN_POWER_CCK2_SP ] = power[ATHN_POWER_CCK55_LP] = tpow_cck[0]; power[ATHN_POWER_CCK55_SP] = tpow_cck[1]; power[ATHN_POWER_CCK11_LP] = tpow_cck[2]; power[ATHN_POWER_CCK11_SP] = tpow_cck[3]; } /* Next entry covers MCS0, MCS8 and MCS16. */ power[ATHN_POWER_HT20( 0)] = tpow_ht20[ 0]; /* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */ power[ATHN_POWER_HT20( 1)] = tpow_ht20[ 1]; power[ATHN_POWER_HT20( 4)] = tpow_ht20[ 2]; power[ATHN_POWER_HT20( 5)] = tpow_ht20[ 3]; power[ATHN_POWER_HT20( 6)] = tpow_ht20[ 4]; power[ATHN_POWER_HT20( 7)] = tpow_ht20[ 5]; power[ATHN_POWER_HT20(12)] = tpow_ht20[ 6]; power[ATHN_POWER_HT20(13)] = tpow_ht20[ 7]; power[ATHN_POWER_HT20(14)] = tpow_ht20[ 8]; power[ATHN_POWER_HT20(15)] = tpow_ht20[ 9]; power[ATHN_POWER_HT20(20)] = tpow_ht20[10]; power[ATHN_POWER_HT20(21)] = tpow_ht20[11]; power[ATHN_POWER_HT20(22)] = tpow_ht20[12]; power[ATHN_POWER_HT20(23)] = tpow_ht20[13]; if (extc != NULL) { /* Next entry covers MCS0, MCS8 and MCS16. */ power[ATHN_POWER_HT40( 0)] = tpow_ht40[ 0]; /* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */ power[ATHN_POWER_HT40( 1)] = tpow_ht40[ 1]; power[ATHN_POWER_HT40( 4)] = tpow_ht40[ 2]; power[ATHN_POWER_HT40( 5)] = tpow_ht40[ 3]; power[ATHN_POWER_HT40( 6)] = tpow_ht40[ 4]; power[ATHN_POWER_HT40( 7)] = tpow_ht40[ 5]; power[ATHN_POWER_HT40(12)] = tpow_ht40[ 6]; power[ATHN_POWER_HT40(13)] = tpow_ht40[ 7]; power[ATHN_POWER_HT40(14)] = tpow_ht40[ 8]; power[ATHN_POWER_HT40(15)] = tpow_ht40[ 9]; power[ATHN_POWER_HT40(20)] = tpow_ht40[10]; power[ATHN_POWER_HT40(21)] = tpow_ht40[11]; power[ATHN_POWER_HT40(22)] = tpow_ht40[12]; power[ATHN_POWER_HT40(23)] = tpow_ht40[13]; } /* Write transmit power values to hardware. */ ar9003_write_txpower(sc, power); /* Apply transmit power correction. */ ar9380_set_correction(sc, c); }