Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_paprd.c
48525 views
/*1* Copyright (c) 2013 Qualcomm Atheros, Inc.2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH8* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY9* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,10* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM11* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR12* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR13* PERFORMANCE OF THIS SOFTWARE.14*/1516#include "opt_ah.h"17#include "ah.h"18#include "ar9300.h"19#include "ah_internal.h"20#include "ar9300paprd.h"21#include "ar9300reg.h"222324#if ATH_SUPPORT_PAPRD2526static struct ar9300_paprd_pwr_adjust ar9300_paprd_pwr_adj_array[] = {27/* rate index , register offset , mask of register , */28{ALL_TARGET_HT20_5, AR_PHY_POWERTX_RATE5, AR_PHY_POWERTX_RATE5_POWERTXHT20_3,29/* mask offset of register , offset dB*/30AR_PHY_POWERTX_RATE5_POWERTXHT20_3_S, 1},31{ALL_TARGET_HT20_6, AR_PHY_POWERTX_RATE6, AR_PHY_POWERTX_RATE6_POWERTXHT20_4,32AR_PHY_POWERTX_RATE6_POWERTXHT20_4_S, 2},33{ALL_TARGET_HT20_7, AR_PHY_POWERTX_RATE6, AR_PHY_POWERTX_RATE6_POWERTXHT20_5,34AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S, 2},35{ALL_TARGET_HT40_5, AR_PHY_POWERTX_RATE7, AR_PHY_POWERTX_RATE7_POWERTXHT40_3,36AR_PHY_POWERTX_RATE7_POWERTXHT40_3_S, 1},37{ALL_TARGET_HT40_6, AR_PHY_POWERTX_RATE8, AR_PHY_POWERTX_RATE8_POWERTXHT40_4,38AR_PHY_POWERTX_RATE8_POWERTXHT40_4_S, 2},39{ALL_TARGET_HT40_7, AR_PHY_POWERTX_RATE8, AR_PHY_POWERTX_RATE8_POWERTXHT40_5,40AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S, 2},41{ALL_TARGET_LEGACY_54, AR_PHY_POWERTX_RATE2, AR_PHY_POWERTX_RATE2_POWERTX54M_7,42AR_PHY_POWERTX_RATE2_POWERTX54M_7_S, 2},43};4445HAL_BOOL create_pa_curve(u_int32_t * paprd_train_data_l,46u_int32_t *paprd_train_data_u, u_int32_t *pa_table, u_int32_t *g_fxp_ext,47int * pa_in);4849static int50ar9300_paprd_setup_single_table(struct ath_hal *ah, struct ieee80211_channel * chan)51{52int is_2g = IEEE80211_IS_CHAN_2GHZ(chan);53HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);54struct ath_hal_9300 *ahp = AH9300(ah);55int is_ht40 = 0;56u_int32_t am_mask = 0;57u_int32_t val = OS_REG_READ(ah, AR_2040_MODE);58u_int8_t target_power_val_t2[ar9300_rate_size];59int power_tblindex = 0, power_delta = 0;60int paprd_scale_factor = 5;6162const u_int8_t mask2num[8] = {630 /* 000 */,641 /* 001 */,651 /* 010 */,662 /* 011 */,671 /* 100 */,682 /* 101 */,692 /* 110 */,703 /* 111 */71};7273ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;7475#define ABS(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x)7677ar9300_set_target_power_from_eeprom(ah, ichan->channel, target_power_val_t2);78if (val & HAL_HT_MACMODE_2040) {79is_ht40 = 1;80}8182/*83* Note on paprd_scale_factor84* This factor is saved in eeprom as 3 bit fields in following fashion.85* In 5G there are 3 scale factors -- upper, mid and lower band.86* Upper band scale factor is coded in bits 25-27 of87* modal_header_5g.paprd_rate_mask_ht20.88* Mid band scale factor is coded in bits 28-30 of89* modal_header_5g.paprd_rate_mask_ht40.90* Lower band scale factor is coded in bits 25-27 of91* modal_header_5g.paprd_rate_mask_ht40.92* For 2G there is only one scale factor. It is saved in bits 25-27 of93* modal_header_2g.paprd_rate_mask_ht20.94*/95AH_PAPRD_GET_SCALE_FACTOR(paprd_scale_factor, eep, is_2g, ichan->channel);96if (is_2g) {97if (is_ht40) {98am_mask = ahp->ah_2g_paprd_rate_mask_ht40 & AH_PAPRD_AM_PM_MASK;99power_tblindex = ALL_TARGET_HT40_0_8_16;100} else {101am_mask = ahp->ah_2g_paprd_rate_mask_ht20 & AH_PAPRD_AM_PM_MASK;102power_tblindex = ALL_TARGET_HT20_0_8_16;103}104if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {105if (is_ht40) {106ahp->paprd_training_power =107target_power_val_t2[ALL_TARGET_HT40_7] + 2;108} else {109ahp->paprd_training_power =110target_power_val_t2[ALL_TARGET_HT20_7] + 2;111}112} else if (AR_SREV_POSEIDON(ah)) {113ahp->paprd_training_power = 25;114} else {115ahp->paprd_training_power =116OS_REG_READ_FIELD_ALT(ah, AR_PHY_POWERTX_RATE5,117AR_PHY_POWERTX_RATE5_POWERTXHT20_0);118if (ABS(target_power_val_t2[power_tblindex],119ahp->paprd_training_power) > paprd_scale_factor)120{121HALDEBUG(ah, HAL_DEBUG_CALIBRATE,122"%s[%d]: Chan %d paprd failing EEP PWR 0x%08x"123"TGT PWR 0x%08x\n", __func__, __LINE__, ichan->channel,124target_power_val_t2[power_tblindex],125ahp->paprd_training_power);126goto FAILED;127}128129power_delta =130ABS(ahp->paprd_training_power,131target_power_val_t2[power_tblindex]);132133power_delta = power_delta > 4 ? 0 : 4 - power_delta;134ahp->paprd_training_power =135ahp->paprd_training_power - power_delta;136}137138139} else {140if (is_ht40) {141ahp->paprd_training_power =142OS_REG_READ_FIELD_ALT(ah, AR_PHY_POWERTX_RATE8,143AR_PHY_POWERTX_RATE8_POWERTXHT40_5);144am_mask = ahp->ah_5g_paprd_rate_mask_ht40 & AH_PAPRD_AM_PM_MASK;145switch (mask2num[ahp->ah_tx_chainmask])146{147case 1:148power_delta = 6;149break;150case 2:151power_delta = 4;152break;153case 3:154power_delta = 2;155break;156default:157goto FAILED;158break;159}160power_tblindex = ALL_TARGET_HT40_7;161} else {162ahp->paprd_training_power =163OS_REG_READ_FIELD_ALT(ah, AR_PHY_POWERTX_RATE6,164AR_PHY_POWERTX_RATE6_POWERTXHT20_5);165am_mask = ahp->ah_5g_paprd_rate_mask_ht20 & AH_PAPRD_AM_PM_MASK;166switch (mask2num[ahp->ah_tx_chainmask])167{168case 1:169power_delta = 6;170break;171case 2:172power_delta = 4;173break;174case 3:175power_delta = 2;176break;177default:178goto FAILED;179break;180}181power_tblindex = ALL_TARGET_HT20_7;182}183/* Adjust for scale factor */184ahp->paprd_training_power += paprd_scale_factor;185/*186ath_hal_printf(ah, "%s[%d] paprd_scale_factor %d power_delta %d\n",187__func__, __LINE__, paprd_scale_factor, power_delta);188*/189if (ABS(target_power_val_t2[power_tblindex], ahp->paprd_training_power)190> paprd_scale_factor)191{192HALDEBUG(ah, HAL_DEBUG_CALIBRATE,193"%s[%d]: Chan %d paprd failing EEP PWR 0x%08x TGT PWR 0x%08x\n",194__func__, __LINE__, ichan->channel,195target_power_val_t2[power_tblindex], ahp->paprd_training_power);196goto FAILED;197}198ahp->paprd_training_power = ahp->paprd_training_power + power_delta;199}200201HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s 2G %d HT40 %d am_mask 0x%08x\n",202__func__, is_2g, is_ht40, am_mask);203OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,204am_mask);205if (AR_SREV_HORNET(ah)) {206OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,2070);208}209else {210OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,211am_mask);212}213214OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,215AR_PHY_PAPRD_HT40_MASK);216/* chain0 */217if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN0_MASK) {218OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,219AR_PHY_PAPRD_CTRL0_B0_USE_SINGLE_TABLE_MASK, 1);220OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,221AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_AM2PM_ENABLE_0, 1);222OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,223AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_AM2AM_ENABLE_0, 1);224OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,225AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_SCALING_ENA, 0);226OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,227AR_PHY_PAPRD_CTRL1_B0_PA_GAIN_SCALE_FACT_0_MASK, 181);228OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,229AR_PHY_PAPRD_CTRL1_B0_PAPRD_MAG_SCALE_FACT_0, 361);230OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,231AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_SCALING_ENA, 0);232OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,233AR_PHY_PAPRD_CTRL0_B0_PAPRD_MAG_THRSH_0, 3);234}235236/* chain1 */237if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN1_MASK) {238OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,239AR_PHY_PAPRD_CTRL0_B1_PAPRD_ADAPTIVE_USE_SINGLE_TABLE_1, 1);240OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,241AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_AM2PM_ENABLE_1, 1);242OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,243AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_AM2AM_ENABLE_1, 1);244OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,245AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_SCALING_ENA, 0);246OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,247AR_PHY_PAPRD_CTRL1_B1_PA_GAIN_SCALE_FACT_1_MASK, 181);248OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,249AR_PHY_PAPRD_CTRL1_B1_PAPRD_MAG_SCALE_FACT_1, 361);250OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,251AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_SCALING_ENA, 0);252OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,253AR_PHY_PAPRD_CTRL0_B1_PAPRD_MAG_THRSH_1, 3);254}255256/* chain2 */257if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK) {258OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,259AR_PHY_PAPRD_CTRL0_B2_PAPRD_ADAPTIVE_USE_SINGLE_TABLE_2, 1);260OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,261AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_AM2PM_ENABLE_2, 1);262OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,263AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_AM2AM_ENABLE_2, 1);264OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,265AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_SCALING_ENA, 0);266OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,267AR_PHY_PAPRD_CTRL1_B2_PA_GAIN_SCALE_FACT_2_MASK, 181);268OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,269AR_PHY_PAPRD_CTRL1_B2_PAPRD_MAG_SCALE_FACT_2, 361);270OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,271AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_SCALING_ENA, 0);272OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,273AR_PHY_PAPRD_CTRL0_B2_PAPRD_MAG_THRSH_2, 3);274}275276ar9300_enable_paprd(ah, AH_FALSE, chan);277if (AR_SREV_POSEIDON(ah)) {278OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,279AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30);280OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,281AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1);282OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,283AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1);284OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,285AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0);286OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,287AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0);288OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,289AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);290OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,291AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);292OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2_POSEIDON,293AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 148);294OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,295AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);296OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,297AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4);298OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,299AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);300OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,301AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);302OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,303AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -3);304OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,305AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, -15);306OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,307AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);308OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4_POSEIDON,309AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0);310OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4_POSEIDON,311AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400);312OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4_POSEIDON,313AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, 100);314} else {315OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,316AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30);317OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,318AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1);319OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,320AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1);321OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,322AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0);323OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,324AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0);325OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,326AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);327OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,328AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);329if (is_2g) {330if(AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)){331OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2,332AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 0x91);333}else{334OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2,335AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);336}337}338else if (AR_SREV_WASP(ah) && !is_2g) {339OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2,340AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 137);341} else {342OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2,343AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);344}345OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,346AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);347OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,348AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4);349OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,350AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);351OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,352AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);353if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {354OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,355AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -3);356} else {357OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,358AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6);359}360if (is_2g) {361if(AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)){362OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,363AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, -10);364}else{365OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,366AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, -15);367}368}369else {370OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,371AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, -10);372}373OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,374AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);375OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4,376AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0);377OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4,378AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400);379OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4,380AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, 100);381}382383OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0,384AR_PHY_PAPRD_PRE_POST_SCALE_0_B0_PAPRD_PRE_POST_SCALING_0_0, 261376);385OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0,386AR_PHY_PAPRD_PRE_POST_SCALE_1_B0_PAPRD_PRE_POST_SCALING_1_0, 248079);387OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0,388AR_PHY_PAPRD_PRE_POST_SCALE_2_B0_PAPRD_PRE_POST_SCALING_2_0, 233759);389OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0,390AR_PHY_PAPRD_PRE_POST_SCALE_3_B0_PAPRD_PRE_POST_SCALING_3_0, 220464);391OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0,392AR_PHY_PAPRD_PRE_POST_SCALE_4_B0_PAPRD_PRE_POST_SCALING_4_0, 208194);393OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0,394AR_PHY_PAPRD_PRE_POST_SCALE_5_B0_PAPRD_PRE_POST_SCALING_5_0, 196949);395OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0,396AR_PHY_PAPRD_PRE_POST_SCALE_6_B0_PAPRD_PRE_POST_SCALING_6_0, 185706);397OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,398AR_PHY_PAPRD_PRE_POST_SCALE_7_B0_PAPRD_PRE_POST_SCALING_7_0, 175487);399return 0;400401FAILED:402return -1;403#undef ABS404}405406/*407* XXX There's another copy of this in ar9300_reset.c, use that!408*/409#if 0410static inline HAL_CHANNEL_INTERNAL*411ar9300_check_chan(struct ath_hal *ah, HAL_CHANNEL *chan)412{413if ((AR9300_IS_CHAN(chan, CHANNEL_2GHZ) ^414AR9300_IS_CHAN(chan, CHANNEL_5GHZ)) == 0)415{416HALDEBUG(ah, HAL_DEBUG_CHANNEL,417"%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",418__func__, chan->channel, chan->channel_flags);419return AH_NULL;420}421422if ((AR9300_IS_CHAN(chan, CHANNEL_OFDM) ^423AR9300_IS_CHAN(chan, CHANNEL_CCK) ^424AR9300_IS_CHAN(chan, CHANNEL_HT20) ^425AR9300_IS_CHAN(chan, CHANNEL_HT40PLUS) ^426AR9300_IS_CHAN(chan, CHANNEL_HT40MINUS)) == 0)427{428HALDEBUG(ah, HAL_DEBUG_CHANNEL,429"%s: invalid channel %u/0x%x; not marked as "430"OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n", __func__,431chan->channel, chan->channel_flags);432return AH_NULL;433}434435return (ath_hal_checkchannel(ah, chan));436}437#endif438439void ar9300_enable_paprd(struct ath_hal *ah, HAL_BOOL enable_flag,440struct ieee80211_channel * chan)441{442HAL_BOOL enable = enable_flag;443u_int32_t am_mask = 0;444u_int32_t val = OS_REG_READ(ah, AR_2040_MODE);445int is_2g = IEEE80211_IS_CHAN_2GHZ(chan);446HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);447int is_ht40 = 0;448struct ath_hal_9300 *ahp = AH9300(ah);449450if (val & HAL_HT_MACMODE_2040) {451is_ht40 = 1;452}453if (enable_flag == AH_TRUE) {454ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;455456if (!is_2g) {457/*458* 3 bits for modal_header_5g.paprd_rate_mask_ht20459* is used for sub band disabling of paprd.460* 5G band is divided into 3 sub bands -- upper, mid, lower.461* If bit 30 of modal_header_5g.paprd_rate_mask_ht20 is set462* to one -- disable paprd for upper 5G463* If bit 29 of modal_header_5g.paprd_rate_mask_ht20 is set464* to one -- disable paprd for mid 5G465* If bit 28 of modal_header_5g.paprd_rate_mask_ht20 is set466* to one -- disable paprd for lower 5G467* u_int32_t am_mask = eep->modal_header_5g.paprd_rate_mask_ht20;468*/469if (ichan->channel >= UPPER_5G_SUB_BANDSTART) {470if (eep->modal_header_5g.paprd_rate_mask_ht20 & (1 << 30)) {471enable = AH_FALSE;472}473} else if (ichan->channel >= MID_5G_SUB_BANDSTART) {474if (eep->modal_header_5g.paprd_rate_mask_ht20 & (1 << 29)) {475enable = AH_FALSE;476}477} else { /* must be in the lower 5G subband */478if (eep->modal_header_5g.paprd_rate_mask_ht20 & (1 << 28)) {479enable = AH_FALSE;480}481}482}483484if (ahp->ah_paprd_broken) {485ahp->ah_paprd_broken = AH_FALSE;486enable = AH_FALSE;487488HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,489"%s: PAPRD is in bad state. Don't enable PAPRD\n",490__func__);491}492}493if (enable) {494HAL_CHANNEL_INTERNAL *ichan;495if (is_2g) {496if (is_ht40) {497am_mask = ahp->ah_2g_paprd_rate_mask_ht40 & AH_PAPRD_AM_PM_MASK;498} else {499am_mask = ahp->ah_2g_paprd_rate_mask_ht20 & AH_PAPRD_AM_PM_MASK;500}501} else {502if (is_ht40) {503am_mask = ahp->ah_5g_paprd_rate_mask_ht40 & AH_PAPRD_AM_PM_MASK;504} else {505am_mask = ahp->ah_5g_paprd_rate_mask_ht20 & AH_PAPRD_AM_PM_MASK;506}507}508/* Earlier we promgrammed TGT Power with Scaled down value, since509* PAPRD CAL was not done.510* Now we finish PAPRD CAL, so bump up the TGT PWR to original511* EEPROM Power. CTLs calc and Maverickd in512* "ar9300_eeprom_set_transmit_power"513*/514ichan = ar9300_check_chan(ah, chan);515ichan->paprd_table_write_done = 1;516// chan->paprd_table_write_done = 1;517/*518ath_hal_printf(ah, "%s[%d] eeprom_set_transmit_power PAPRD\n",519__func__, __LINE__);520*/521if (ar9300_eeprom_set_transmit_power(ah, &ahp->ah_eeprom, chan,522ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan),523ath_hal_get_twice_max_regpower(AH_PRIVATE(ah), ichan, chan),524AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit)) != HAL_OK) {525ichan->paprd_table_write_done = 0;526// chan->paprd_table_write_done = 0;527/* Intentional print */528ath_hal_printf(ah,529"%s[%d] eeprom_set_transmit_power failed ABORT PAPRD\n",530__func__, __LINE__);531532OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,533AR_PHY_PAPRD_CTRL0_B0_PAPRD_ENABLE_0, 0);534if (!AR_SREV_POSEIDON(ah) && !AR_SREV_HORNET(ah)) {535OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,536AR_PHY_PAPRD_CTRL0_B1_PAPRD_ENABLE_1, 0);537if (!AR_SREV_JUPITER(ah) || (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK)) {538OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,539AR_PHY_PAPRD_CTRL0_B2_PAPRD_ENABLE_2, 0);540541}542}543return;544}545546HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s 2G %d HT40 %d am_mask 0x%08x\n",547__func__, is_2g, is_ht40, am_mask);548OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,549am_mask);550if (AR_SREV_HORNET(ah)) {551OS_REG_RMW_FIELD_ALT(ah,552AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, 0);553} else {554OS_REG_RMW_FIELD_ALT(ah,555AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask);556}557558OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,559AR_PHY_PAPRD_HT40_MASK);560/* chain0 */561if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN0_MASK) {562OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,563AR_PHY_PAPRD_CTRL0_B0_USE_SINGLE_TABLE_MASK, 1);564OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,565AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_AM2PM_ENABLE_0, 1);566OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,567AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_AM2AM_ENABLE_0, 1);568OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,569AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_SCALING_ENA, 0);570OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,571AR_PHY_PAPRD_CTRL1_B0_PA_GAIN_SCALE_FACT_0_MASK, 181);572OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,573AR_PHY_PAPRD_CTRL1_B0_PAPRD_MAG_SCALE_FACT_0, 361);574OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,575AR_PHY_PAPRD_CTRL1_B0_ADAPTIVE_SCALING_ENA, 0);576OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,577AR_PHY_PAPRD_CTRL0_B0_PAPRD_MAG_THRSH_0, 3);578}579/* chain1 */580if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN1_MASK) {581OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,582AR_PHY_PAPRD_CTRL0_B1_PAPRD_ADAPTIVE_USE_SINGLE_TABLE_1, 1);583OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,584AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_AM2PM_ENABLE_1, 1);585OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,586AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_AM2AM_ENABLE_1, 1);587OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,588AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_SCALING_ENA, 0);589OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,590AR_PHY_PAPRD_CTRL1_B1_PA_GAIN_SCALE_FACT_1_MASK, 181);591OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,592AR_PHY_PAPRD_CTRL1_B1_PAPRD_MAG_SCALE_FACT_1, 361);593OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,594AR_PHY_PAPRD_CTRL1_B1_ADAPTIVE_SCALING_ENA, 0);595OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,596AR_PHY_PAPRD_CTRL0_B1_PAPRD_MAG_THRSH_1, 3);597}598/* chain2 */599if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK) {600OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,601AR_PHY_PAPRD_CTRL0_B2_PAPRD_ADAPTIVE_USE_SINGLE_TABLE_2, 1);602OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,603AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_AM2PM_ENABLE_2, 1);604OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,605AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_AM2AM_ENABLE_2, 1);606OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,607AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_SCALING_ENA, 0);608OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,609AR_PHY_PAPRD_CTRL1_B2_PA_GAIN_SCALE_FACT_2_MASK, 181);610OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,611AR_PHY_PAPRD_CTRL1_B2_PAPRD_MAG_SCALE_FACT_2, 361);612OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,613AR_PHY_PAPRD_CTRL1_B2_ADAPTIVE_SCALING_ENA, 0);614OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,615AR_PHY_PAPRD_CTRL0_B2_PAPRD_MAG_THRSH_2, 3);616}617618if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN0_MASK) {619OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,620AR_PHY_PAPRD_CTRL0_B0_PAPRD_ENABLE_0, 1);621}622623if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN1_MASK) {624OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,625AR_PHY_PAPRD_CTRL0_B1_PAPRD_ENABLE_1, 1);626}627628if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK) {629OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,630AR_PHY_PAPRD_CTRL0_B2_PAPRD_ENABLE_2, 1);631}632633} else {634if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN0_MASK) {635OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,636AR_PHY_PAPRD_CTRL0_B0_PAPRD_ENABLE_0, 0);637}638639if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN1_MASK) {640OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,641AR_PHY_PAPRD_CTRL0_B1_PAPRD_ENABLE_1, 0);642}643644if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK) {645OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,646AR_PHY_PAPRD_CTRL0_B2_PAPRD_ENABLE_2, 0);647}648}649}650651static void ar9300_gain_table_entries(struct ath_hal *ah)652{653int i;654u_int32_t reg;655u_int32_t *gain_table_entries = AH9300(ah)->paprd_gain_table_entries;656u_int32_t *gain_vs_table_index = AH9300(ah)->paprd_gain_table_index;657658reg = AR_PHY_TXGAIN_TAB(1);659660for (i = 0; i < 32; i++) {661gain_table_entries[i] = OS_REG_READ(ah, reg);662gain_vs_table_index[i] = (gain_table_entries[i] >> 24) & 0xff;663/*664* ath_hal_printf(665* ah, "+++reg 0x%08x gain_table_entries[%d] = 0x%08x \n",666* reg, i, gain_table_entries[i]);667*/668reg = reg + 4;669}670}671672/* Get gain index for Target power */673static unsigned int ar9300_get_desired_gain_for_chain(struct ath_hal *ah,674int chain_num, int target_power)675{676int olpc_gain_delta = 0;677int alpha_therm = 0, alpha_volt = 0;678int therm_cal_value = 0, volt_cal_value = 0;679int latest_therm_value = 0, latest_volt_value = 0, olpc_gain_delta_tmp = 0;680int thermal_gain_corr = 0, voltage_gain_corr = 0, desired_scale = 0;681int desired_gain = 0;682int cl_gain_mod = 0;683684/* Clear the training done bit */685if (AR_SREV_POSEIDON(ah)) {686OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,687AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);688} else {689OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,690AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);691}692/*field_read("BB_tpc_12.desired_scale_ht40_5", &desired_scale);*/693desired_scale =694OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_12,695AR_PHY_TPC_12_DESIRED_SCALE_HT40_5);696/*field_read("BB_tpc_19.alpha_therm", &alpha_therm);*/697alpha_therm =698OS_REG_READ_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM);699/*field_read("BB_tpc_19.alpha_volt", &alpha_volt);*/700alpha_volt =701OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALT_ALPHA_VOLT);702703/*field_read("BB_tpc_18.therm_cal_value", &therm_cal_value);*/704therm_cal_value =705OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_18,706AR_PHY_TPC_18_ALT_THERM_CAL_VALUE);707/*field_read("BB_tpc_18.volt_cal_value", &volt_cal_value);*/708volt_cal_value =709OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_18,710AR_PHY_TPC_18_ALT_VOLT_CAL_VALUE);711712/*field_read("BB_therm_adc_4.latest_therm_value", &latest_therm_value);*/713latest_therm_value =714OS_REG_READ_FIELD_ALT(ah, AR_PHY_THERM_ADC_4,715AR_PHY_THERM_ADC_4_LATEST_THERM_VALUE);716/*field_read("BB_therm_adc_4.latest_volt_value", &latest_volt_value);*/717latest_volt_value =718OS_REG_READ_FIELD_ALT(ah, AR_PHY_THERM_ADC_4,719AR_PHY_THERM_ADC_4_LATEST_VOLT_VALUE);720721/*722* sprintf(723* field_name, "%s%d%s%d\0", "BB_tpc_11_b",724* chain_num, ".olpc_gain_delta_", chain_num);725*/726/*field_read(field_name, &olpc_gain_delta_tmp);*/727728729if (chain_num == 0) {730olpc_gain_delta_tmp =731OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_11_B0,732AR_PHY_TPC_11_B0_OLPC_GAIN_DELTA_0);733cl_gain_mod = OS_REG_READ_FIELD_ALT(ah, AR_PHY_CL_TAB_0,734AR_PHY_CL_TAB_0_CL_GAIN_MOD);735} else if (chain_num == 1) {736if (!AR_SREV_POSEIDON(ah)) {737olpc_gain_delta_tmp =738OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_11_B1,739AR_PHY_TPC_11_B1_OLPC_GAIN_DELTA_1);740cl_gain_mod = OS_REG_READ_FIELD_ALT(ah, AR_PHY_CL_TAB_1,741AR_PHY_CL_TAB_1_CL_GAIN_MOD);742}743} else if (chain_num == 2) {744if (!AR_SREV_POSEIDON(ah)) {745olpc_gain_delta_tmp =746OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_11_B2,747AR_PHY_TPC_11_B2_OLPC_GAIN_DELTA_2);748cl_gain_mod = OS_REG_READ_FIELD_ALT(ah, AR_PHY_CL_TAB_2,749AR_PHY_CL_TAB_2_CL_GAIN_MOD);750}751} else {752/* invalid chain_num */753}754755if (olpc_gain_delta_tmp < 128) {756olpc_gain_delta = olpc_gain_delta_tmp;757} else {758olpc_gain_delta = olpc_gain_delta_tmp - 256;759}760761thermal_gain_corr =762(int) (alpha_therm * (latest_therm_value - therm_cal_value) +763128) >> 8;764voltage_gain_corr =765(int) (alpha_volt * (latest_volt_value - volt_cal_value) + 64) >> 7;766desired_gain =767target_power - olpc_gain_delta - thermal_gain_corr -768voltage_gain_corr + desired_scale + cl_gain_mod;769/*770* printf(771* "olpc_gain_delta %d, desired_gain %d\n",772* olpc_gain_delta, desired_gain);773*/774#if 0775ath_hal_printf(ah,776"+++ target_power %d olpc_gain_delta %d, cl_gain_mod %d,"777"thermal_gain_corr %d voltage_gain_corr %d desired_scale %d"778"desired_gain %d\n",779target_power, olpc_gain_delta, cl_gain_mod, thermal_gain_corr,780voltage_gain_corr,781desired_scale, desired_gain);782#endif783return (unsigned int) desired_gain;784}785786static void ar9300_tx_force_gain(struct ath_hal *ah, unsigned int gain_index)787{788int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain;789int padrvgn_a, padrvgn_b, padrvgn_c, padrvgn_d;790u_int32_t *gain_table_entries = AH9300(ah)->paprd_gain_table_entries;791792/*u_int32_t *gain_vs_table_index = ah->paprd_gain_table_index;*/793selected_gain_entry = gain_table_entries[gain_index];794txbb1dbgain = selected_gain_entry & 0x7;795txbb6dbgain = (selected_gain_entry >> 3) & 0x3;796txmxrgain = (selected_gain_entry >> 5) & 0xf;797padrvgn_a = (selected_gain_entry >> 9) & 0xf;798padrvgn_b = (selected_gain_entry >> 13) & 0xf;799padrvgn_c = (selected_gain_entry >> 17) & 0xf;800padrvgn_d = (selected_gain_entry >> 21) & 0x3;801802OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,803AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain);804OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,805AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain);806OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,807AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain);808OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,809AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgn_a);810OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,811AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgn_b);812OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,813AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgn_c);814OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,815AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgn_d);816OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,817AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0);818OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,819AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0);820821OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0);822OS_REG_RMW_FIELD_ALT(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0);823}824825#define HAL_DEBUG_PAPRD HAL_DEBUG_CALIBRATE /* driver: conditionally print */826827#if defined(ART_PAPRD_DEBUG) || defined(AH_DEBUG)828static void ar9300_paprd_debug_print(struct ath_hal *ah)829{830int temp;831int txbb1dbgain, txbb6dbgain, txmxrgain;832int padrvgn_a, padrvgn_b, padrvgn_c, padrvgn_d;833834if (AR_SREV_POSEIDON(ah)) {835/*field_read("BB_paprd_trainer_cntl1.cf_paprd_lb_skip", &temp);*/836temp =837OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,838AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP);839HALDEBUG(ah, HAL_DEBUG_PAPRD,840"BB_paprd_trainer_cntl1.cf_paprd_lb_skip=0x%x\n", temp);841/*field_read("BB_paprd_trainer_cntl1.cf_paprd_lb_enable", &temp);*/842temp =843OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,844AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE);845HALDEBUG(ah, HAL_DEBUG_PAPRD,846"BB_paprd_trainer_cntl1.cf_paprd_lb_enable=0x%x\n", temp);847/*field_read("BB_paprd_trainer_cntl1.cf_paprd_tx_gain_force", &temp);*/848temp =849OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,850AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE);851HALDEBUG(ah, HAL_DEBUG_PAPRD,852"BB_paprd_trainer_cntl1.cf_paprd_tx_gain_force=0x%x\n", temp);853/*854* field_read(855* "BB_paprd_trainer_cntl1.cf_paprd_rx_bb_gain_force", &temp);856*/857temp =858OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,859AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE);860HALDEBUG(ah, HAL_DEBUG_PAPRD,861"BB_paprd_trainer_cntl1.cf_paprd_rx_bb_gain_force=0x%x\n", temp);862/*field_read("BB_paprd_trainer_cntl1.cf_paprd_iqcorr_enable", &temp);*/863temp =864OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,865AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE);866HALDEBUG(ah, HAL_DEBUG_PAPRD,867"BB_paprd_trainer_cntl1.cf_paprd_iqcorr_enable=0x%x\n", temp);868/*field_read("BB_paprd_trainer_cntl1.cf_paprd_agc2_settling", &temp);*/869temp =870OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,871AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING);872HALDEBUG(ah, HAL_DEBUG_PAPRD,873"BB_paprd_trainer_cntl1.cf_paprd_agc2_settling=0x%x\n", temp);874/*field_read("BB_paprd_trainer_cntl1.cf_paprd_train_enable", &temp);*/875temp =876OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1_POSEIDON,877AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE);878HALDEBUG(ah, HAL_DEBUG_PAPRD,879"BB_paprd_trainer_cntl1.cf_paprd_train_enable=0x%x\n", temp);880/*881* field_read("BB_paprd_trainer_cntl2.cf_paprd_init_rx_bb_gain", &temp);882*/883temp =884OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2_POSEIDON,885AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN);886HALDEBUG(ah, HAL_DEBUG_PAPRD,887"BB_paprd_trainer_cntl2.cf_paprd_init_rx_bb_gain=0x%x\n", temp);888/*field_read("BB_paprd_trainer_cntl3.cf_paprd_fine_corr_len", &temp);*/889temp =890OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,891AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN);892HALDEBUG(ah, HAL_DEBUG_PAPRD,893"BB_paprd_trainer_cntl3.cf_paprd_fine_corr_len=0x%x\n", temp);894/*895* field_read("BB_paprd_trainer_cntl3.cf_paprd_coarse_corr_len", &temp);896*/897temp =898OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,899AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN);900HALDEBUG(ah, HAL_DEBUG_PAPRD,901"BB_paprd_trainer_cntl3.cf_paprd_coarse_corr_len=0x%x\n", temp);902/*903* field_read("BB_paprd_trainer_cntl3.cf_paprd_num_corr_stages", &temp);904*/905temp =906OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,907AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES);908HALDEBUG(ah, HAL_DEBUG_PAPRD,909"BB_paprd_trainer_cntl3.cf_paprd_num_corr_stages=0x%x\n", temp);910/*911* field_read(912* "BB_paprd_trainer_cntl3.cf_paprd_min_loopback_del", &temp);913*/914temp =915OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,916AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL);917HALDEBUG(ah, HAL_DEBUG_PAPRD,918"BB_paprd_trainer_cntl3.cf_paprd_min_loopback_del=0x%x\n", temp);919/*field_read("BB_paprd_trainer_cntl3.cf_paprd_quick_drop", &temp);*/920temp =921OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,922AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);923HALDEBUG(ah, HAL_DEBUG_PAPRD,924"BB_paprd_trainer_cntl3.cf_paprd_quick_drop=0x%x\n", temp);925/*926* field_read(927* "BB_paprd_trainer_cntl3.cf_paprd_adc_desired_size", &temp);928*/929temp =930OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,931AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE);932HALDEBUG(ah, HAL_DEBUG_PAPRD,933"BB_paprd_trainer_cntl3.cf_paprd_adc_desired_size=0x%x\n", temp);934/*935* field_read("BB_paprd_trainer_cntl3.cf_paprd_bbtxmix_disable", &temp);936*/937temp =938OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,939AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE);940HALDEBUG(ah, HAL_DEBUG_PAPRD,941"BB_paprd_trainer_cntl3.cf_paprd_bbtxmix_disable=0x%x\n", temp);942/*field_read("BB_paprd_trainer_cntl4.cf_paprd_safety_delta", &temp);*/943temp =944OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4_POSEIDON,945AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA);946HALDEBUG(ah, HAL_DEBUG_PAPRD,947"BB_paprd_trainer_cntl4.cf_paprd_safety_delta=0x%x\n", temp);948/*field_read("BB_paprd_trainer_cntl4.cf_paprd_min_corr", &temp);*/949temp =950OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4_POSEIDON,951AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR);952HALDEBUG(ah, HAL_DEBUG_PAPRD,953"BB_paprd_trainer_cntl4.cf_paprd_min_corr=0x%x\n", temp);954/*field_read("BB_paprd_trainer_stat1.paprd_agc2_pwr", &temp);*/955temp =956OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,957AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);958HALDEBUG(ah, HAL_DEBUG_PAPRD,959" paprd_agc2_pwr = 0x%02x\n", temp);960/*field_read("BB_paprd_trainer_stat1.paprd_rx_gain_idx", &temp);*/961temp =962OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,963AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX);964HALDEBUG(ah, HAL_DEBUG_PAPRD,965" paprd_rx_gain_idx = 0x%02x\n", temp);966/*field_read("BB_paprd_trainer_stat1.paprd_train_active", &temp);*/967temp =968OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,969AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE);970HALDEBUG(ah, HAL_DEBUG_PAPRD,971" paprd_train_active = 0x%08x\n", temp);972/*field_read("BB_paprd_trainer_stat1.paprd_corr_err", &temp);*/973temp =974OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,975AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR);976HALDEBUG(ah, HAL_DEBUG_PAPRD,977" paprd_corr_err = 0x%08x\n", temp);978/*field_read("BB_paprd_trainer_stat1.paprd_train_incomplete", &temp);*/979temp =980OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,981AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE);982HALDEBUG(ah, HAL_DEBUG_PAPRD,983" paprd_train_incomplete = 0x%08x\n", temp);984/*field_read("BB_paprd_trainer_stat1.paprd_train_done", &temp);*/985temp =986OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,987AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);988HALDEBUG(ah, HAL_DEBUG_PAPRD,989" paprd_train_done = 0x%08x\n", temp);990/*field_read("BB_paprd_trainer_stat2.paprd_fine_idx", &temp);*/991temp =992OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2_POSEIDON,993AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX);994HALDEBUG(ah, HAL_DEBUG_PAPRD,995" paprd_fine_idx = 0x%08x\n", temp);996/*field_read("BB_paprd_trainer_stat2.paprd_coarse_idx", &temp);*/997temp =998OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2_POSEIDON,999AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX);1000HALDEBUG(ah, HAL_DEBUG_PAPRD,1001" paprd_coarse_idx = 0x%08x\n", temp);1002/*field_read("BB_paprd_trainer_stat2.paprd_fine_val", &temp);*/1003temp =1004OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2_POSEIDON,1005AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL);1006HALDEBUG(ah, HAL_DEBUG_PAPRD,1007" paprd_fine_val = 0x%08x\n", temp);1008/*field_read("BB_paprd_trainer_stat3.paprd_train_samples_cnt", &temp);*/1009temp =1010OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT3_POSEIDON,1011AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT);1012HALDEBUG(ah, HAL_DEBUG_PAPRD,1013" paprd_train_samples_cnt = 0x%08x\n", temp);1014} else {1015/*field_read("BB_paprd_trainer_cntl1.cf_paprd_lb_skip", &temp);*/1016temp =1017OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1018AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP);1019HALDEBUG(ah, HAL_DEBUG_PAPRD,1020"BB_paprd_trainer_cntl1.cf_paprd_lb_skip=0x%x\n", temp);1021/*field_read("BB_paprd_trainer_cntl1.cf_paprd_lb_enable", &temp);*/1022temp =1023OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1024AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE);1025HALDEBUG(ah, HAL_DEBUG_PAPRD,1026"BB_paprd_trainer_cntl1.cf_paprd_lb_enable=0x%x\n", temp);1027/*field_read("BB_paprd_trainer_cntl1.cf_paprd_tx_gain_force", &temp);*/1028temp =1029OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1030AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE);1031HALDEBUG(ah, HAL_DEBUG_PAPRD,1032"BB_paprd_trainer_cntl1.cf_paprd_tx_gain_force=0x%x\n", temp);1033/*1034* field_read(1035* "BB_paprd_trainer_cntl1.cf_paprd_rx_bb_gain_force", &temp);1036*/1037temp =1038OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1039AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE);1040HALDEBUG(ah, HAL_DEBUG_PAPRD,1041"BB_paprd_trainer_cntl1.cf_paprd_rx_bb_gain_force=0x%x\n", temp);1042/*field_read("BB_paprd_trainer_cntl1.cf_paprd_iqcorr_enable", &temp);*/1043temp =1044OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1045AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE);1046HALDEBUG(ah, HAL_DEBUG_PAPRD,1047"BB_paprd_trainer_cntl1.cf_paprd_iqcorr_enable=0x%x\n", temp);1048/*field_read("BB_paprd_trainer_cntl1.cf_paprd_agc2_settling", &temp);*/1049temp =1050OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1051AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING);1052HALDEBUG(ah, HAL_DEBUG_PAPRD,1053"BB_paprd_trainer_cntl1.cf_paprd_agc2_settling=0x%x\n", temp);1054/*field_read("BB_paprd_trainer_cntl1.cf_paprd_train_enable", &temp);*/1055temp =1056OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL1,1057AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE);1058HALDEBUG(ah, HAL_DEBUG_PAPRD,1059"BB_paprd_trainer_cntl1.cf_paprd_train_enable=0x%x\n", temp);1060/*1061* field_read("BB_paprd_trainer_cntl2.cf_paprd_init_rx_bb_gain", &temp);1062*/1063temp =1064OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL2,1065AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN);1066HALDEBUG(ah, HAL_DEBUG_PAPRD,1067"BB_paprd_trainer_cntl2.cf_paprd_init_rx_bb_gain=0x%x\n", temp);1068/*field_read("BB_paprd_trainer_cntl3.cf_paprd_fine_corr_len", &temp);*/1069temp =1070OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1071AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN);1072HALDEBUG(ah, HAL_DEBUG_PAPRD,1073"BB_paprd_trainer_cntl3.cf_paprd_fine_corr_len=0x%x\n", temp);1074/*1075* field_read("BB_paprd_trainer_cntl3.cf_paprd_coarse_corr_len", &temp);1076*/1077temp =1078OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1079AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN);1080HALDEBUG(ah, HAL_DEBUG_PAPRD,1081"BB_paprd_trainer_cntl3.cf_paprd_coarse_corr_len=0x%x\n", temp);1082/*1083* field_read("BB_paprd_trainer_cntl3.cf_paprd_num_corr_stages", &temp);1084*/1085temp =1086OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1087AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES);1088HALDEBUG(ah, HAL_DEBUG_PAPRD,1089"BB_paprd_trainer_cntl3.cf_paprd_num_corr_stages=0x%x\n", temp);1090/*1091* field_read(1092* "BB_paprd_trainer_cntl3.cf_paprd_min_loopback_del", &temp);1093*/1094temp =1095OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1096AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL);1097HALDEBUG(ah, HAL_DEBUG_PAPRD,1098"BB_paprd_trainer_cntl3.cf_paprd_min_loopback_del=0x%x\n", temp);1099/*field_read("BB_paprd_trainer_cntl3.cf_paprd_quick_drop", &temp);*/1100temp =1101OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1102AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);1103HALDEBUG(ah, HAL_DEBUG_PAPRD,1104"BB_paprd_trainer_cntl3.cf_paprd_quick_drop=0x%x\n", temp);1105/*1106* field_read(1107* "BB_paprd_trainer_cntl3.cf_paprd_adc_desired_size", &temp);1108*/1109temp =1110OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1111AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE);1112HALDEBUG(ah, HAL_DEBUG_PAPRD,1113"BB_paprd_trainer_cntl3.cf_paprd_adc_desired_size=0x%x\n", temp);1114/*1115* field_read(1116* "BB_paprd_trainer_cntl3.cf_paprd_bbtxmix_disable", &temp);1117*/1118temp =1119OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,1120AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE);1121HALDEBUG(ah, HAL_DEBUG_PAPRD,1122"BB_paprd_trainer_cntl3.cf_paprd_bbtxmix_disable=0x%x\n", temp);1123/*field_read("BB_paprd_trainer_cntl4.cf_paprd_safety_delta", &temp);*/1124temp =1125OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4,1126AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA);1127HALDEBUG(ah, HAL_DEBUG_PAPRD,1128"BB_paprd_trainer_cntl4.cf_paprd_safety_delta=0x%x\n", temp);1129/*field_read("BB_paprd_trainer_cntl4.cf_paprd_min_corr", &temp);*/1130temp =1131OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL4,1132AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR);1133HALDEBUG(ah, HAL_DEBUG_PAPRD,1134"BB_paprd_trainer_cntl4.cf_paprd_min_corr=0x%x\n", temp);1135/*field_read("BB_paprd_trainer_stat1.paprd_agc2_pwr", &temp);*/1136temp =1137OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1138AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);1139HALDEBUG(ah, HAL_DEBUG_PAPRD,1140" paprd_agc2_pwr = 0x%02x\n", temp);1141/*field_read("BB_paprd_trainer_stat1.paprd_rx_gain_idx", &temp);*/1142temp =1143OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1144AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX);1145HALDEBUG(ah, HAL_DEBUG_PAPRD,1146" paprd_rx_gain_idx = 0x%02x\n", temp);1147/*field_read("BB_paprd_trainer_stat1.paprd_train_active", &temp);*/1148temp =1149OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1150AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE);1151HALDEBUG(ah, HAL_DEBUG_PAPRD,1152" paprd_train_active = 0x%08x\n", temp);1153/*field_read("BB_paprd_trainer_stat1.paprd_corr_err", &temp);*/1154temp =1155OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1156AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR);1157HALDEBUG(ah, HAL_DEBUG_PAPRD,1158" paprd_corr_err = 0x%08x\n", temp);1159/*field_read("BB_paprd_trainer_stat1.paprd_train_incomplete", &temp);*/1160temp =1161OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1162AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE);1163HALDEBUG(ah, HAL_DEBUG_PAPRD,1164" paprd_train_incomplete = 0x%08x\n", temp);1165/*field_read("BB_paprd_trainer_stat1.paprd_train_done", &temp);*/1166temp =1167OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1168AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);1169HALDEBUG(ah, HAL_DEBUG_PAPRD,1170" paprd_train_done = 0x%08x\n", temp);1171/*field_read("BB_paprd_trainer_stat2.paprd_fine_idx", &temp);*/1172temp =1173OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2,1174AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX);1175HALDEBUG(ah, HAL_DEBUG_PAPRD,1176" paprd_fine_idx = 0x%08x\n", temp);1177/*field_read("BB_paprd_trainer_stat2.paprd_coarse_idx", &temp);*/1178temp =1179OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2,1180AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX);1181HALDEBUG(ah, HAL_DEBUG_PAPRD,1182" paprd_coarse_idx = 0x%08x\n", temp);1183/*field_read("BB_paprd_trainer_stat2.paprd_fine_val", &temp);*/1184temp =1185OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT2,1186AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL);1187HALDEBUG(ah, HAL_DEBUG_PAPRD,1188" paprd_fine_val = 0x%08x\n", temp);1189/*field_read("BB_paprd_trainer_stat3.paprd_train_samples_cnt", &temp);*/1190temp =1191OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT3,1192AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT);1193HALDEBUG(ah, HAL_DEBUG_PAPRD,1194" paprd_train_samples_cnt = 0x%08x\n", temp);1195}11961197/*field_read("BB_tpc_1.force_dac_gain", &temp);*/1198temp =1199OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN);1200HALDEBUG(ah, HAL_DEBUG_PAPRD, " dac_gain_forced = 0x%08x\n",1201temp);1202/*field_read("BB_tpc_1.forced_dac_gain", &temp);*/1203temp =1204OS_REG_READ_FIELD_ALT(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN);1205HALDEBUG(ah, HAL_DEBUG_PAPRD, " forced_dac_gain = 0x%08x\n",1206temp);12071208/*field_read("BB_paprd_ctrl0_b0.paprd_enable_0", &temp);*/1209temp =1210OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B0,1211AR_PHY_PAPRD_CTRL0_B0_PAPRD_ENABLE_0);1212HALDEBUG(ah, HAL_DEBUG_PAPRD,1213" BB_paprd_ctrl0_b0.paprd_enable_0 = 0x%08x\n", temp);1214if (!AR_SREV_POSEIDON(ah)) {1215/*field_read("BB_paprd_ctrl0_b1.paprd_enable_1", &temp);*/1216temp =1217OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B1,1218AR_PHY_PAPRD_CTRL0_B1_PAPRD_ENABLE_1);1219HALDEBUG(ah, HAL_DEBUG_PAPRD,1220" BB_paprd_ctrl0_b1.paprd_enable_1 = 0x%08x\n", temp);1221if (AH9300(ah)->ah_tx_chainmask & AR9300_CHAIN2_MASK) {1222/*field_read("BB_paprd_ctrl0_b2.paprd_enable_2", &temp);*/1223temp =1224OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL0_B2,1225AR_PHY_PAPRD_CTRL0_B2_PAPRD_ENABLE_2);1226HALDEBUG(ah, HAL_DEBUG_PAPRD,1227" BB_paprd_ctrl0_b2.paprd_enable_2 = 0x%08x\n", temp);1228}1229}12301231/*field_read("BB_tx_forced_gain.forced_txbb1dbgain", &txbb1dbgain);*/1232txbb1dbgain =1233OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1234AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN);1235/*field_read("BB_tx_forced_gain.forced_txbb6dbgain", &txbb6dbgain);*/1236txbb6dbgain =1237OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1238AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN);1239/*field_read("BB_tx_forced_gain.forced_txmxrgain", &txmxrgain);*/1240txmxrgain =1241OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1242AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN);1243/*field_read("BB_tx_forced_gain.forced_padrvgn_a", &padrvgn_a);*/1244padrvgn_a =1245OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1246AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA);1247/*field_read("BB_tx_forced_gain.forced_padrvgn_b", &padrvgn_b);*/1248padrvgn_b =1249OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1250AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB);1251/*field_read("BB_tx_forced_gain.forced_padrvgn_c", &padrvgn_c);*/1252padrvgn_c =1253OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1254AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC);1255/*field_read("BB_tx_forced_gain.forced_padrvgn_d", &padrvgn_d);*/1256padrvgn_d =1257OS_REG_READ_FIELD_ALT(ah, AR_PHY_TX_FORCED_GAIN,1258AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND);12591260HALDEBUG(ah, HAL_DEBUG_PAPRD,1261"txbb1dbgain=0x%x, txbb6dbgain=0x%x, txmxrgain=0x%x\n",1262txbb1dbgain, txbb6dbgain, txmxrgain);1263HALDEBUG(ah, HAL_DEBUG_PAPRD,1264"padrvgn_a=0x%x, padrvgn_b=0x%x\n", padrvgn_a, padrvgn_b);1265HALDEBUG(ah, HAL_DEBUG_PAPRD,1266"padrvgn_c=0x%x, padrvgn_d=0x%x\n", padrvgn_c, padrvgn_d);1267}1268#else1269#define ar9300_paprd_debug_print(ah) /* dummy macro */1270#endif /* defined(ART_PAPRD_DEBUG) || defined(AH_DEBUG) */12711272static int ar9300_create_pa_curve(struct ath_hal *ah, u_int32_t * pa_table,1273u_int32_t * small_signal_gain, int * pa_in)1274{1275int i;1276int status;1277/*char field_name[100];*/1278u_int32_t paprd_train_data_l[48], paprd_train_data_u[48];1279u_int32_t reg;12801281ar9300_paprd_debug_print(ah);1282OS_REG_RMW_FIELD_ALT(ah, AR_PHY_CHAN_INFO_MEMORY,1283AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ, 0);1284reg = AR_PHY_CHAN_INFO_TAB_0;12851286for (i = 0; i < 48; i++) {1287/*1288* sprintf(1289* field_name, "%s%d%s\0", "BB_chan_info_chan_tab_b0[",1290* i, "].chaninfo_word");1291*/1292/*field_read(field_name, &paprd_train_data_l[i]);*/1293paprd_train_data_l[i] = OS_REG_READ(ah, reg);1294reg = reg + 4;1295}12961297OS_REG_RMW_FIELD_ALT(ah, AR_PHY_CHAN_INFO_MEMORY,1298AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ, 1);1299reg = AR_PHY_CHAN_INFO_TAB_0;13001301for (i = 0; i < 48; i++) {1302/*1303* sprintf(1304* field_name, "%s%d%s\0", "BB_chan_info_chan_tab_b0[",1305* i, "].chaninfo_word");1306*/1307/*field_read(field_name, &paprd_train_data_u[i]);*/1308paprd_train_data_u[i] = OS_REG_READ(ah, reg);1309reg = reg + 4;1310}13111312/*1313* for(i=0; i<48; i++)1314* ath_hal_printf(1315* ah, "%08x%08x\n", paprd_train_data_u[i], paprd_train_data_l[i]);1316*/1317status = 0;1318if (create_pa_curve(1319paprd_train_data_l, paprd_train_data_u,1320pa_table, small_signal_gain, pa_in) ==1321AH_FALSE)1322{1323status = -2;1324}1325/* Clear the training done bit */1326if (AR_SREV_POSEIDON(ah)) {1327OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,1328AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);1329} else {1330OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,1331AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);1332}1333return status;1334}13351336static int find_expn(int num)1337{1338int tmp, exp;13391340exp = 0;1341tmp = num >> 1;13421343while (tmp != 0) {1344tmp = tmp >> 1;1345exp++;1346}13471348return exp;1349}13501351static int find_proper_scale(int expn, int n)1352{1353int q_pw;13541355q_pw = (expn > n) ? expn - 10 : 0;1356return q_pw;1357}13581359static int find_max(int *array, int length)1360{1361int i, loc_max;13621363loc_max = 0;13641365for (i = 0; i < length; i++) {1366if (array[i] > loc_max) {1367loc_max = array[i];1368}1369}13701371return loc_max;1372}13731374static int paprd_abs(int num)1375{1376if (num < 0) {1377return -num;1378}1379return num;1380}13811382#define NUM_BIN 2313831384HAL_BOOL create_pa_curve(u_int32_t * paprd_train_data_l,1385u_int32_t * paprd_train_data_u, u_int32_t * pa_table,1386u_int32_t * g_fxp_ext, int *pa_in)1387{1388unsigned int accum_cnt[NUM_BIN + 1];1389unsigned int accum_tx[NUM_BIN + 1];1390unsigned int accum_rx[NUM_BIN + 1];1391unsigned int accum_ang[NUM_BIN + 1];1392unsigned int thresh_accum_cnt;13931394int max_index;1395int scale_factor;13961397int x_est[NUM_BIN + 1];1398int y[NUM_BIN + 1];1399int theta[NUM_BIN + 1];1400int y_sqr[NUM_BIN + 1];1401int y_quad[NUM_BIN + 1];1402int theta_tilde[NUM_BIN + 1];1403int pa_angle[NUM_BIN + 1];14041405int b1_tmp[NUM_BIN + 1];1406int b2_tmp[NUM_BIN + 1];1407int b1_abs[NUM_BIN + 1];1408int b2_abs[NUM_BIN + 1];14091410int y_lin[NUM_BIN + 1];1411int y_est[NUM_BIN + 1];1412int x_est_fxp1_nonlin[NUM_BIN + 1];1413int x_tilde[NUM_BIN + 1];1414int x_tilde_abs[NUM_BIN + 1];14151416int g_fxp;1417int y_intercept;1418int order_x_by_y;1419int m, half_lo, half_hi;1420int sum_y_sqr;1421int sum_y_quad;1422int q_x, q_b1, q_b2;1423int beta_raw, alpha_raw, scale_b;1424int q_scale_b, q_beta, q_alpha;1425int alpha, beta;1426int order_1, order_2;1427int order1_5x, order2_3x;1428int order1_5x_rem, order2_3x_rem;1429int y5, y3, tmp;1430int bin, idx;1431int theta_low_bin = 0;14321433/*1434* [15:00] u16, accum_cnt[15:00]: number of samples in the bin1435* [42:16] u27, accum_tx[26:00]: sum(tx amplitude) of the bin1436* [63:43] u21, accum_rx[20:00]:1437* sum(rx amplitude distance to lower bin edge) of the bin1438* [90:64] s27, accum_ang[26:00]: sum(angles) of the bin1439*/1440max_index = 0;1441/*1442* Disregard any bin that contains less than1443* or equal to 16 counts of samples1444*/1445thresh_accum_cnt = 16;1446scale_factor = 5;14471448for (bin = 0; bin < NUM_BIN; bin++) {1449accum_cnt[bin] = paprd_train_data_l[bin] & 0xffff;1450/* lower 16 bit OR-ed upper 11 bits */1451accum_tx[bin] =1452((paprd_train_data_l[bin] >> 16) & 0xffff) |1453((paprd_train_data_u[bin] & 0x7ff) << 16);1454accum_rx[bin] =1455((paprd_train_data_u[bin] >> 11) & 0x1f) |1456((paprd_train_data_l[bin + 23] & 0xffff) << 5);1457accum_ang[bin] =1458((paprd_train_data_l[bin + 23] >> 16) & 0xffff) |1459((paprd_train_data_u[bin + 23] & 0x7ff) << 16);1460/*1461* printf(1462* "%d\t%d\t%d\t%d\n", accum_cnt[bin], accum_tx[bin],1463* accum_rx[bin], accum_ang[bin]);1464*/1465if (accum_cnt[bin] > thresh_accum_cnt) {1466/* accum_cnt[i] will be non-zero at this point */1467x_est[bin + 1] =1468((((accum_tx[bin] << scale_factor) +1469accum_cnt[bin]) / accum_cnt[bin]) + 32) >> scale_factor;1470y[bin + 1] =1471(((((accum_rx[bin] << scale_factor) +1472accum_cnt[bin]) / accum_cnt[bin]) + 32) >> scale_factor) +1473(1 << scale_factor) * max_index + 16;1474if (accum_ang[bin] >= (1 << 26)) {1475theta[bin + 1] =1476((accum_ang[bin] - (1 << 27)) * (1 << scale_factor) +1477accum_cnt[bin]);1478theta[bin + 1] = theta[bin + 1] / (int) accum_cnt[bin];1479/*1480* theta[i+1] =1481* ((accum_ang[i] - (1 << 27)) *1482* (1 << scale_factor) + zz) / zz;1483*/1484} else {1485theta[bin + 1] =1486((accum_ang[bin] * (1 << scale_factor)) +1487accum_cnt[bin]) / accum_cnt[bin];1488}1489max_index++;1490}1491/*1492* printf(1493* "i=%d, theta[i+1]=%d\t%d\t%d\t%d\t%d\n",1494* i, theta[i+1], accum_cnt[i],1495* accum_tx[i], accum_rx[i], accum_ang[i]);1496*/1497}14981499/*1500* Find average theta of first 5 bin and all of those to same value.1501* Curve is linear at that range.1502*/1503for (bin = 1; bin < 6; bin++) {1504theta_low_bin += theta[bin];1505}1506theta_low_bin = theta_low_bin / 5;1507for (bin = 1; bin < 6; bin++) {1508theta[bin] = theta_low_bin;1509}15101511/* Set values at origin */1512theta[0] = theta_low_bin;15131514for (bin = 0; bin <= max_index; bin++) {1515theta[bin] = theta[bin] - theta_low_bin;1516/*printf("bin=%d, theta[bin] = %d\n", bin, theta[bin]);*/1517}15181519x_est[0] = 0;1520y[0] = 0;1521scale_factor = 8;1522/* low signal gain */1523if (x_est[6] == x_est[3]) {1524return AH_FALSE;1525}1526g_fxp =1527(((y[6] - y[3]) * 1 << scale_factor) + (x_est[6] - x_est[3])) /1528(x_est[6] - x_est[3]);1529if (g_fxp == 0) {1530/*1531* ath_hal_printf(1532* NULL, "%s[%d] Potential divide by zero error\n",1533* __func__, __LINE__);1534*/1535return AH_FALSE;1536}15371538for (bin = 0; bin <= max_index; bin++) {1539y_lin[bin] =1540(g_fxp * (x_est[bin] - x_est[3]) + (1 << scale_factor)) /1541(1 << scale_factor) + y[3];1542}1543y_intercept = y_lin[0];15441545for (bin = 0; bin <= max_index; bin++) {1546y_est[bin] = y[bin] - y_intercept;1547y_lin[bin] = y_lin[bin] - y_intercept;1548}15491550for (bin = 0; bin <= 3; bin++) {1551y_est[bin] = bin * 32;1552/* g_fxp was checked for zero already */1553x_est[bin] = ((y_est[bin] * 1 << scale_factor) + g_fxp) / g_fxp;1554}15551556/*1557* for (bin = 0; bin <= max_index; bin++) {1558* printf("y_est[%d] = %d, x_est[%d]=%d\n",1559* bin, y_est[bin], bin, x_est[bin]);1560* }1561*/1562for (bin = 0; bin <= max_index; bin++) {1563x_est_fxp1_nonlin[bin] =1564x_est[bin] - ((1 << scale_factor) * y_est[bin] + g_fxp) / g_fxp;1565/*printf("x_est_fxp1_nonlin[%d] = %d\n", bin, x_est_fxp1_nonlin[bin]);*/1566}15671568/* Check for divide by 0 */1569if (y_est[max_index] == 0) {1570return AH_FALSE;1571}1572order_x_by_y =1573(x_est_fxp1_nonlin[max_index] + y_est[max_index]) / y_est[max_index];1574if (order_x_by_y == 0) {1575m = 10;1576} else if (order_x_by_y == 1) {1577m = 9;1578} else {1579m = 8;1580}15811582half_lo = (max_index > 15) ? 7 : max_index >> 1;1583half_hi = max_index - half_lo;1584scale_factor = 8;1585sum_y_sqr = 0;1586sum_y_quad = 0;15871588for (bin = 0; bin <= half_hi; bin++) {1589if (y_est[bin + half_lo] == 0) {1590/*1591* ath_hal_printf(1592* NULL, "%s Potential divide by zero error\n", __func__);1593*/1594return AH_FALSE;1595}15961597x_tilde[bin] =1598(x_est_fxp1_nonlin[bin + half_lo] * (1 << m) +1599y_est[bin + half_lo]) / y_est[bin + half_lo];1600x_tilde[bin] = (x_tilde[bin] * (1 << m) + y_est[bin + half_lo]) /1601y_est[bin + half_lo];1602x_tilde[bin] = (x_tilde[bin] * (1 << m) + y_est[bin + half_lo]) /1603y_est[bin + half_lo];16041605y_sqr[bin] =1606(y_est[bin + half_lo] * y_est[bin + half_lo] +1607(scale_factor * scale_factor)) / (scale_factor * scale_factor);1608x_tilde_abs[bin] = paprd_abs(x_tilde[bin]);1609y_quad[bin] = y_sqr[bin] * y_sqr[bin];1610sum_y_sqr = sum_y_sqr + y_sqr[bin];1611sum_y_quad = sum_y_quad + y_quad[bin];1612}16131614/*printf("sum_y_sqr = %d, sum_y_quad=%d\n", sum_y_sqr, sum_y_quad);*/16151616for (bin = 0; bin <= half_hi; bin++) {1617b1_tmp[bin] = y_sqr[bin] * (half_hi + 1) - sum_y_sqr;1618b2_tmp[bin] = sum_y_quad - sum_y_sqr * y_sqr[bin];1619b1_abs[bin] = paprd_abs(b1_tmp[bin]);1620b2_abs[bin] = paprd_abs(b2_tmp[bin]);16211622/*1623* printf(1624* "bin=%d, b1_tmp[bin] = %d, b2_tmp[bin] = %d\n",1625* bin, b1_tmp[bin], b2_tmp[bin]);1626*/1627}16281629q_x = find_proper_scale(find_expn(find_max(x_tilde_abs, half_hi + 1)), 10);1630q_b1 = find_proper_scale(find_expn(find_max(b1_abs, half_hi + 1)), 10);1631q_b2 = find_proper_scale(find_expn(find_max(b2_abs, half_hi + 1)), 10);16321633beta_raw = 0;1634alpha_raw = 0;16351636for (bin = 0; bin <= half_hi; bin++) {1637x_tilde[bin] = x_tilde[bin] / (1 << q_x);1638b1_tmp[bin] = b1_tmp[bin] / (1 << q_b1);1639b2_tmp[bin] = b2_tmp[bin] / (1 << q_b2);16401641/*1642* printf(1643* "bin=%d, b1_tmp[bin]=%d b2_tmp[bin]=%d x_tilde[bin] = %d\n",1644* bin, b1_tmp[bin], b2_tmp[bin], x_tilde[bin]);1645*/1646beta_raw = beta_raw + b1_tmp[bin] * x_tilde[bin];1647alpha_raw = alpha_raw + b2_tmp[bin] * x_tilde[bin];1648}16491650scale_b =1651((sum_y_quad / scale_factor) * (half_hi + 1) -1652(sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor;1653q_scale_b = find_proper_scale(find_expn(paprd_abs(scale_b)), 10);1654scale_b = scale_b / (1 << q_scale_b);1655/* Check for divide by 0 */1656if (scale_b == 0) {1657return AH_FALSE;1658}1659q_beta = find_proper_scale(find_expn(paprd_abs(beta_raw)), 10);1660q_alpha = find_proper_scale(find_expn(paprd_abs(alpha_raw)), 10);16611662beta_raw = beta_raw / (1 << q_beta);1663alpha_raw = alpha_raw / (1 << q_alpha);1664alpha = (alpha_raw << 10) / scale_b;1665beta = (beta_raw << 10) / scale_b;1666order_1 = 3 * m - q_x - q_b1 - q_beta + 10 + q_scale_b;1667order_2 = 3 * m - q_x - q_b2 - q_alpha + 10 + q_scale_b;16681669order1_5x = order_1 / 5;1670order2_3x = order_2 / 3;16711672order1_5x_rem = order_1 - 5 * order1_5x;1673order2_3x_rem = order_2 - 3 * order2_3x;16741675for (idx = 0; idx < AR9300_PAPRD_TABLE_SZ; idx++) {1676tmp = idx * 32;1677y5 = ((beta * tmp) >> 6) >> order1_5x;1678y5 = (y5 * tmp) >> order1_5x;1679y5 = (y5 * tmp) >> order1_5x;1680y5 = (y5 * tmp) >> order1_5x;1681y5 = (y5 * tmp) >> order1_5x;16821683y5 = y5 >> order1_5x_rem;1684y3 = (alpha * tmp) >> order2_3x;1685y3 = (y3 * tmp) >> order2_3x;1686y3 = (y3 * tmp) >> order2_3x;16871688y3 = y3 >> order2_3x_rem;1689/* g_fxp was checked for zero already */1690pa_in[idx] = y5 + y3 + (256 * tmp) / g_fxp;1691}16921693for (idx = 1; idx < 23; idx++) {1694tmp = pa_in[idx + 1] - pa_in[idx];1695if (tmp < 0) {1696pa_in[idx + 1] = pa_in[idx] + (pa_in[idx] - pa_in[idx - 1]);1697}1698}16991700for (idx = 0; idx < AR9300_PAPRD_TABLE_SZ; idx++) {1701pa_in[idx] = (pa_in[idx] < 1400) ? pa_in[idx] : 1400;1702/*printf("idx=%d, pa_in[idx]=%d\n", i, pa_in[idx]);*/1703}17041705beta_raw = 0;1706alpha_raw = 0;17071708for (bin = 0; bin <= half_hi; bin++) {1709/*1710* printf(1711* "bin=%d half_lo=%d m=%d theta[bin+half_lo]=%d "1712* "y_est[bin+half_lo]=%d\n",1713* bin, half_lo, m, theta[bin+half_lo], y_est[bin+half_lo]);1714*/1715/* y_est[] was already checked for zero */1716theta_tilde[bin] =1717((theta[bin + half_lo] << m) + y_est[bin + half_lo]) /1718y_est[bin + half_lo];1719theta_tilde[bin] = ((theta_tilde[bin] << m) + y_est[bin + half_lo]) /1720y_est[bin + half_lo];1721theta_tilde[bin] = ((theta_tilde[bin] << m) + y_est[bin + half_lo]) /1722y_est[bin + half_lo];17231724/*printf("bin=%d theta_tilde[bin]=%d\n", bin, theta_tilde[bin]);*/1725beta_raw = beta_raw + b1_tmp[bin] * theta_tilde[bin];1726alpha_raw = alpha_raw + b2_tmp[bin] * theta_tilde[bin];17271728/*1729printf("bin=%d, alpha_raw=%d, beta_raw=%d\n", bin, alpha_raw, beta_raw);1730*/1731}17321733q_beta = find_proper_scale(find_expn(paprd_abs(beta_raw)), 10);1734q_alpha = find_proper_scale(find_expn(paprd_abs(alpha_raw)), 10);17351736beta_raw = beta_raw / (1 << q_beta);1737alpha_raw = alpha_raw / (1 << q_alpha);1738/* scale_b checked for zero previously */1739alpha = (alpha_raw << 10) / scale_b;1740beta = (beta_raw << 10) / scale_b;1741order_1 = 3 * m - q_x - q_b1 - q_beta + 10 + q_scale_b + 5;1742order_2 = 3 * m - q_x - q_b2 - q_alpha + 10 + q_scale_b + 5;17431744order1_5x = order_1 / 5;1745order2_3x = order_2 / 3;17461747order1_5x_rem = order_1 - 5 * order1_5x;1748order2_3x_rem = order_2 - 3 * order2_3x;17491750for (idx = 0; idx < AR9300_PAPRD_TABLE_SZ; idx++) {1751tmp = idx * 32;17521753if (beta > 0) {1754y5 = (((beta * tmp - 64) >> 6) -1755(1 << order1_5x)) / (1 << order1_5x);1756} else {1757y5 = ((((beta * tmp - 64) >> 6) +1758(1 << order1_5x)) / (1 << order1_5x));1759}17601761y5 = (y5 * tmp) / (1 << order1_5x);1762y5 = (y5 * tmp) / (1 << order1_5x);1763y5 = (y5 * tmp) / (1 << order1_5x);1764y5 = (y5 * tmp) / (1 << order1_5x);17651766y5 = y5 / (1 << order1_5x_rem);17671768if (beta > 0) {1769y3 = (alpha * tmp - (1 << order2_3x)) / (1 << order2_3x);1770} else {1771y3 = (alpha * tmp + (1 << order2_3x)) / (1 << order2_3x);1772}17731774y3 = (y3 * tmp) / (1 << order2_3x);1775y3 = (y3 * tmp) / (1 << order2_3x);17761777y3 = y3 / (1 << order2_3x_rem);1778pa_angle[idx] = y5 + y3;1779/*printf("idx=%d, y5 = %d, y3=%d\n", idx, y5, y3);*/1780pa_angle[idx] =1781(pa_angle[idx] < -150) ? -150 : ((pa_angle[idx] >1782150) ? 150 : pa_angle[idx]);1783}17841785pa_angle[0] = 0;1786pa_angle[1] = 0;1787pa_angle[2] = 0;1788pa_angle[3] = 0;17891790pa_angle[4] = (pa_angle[5] + 2) >> 1;17911792for (idx = 0; idx < AR9300_PAPRD_TABLE_SZ; idx++) {1793pa_table[idx] = ((pa_in[idx] & 0x7ff) << 11) + (pa_angle[idx] & 0x7ff);1794/*1795* HALDEBUG(1796* NULL, HAL_DEBUG_UNMASKABLE,"%d\t%d\t0x%x\n",1797* pa_in[idx], pa_angle[idx], pa_table[idx]);1798*/1799}18001801/*HALDEBUG(NULL, HAL_DEBUG_UNMASKABLE, "g_fxp = %d\n", g_fxp);*/1802*g_fxp_ext = g_fxp;1803return AH_TRUE;1804}18051806// Due to a hardware bug, when transmitting with just one chain the papd1807// data for chain 0 is always used. So when using chain 2 or 4, the1808// corresponding data must be copied into the chain 0 area.1809void ar9300_swizzle_paprd_entries(struct ath_hal *ah, unsigned int txchain)1810{1811int i;1812u_int32_t *paprd_table_val = NULL;1813u_int32_t small_signal_gain = 0;1814u_int32_t reg = 0;18151816reg = AR_PHY_PAPRD_MEM_TAB_B0;1817switch (txchain) {1818case 0x1:1819case 0x3:1820case 0x7:1821paprd_table_val = &AH9300(ah)->pa_table[0][0];1822small_signal_gain = AH9300(ah)->small_signal_gain[0];1823break;1824case 0x2:1825paprd_table_val = &AH9300(ah)->pa_table[1][0];1826small_signal_gain = AH9300(ah)->small_signal_gain[1];1827break;1828case 0x4:1829paprd_table_val = &AH9300(ah)->pa_table[2][0];1830small_signal_gain = AH9300(ah)->small_signal_gain[2];1831break;1832default:1833// Error out.1834ath_hal_printf(ah, "YAK! Bad chain mask %x\n", txchain);1835return;1836}1837for (i = 0; i < AR9300_PAPRD_TABLE_SZ; i++) {1838OS_REG_WRITE(ah, reg, paprd_table_val[i]);1839HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n", __func__,1840__LINE__, reg, paprd_table_val[i]);18411842reg = reg + 4;1843}1844OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PA_GAIN123_B0,AR_PHY_PA_GAIN123_B0_PA_GAIN1_0, small_signal_gain);1845HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x small_signal_gain 0x%08x\n", __func__, __LINE__,1846(unsigned) AR_PHY_PA_GAIN123_B0, OS_REG_READ(ah, AR_PHY_PA_GAIN123_B0));18471848OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0, AR_PHY_PAPRD_CTRL1_B0_PAPRD_POWER_AT_AM2AM_CAL_0,1849AH9300(ah)->paprd_training_power);1850HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n", __func__, __LINE__,1851(unsigned) AR_PHY_PAPRD_CTRL1_B0, OS_REG_READ(ah, AR_PHY_PAPRD_CTRL1_B0));18521853}18541855void ar9300_populate_paprd_single_table(struct ath_hal *ah,1856struct ieee80211_channel *chan, int chain_num)1857{1858int i, j, bad_read = 0;1859#ifdef AH_DEBUG1860HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);1861#endif1862u_int32_t *paprd_table_val = &AH9300(ah)->pa_table[chain_num][0];1863u_int32_t small_signal_gain = AH9300(ah)->small_signal_gain[chain_num];1864u_int32_t reg = 0;18651866HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1867"%s[%d]: channel %d paprd_done %d write %d\n", __func__, __LINE__,1868ichan->channel, ichan->paprd_done, ichan->paprd_table_write_done);18691870if (chain_num == 0) {1871reg = AR_PHY_PAPRD_MEM_TAB_B0;1872} else if (chain_num == 1) {1873reg = AR_PHY_PAPRD_MEM_TAB_B1;1874} else if (chain_num == 2) {1875reg = AR_PHY_PAPRD_MEM_TAB_B2;1876}18771878for (i = 0; i < AR9300_PAPRD_TABLE_SZ; i++) {1879if (AR_SREV_POSEIDON(ah)) {1880HALASSERT(chain_num == 0x1);1881if ((reg == AR_PHY_PAPRD_MEM_TAB_B1) ||1882(reg == AR_PHY_PAPRD_MEM_TAB_B2)) {1883continue;1884}1885}1886/*1887* sprintf(1888* field_name, "%s%d[%d]%s\0", "BB_paprd_mem_tab_b",1889* chain_num, i, ".paprd_mem");1890*/1891OS_REG_WRITE(ah, reg, paprd_table_val[i]);1892HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n", __func__,1893__LINE__, reg, paprd_table_val[i]);1894/*1895* printf(1896* "%s[%d] reg %08x = 0x%08x\n",1897* __func__, __LINE__, reg, paprd_table_val[i]);1898*/1899if (OS_REG_READ(ah, reg) == 0xdeadbeef) {1900HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,1901"%s: Reg0x%x = 0xdeadbeef\n", __func__, reg);1902bad_read++;1903for (j = AR_PHY_PAPRD_MEM_TAB_B0; j < (AR_PHY_PAPRD_MEM_TAB_B0 + 0x10); j+=4)1904{1905if (OS_REG_READ(ah, j) == 0xdeadbeef) {1906HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,1907"%s: Reg0x%x = 0xdeadbeef\n", __func__, j);1908bad_read++;1909}1910}1911for (j = AR_PHY_PAPRD_MEM_TAB_B1; j < (AR_PHY_PAPRD_MEM_TAB_B1 + 0x10); j+=4)1912{1913if (OS_REG_READ(ah, j) == 0xdeadbeef) {1914HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,1915"%s: Reg0x%x = 0xdeadbeef\n", __func__, j);1916bad_read++;1917}1918}1919}19201921reg = reg + 4;1922}19231924if (bad_read > 4) {1925HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,1926"%s: Get %d 0xdeadbeef. Mark PAPRD as broken.\n",1927__func__, bad_read);1928AH9300(ah)->ah_paprd_broken = AH_TRUE;1929}19301931if (chain_num == 0) {1932OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PA_GAIN123_B0,1933AR_PHY_PA_GAIN123_B0_PA_GAIN1_0, small_signal_gain);1934HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1935"%s[%d] reg %08x small_signal_gain 0x%08x\n", __func__, __LINE__,1936(unsigned) AR_PHY_PA_GAIN123_B0,1937OS_REG_READ(ah, AR_PHY_PA_GAIN123_B0));1938} else if (chain_num == 1) {1939if (!AR_SREV_POSEIDON(ah) && !AR_SREV_HORNET(ah) && !AR_SREV_APHRODITE(ah)) {1940OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PA_GAIN123_B1,1941AR_PHY_PA_GAIN123_B1_PA_GAIN1_1, small_signal_gain);1942HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1943"%s[%d] reg %08x small_signal_gain 0x%08x\n",1944__func__, __LINE__,1945(unsigned) AR_PHY_PA_GAIN123_B1,1946OS_REG_READ(ah, AR_PHY_PA_GAIN123_B1));1947}1948} else if (chain_num == 2) {1949if (!AR_SREV_POSEIDON(ah) && !AR_SREV_HORNET(ah) && !AR_SREV_APHRODITE(ah)) {1950OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PA_GAIN123_B2,1951AR_PHY_PA_GAIN123_B2_PA_GAIN1_2, small_signal_gain);1952HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1953"%s[%d] reg %08x small_signal_gain 0x%08x\n",1954__func__, __LINE__,1955(unsigned) AR_PHY_PA_GAIN123_B2,1956OS_REG_READ(ah, AR_PHY_PA_GAIN123_B2));1957}1958} else {1959/* invalid channel number */1960}19611962OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B0,1963AR_PHY_PAPRD_CTRL1_B0_PAPRD_POWER_AT_AM2AM_CAL_0,1964AH9300(ah)->paprd_training_power);1965HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n", __func__,1966__LINE__, (unsigned) AR_PHY_PAPRD_CTRL1_B0,1967OS_REG_READ(ah, AR_PHY_PAPRD_CTRL1_B0));1968if (!AR_SREV_POSEIDON(ah) && !AR_SREV_HORNET(ah) && !AR_SREV_APHRODITE(ah)) {1969OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B1,1970AR_PHY_PAPRD_CTRL1_B1_PAPRD_POWER_AT_AM2AM_CAL_1,1971AH9300(ah)->paprd_training_power);1972HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n", __func__,1973__LINE__, (unsigned) AR_PHY_PAPRD_CTRL1_B1,1974OS_REG_READ(ah, AR_PHY_PAPRD_CTRL1_B1));1975if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {1976OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_CTRL1_B2,1977AR_PHY_PAPRD_CTRL1_B2_PAPRD_POWER_AT_AM2AM_CAL_2,1978AH9300(ah)->paprd_training_power);1979HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1980"%s[%d] reg %08x = 0x%08x\n", __func__,1981__LINE__, (unsigned) AR_PHY_PAPRD_CTRL1_B2,1982OS_REG_READ(ah, AR_PHY_PAPRD_CTRL1_B2));1983}1984}1985/*ar9300_enable_paprd(ah, AH_TRUE);*/1986}19871988HAL_STATUS ar9300_paprd_setup_gain_table(struct ath_hal *ah, int chain_num)1989{1990unsigned int i, desired_gain, gain_index;1991HALDEBUG(ah, HAL_DEBUG_CALIBRATE,1992"Run papredistortion single table algorithm:: Training power = %d\n",1993AH9300(ah)->paprd_training_power / 2);19941995if (AH9300(ah)->ah_tx_chainmask & (1 << chain_num)) {1996/* this is an active chain */1997desired_gain = ar9300_get_desired_gain_for_chain(1998ah, chain_num, AH9300(ah)->paprd_training_power);1999/* find out gain index */2000gain_index = 0;20012002for (i = 0; i < 32; i++) {2003if (AH9300(ah)->paprd_gain_table_index[i] < desired_gain) {2004gain_index = gain_index + 1;2005} else {2006break;2007}2008}20092010/*printf("gain_index = %d\n", gain_index);*/2011/*ath_hal_printf(ah, "++++ gain_index = %d\n", gain_index);*/2012ar9300_tx_force_gain(ah, gain_index);2013if (AR_SREV_POSEIDON(ah)) {2014OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,2015AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);2016} else {2017OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,2018AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE, 0);2019}2020}20212022return HAL_OK;2023}20242025static HAL_BOOL ar9300_paprd_retrain_pain(struct ath_hal * ah, int * pa_in)2026{2027int count = 0, i;2028int capdiv_offset = 0, quick_drop_offset;2029int capdiv2g, quick_drop;20302031capdiv2g = (OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF3) >> 1) & 0xF;2032if (!AR_SREV_POSEIDON(ah)) {2033quick_drop =2034OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,2035AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);2036} else {2037quick_drop =2038OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,2039AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);2040}20412042if ( quick_drop != 0 ) {2043quick_drop -= 0x40;2044}2045for (i = 0; i < (NUM_BIN + 1); i++) {2046if (pa_in[i] == 1400) {2047count++;2048}2049}20502051if (AR_SREV_POSEIDON(ah)) {2052if ((pa_in[23] < 800) || (pa_in[23] == 1400)) {2053if (pa_in[23] < 800) {2054capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);2055capdiv2g = capdiv2g + capdiv_offset;2056if (capdiv2g > 7) {2057capdiv2g = 7;2058if (pa_in[23] < 600) {2059quick_drop = quick_drop + 1;2060if (quick_drop > 0) {2061quick_drop = 0;2062}2063}2064}20652066OS_REG_RMW_FIELD(ah,2067AR_PHY_65NM_CH0_TXRF3,2068AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2069capdiv2g);20702071OS_REG_RMW_FIELD_ALT(ah,2072AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,2073AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2074quick_drop);20752076return AH_TRUE;2077} /* end of if (pa_in[23] < 800) */2078else if (pa_in[23] == 1400) {2079quick_drop_offset = (int)(count / 3);2080if (quick_drop_offset > 2) {2081quick_drop_offset = 2;2082}2083quick_drop = quick_drop + quick_drop_offset;2084capdiv2g = capdiv2g + (int)(quick_drop_offset / 2);2085if (capdiv2g > 7) {2086capdiv2g = 7;2087}2088if (quick_drop > 0) {2089quick_drop = 0;2090capdiv2g = capdiv2g - (int)(quick_drop_offset / 1);2091if (capdiv2g < 0) {2092capdiv2g = 0;2093}2094}2095OS_REG_RMW_FIELD(ah,2096AR_PHY_65NM_CH0_TXRF3,2097AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2098capdiv2g);20992100OS_REG_RMW_FIELD_ALT(ah,2101AR_PHY_PAPRD_TRAINER_CNTL3_POSEIDON,2102AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2103quick_drop);21042105return AH_TRUE;2106/* sleep(1); */2107} /* end of if (pa_in[23] == 1400)*/2108} /* end of if ((pa_in[23] < 800) || (pa_in[23] == 1400)) */2109}else if (AR_SREV_HORNET(ah)) {2110if ((pa_in[23] < 1000) || (pa_in[23] == 1400)) {2111if (pa_in[23] < 1000) {2112capdiv_offset = ((1000 - pa_in[23]) / 100);2113capdiv2g = capdiv2g + capdiv_offset;2114if (capdiv_offset > 3) {2115quick_drop_offset = 1;2116quick_drop = quick_drop - quick_drop_offset;2117capdiv2g = capdiv2g + 1;2118if (capdiv2g > 6) {2119capdiv2g = 6;2120}2121if (quick_drop < -4) {2122quick_drop = -4;2123}2124OS_REG_RMW_FIELD(ah,2125AR_PHY_65NM_CH0_TXRF3,2126AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2127capdiv2g);2128OS_REG_RMW_FIELD_ALT(ah,2129AR_PHY_PAPRD_TRAINER_CNTL3,2130AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2131quick_drop);2132return AH_TRUE;2133} else {2134capdiv2g = capdiv2g + capdiv_offset;2135if (capdiv2g > 6) {2136capdiv2g = 6;2137}2138if (quick_drop < -4) {2139quick_drop = -4;2140}2141OS_REG_RMW_FIELD(ah,2142AR_PHY_65NM_CH0_TXRF3,2143AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2144capdiv2g);2145OS_REG_RMW_FIELD_ALT(ah,2146AR_PHY_PAPRD_TRAINER_CNTL3,2147AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2148quick_drop);2149return AH_TRUE;2150}2151} /* end of if (PA_in[23] < 1000) */2152else if (pa_in[23] == 1400) {2153if (count > 3) {2154quick_drop_offset = 1;2155quick_drop = quick_drop + quick_drop_offset;2156capdiv2g = capdiv2g - (count / 4);2157if (capdiv2g < 0) {2158capdiv2g = 0;2159}2160if (quick_drop > -2) {2161quick_drop = -2;2162}2163OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,2164AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2165capdiv2g);2166OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,2167AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2168quick_drop);2169return AH_TRUE;2170} else {2171capdiv2g = capdiv2g - 1;2172if (capdiv2g < 0) {2173capdiv2g = 0;2174}2175OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,2176AR_PHY_65NM_CH0_TXRF3_CAPDIV2G,2177capdiv2g);2178OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_CNTL3,2179AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,2180quick_drop);2181return AH_TRUE;2182}2183} /* end of if (PA_in[23] == 1400)*/2184} /* end of if ((PA_in[23] < 1000) || (PA_in[23] == 1400)) */2185}21862187return AH_FALSE;2188}21892190HAL_STATUS ar9300_paprd_create_curve(struct ath_hal * ah,2191struct ieee80211_channel * chan, int chain_num)2192{2193int status = 0;2194u_int32_t *pa_table, small_signal_gain;2195int pa_in[NUM_BIN + 1];21962197if (AH9300(ah)->ah_tx_chainmask & (1 << chain_num)) {2198pa_table = &AH9300(ah)->pa_table[chain_num][0];2199/* Compute PA table and gain index */2200status = ar9300_create_pa_curve(ah, &pa_table[0], &small_signal_gain,2201&pa_in[0]);22022203if (AR_SREV_WASP(ah)) {2204OS_DELAY(1000);2205}22062207if (status != 0) {2208ath_hal_printf(ah, "ERROR:: paprd failed with error code = %d\n",2209status);2210return -1;2211}2212AH9300(ah)->small_signal_gain[chain_num] = small_signal_gain;22132214if (AR_SREV_POSEIDON(ah) || AR_SREV_HORNET(ah)) {2215if (ar9300_paprd_retrain_pain(ah, pa_in)) {2216/* need re-train PAPRD */2217return HAL_EINPROGRESS;2218}2219}2220}2221return HAL_OK;2222}22232224int ar9300_paprd_init_table(struct ath_hal *ah, struct ieee80211_channel * chan)2225{2226HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);22272228if ((AR_SREV_WASP(ah) && IS_CHAN_5GHZ(ichan)) ||2229ar9300_paprd_setup_single_table(ah, chan)) {2230goto FAIL;2231}2232OS_MEMZERO(AH9300(ah)->paprd_gain_table_entries,2233sizeof(AH9300(ah)->paprd_gain_table_entries));2234OS_MEMZERO(AH9300(ah)->paprd_gain_table_index,2235sizeof(AH9300(ah)->paprd_gain_table_index));22362237ar9300_gain_table_entries(ah);2238return 0;2239FAIL:2240return -1;2241}22422243int ar9300_paprd_is_done(struct ath_hal *ah)2244{2245int temp, agc2_pwr;22462247/*field_read("BB_paprd_trainer_stat1.paprd_train_done", &temp);*/2248if (!AR_SREV_POSEIDON(ah)) {2249temp =2250OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,2251AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);22522253if (temp == 0x1) {2254agc2_pwr =2255OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1,2256AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);22572258HALDEBUG(ah, HAL_DEBUG_CALIBRATE,2259"%s AGC2_PWR=0x%2x Training done=0x%2x\n",2260__func__, agc2_pwr, temp);22612262/* Retrain if agc2_pwr is not in ideal range */2263if (agc2_pwr <= AH_PAPRD_IDEAL_AGC2_PWR_RANGE) {2264temp = 0;2265}2266}2267} else {2268temp =2269OS_REG_READ_FIELD_ALT(ah, AR_PHY_PAPRD_TRAINER_STAT1_POSEIDON,2270AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);2271}2272if (!temp) {2273/*ath_hal_printf(ah, "%s[%d] PAPRD TEMp Error\n", __func__, __LINE__);*/2274}22752276return temp;2277}22782279/*2280* ar9300_paprd_dec_tx_pwr2281*2282* This function do decrease tx power if Paprd is off or train failed.2283*/2284void2285ar9300_paprd_dec_tx_pwr(struct ath_hal *ah)2286{2287u_int32_t pwr_temp, pwr_reg;2288int i, loop_cnt;2289struct ar9300_paprd_pwr_adjust *p_item;2290struct ath_hal_9300 *ahp = AH9300(ah);22912292if (AR_SREV_POSEIDON(ah)) {2293loop_cnt =2294(sizeof(ar9300_paprd_pwr_adj_array) /2295sizeof(struct ar9300_paprd_pwr_adjust));2296for (i = 0; i < loop_cnt; i++ )2297{2298p_item = &ar9300_paprd_pwr_adj_array[i];2299pwr_reg = OS_REG_READ(ah, p_item->reg_addr);2300pwr_temp = ahp->ah_default_tx_power[p_item->target_rate];2301pwr_temp -= (p_item->sub_db * 2);2302pwr_temp = pwr_temp << p_item->reg_mask_offset;2303pwr_temp |= (pwr_reg&~(p_item->reg_mask <<p_item->reg_mask_offset));23042305if (pwr_temp != pwr_reg)2306{2307OS_REG_WRITE(ah, p_item->reg_addr, pwr_temp);2308}2309}2310}2311return;2312}23132314int ar9300_paprd_thermal_send(struct ath_hal *ah)2315{2316if (AR_SREV_HORNET(ah)) {2317return OS_REG_READ(ah, AR_TFCNT);2318} else {2319return 1;2320}2321}23222323#if 02324void ar9300_paprd_test_prints(struct ath_hal *ah)2325{2326u_int32_t i, reg = 0;23272328HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "=====ar9300_paprd_test_prints=======\n");2329/*printf("=====ar9300_paprd_test_prints=======\n");*/2330HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "BB_paprd_ctrl0_b0 = 0x%08x\n",2331OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B0));2332/*2333* printf(2334* "BB_paprd_ctrl0_b0 = 0x%08x\n",2335* OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B0));2336*/2337if (!AR_SREV_POSEIDON(ah) && !AR_SREV_HORNET(ah)) {2338HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "BB_paprd_ctrl0_b1 = 0x%08x\n",2339OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B1));2340/*2341* printf(2342* "BB_paprd_ctrl0_b1 = 0x%08x\n",2343* OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B1));2344*/2345HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "BB_paprd_ctrl0_b2 = 0x%08x\n",2346OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B2));2347/*2348* printf(2349* "BB_paprd_ctrl0_b2 = 0x%08x\n",2350* OS_REG_READ(ah, AR_PHY_PAPRD_CTRL0_B2));2351*/2352}23532354reg = AR_PHY_PAPRD_MEM_TAB_B0;2355HALDEBUG(NULL, HAL_DEBUG_CALIBRATE,2356"%s[%d] reg %08lx small_signal_gain ch0 0x%08x\n", __func__, __LINE__,2357AR_PHY_PA_GAIN123_B0, OS_REG_READ(ah, AR_PHY_PA_GAIN123_B0));2358/*2359* printf(2360* "%s[%d] reg %08lx small_signal_gain ch0 0x%08x\n",2361* __func__, __LINE__, AR_PHY_PA_GAIN123_B0,2362* OS_REG_READ(ah, AR_PHY_PA_GAIN123_B0));2363*/23642365for (i = 0; i < 24; i++) {2366HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n",2367__func__, __LINE__, reg, OS_REG_READ(ah, reg));2368/*2369* printf(2370* "%s[%d] reg %08x = 0x%08x\n", __func__, __LINE__,2371* reg, OS_REG_READ(ah, reg));2372*/2373reg = reg + 4;2374}23752376ar9300_paprd_debug_print(ah);2377HALDEBUG(NULL, HAL_DEBUG_CALIBRATE,2378"=====ar9300_paprd_test_prints end=======\n");2379/*printf("=====ar9300_paprd_test_prints end=======\n");*/23802381if (!AR_SREV_POSEIDON(ah)) {2382reg = AR_PHY_PAPRD_MEM_TAB_B1;2383printf("%s[%d] reg %08lx small_signal_gain ch1 0x%08x\n",2384__func__, __LINE__,2385AR_PHY_PA_GAIN123_B1, OS_REG_READ(ah, AR_PHY_PA_GAIN123_B1));2386for (i = 0; i < 24; i++) {2387OS_REG_WRITE(ah, reg, paprd_table_val[i]);2388HALDEBUG(NULL, HAL_DEBUG_CALIBRATE, "%s[%d] reg %08x = 0x%08x\n",2389__func__, __LINE__, reg, OS_REG_READ(ah, reg));2390printf("%s[%d] reg %08x = 0x%08x\n", __func__, __LINE__, reg,2391OS_REG_READ(ah, reg));2392reg = reg + 4;2393}23942395reg = AR_PHY_PAPRD_MEM_TAB_B2;2396printf("%s[%d] reg %08lx small_signal_gain ch2 0x%08x\n",2397__func__, __LINE__,2398AR_PHY_PA_GAIN123_B2, OS_REG_READ(ah, AR_PHY_PA_GAIN123_B2));2399}2400}2401#endif24022403#else2404int2405ar9300_paprd_init_table(struct ath_hal *ah, HAL_CHANNEL * chan)2406{2407return 0;2408}24092410HAL_STATUS2411ar9300_paprd_setup_gain_table(struct ath_hal * ah, int chain_num)2412{2413return HAL_OK;2414}24152416HAL_STATUS2417ar9300_paprd_create_curve(struct ath_hal * ah, HAL_CHANNEL * chan,2418int chain_num)2419{2420return HAL_OK;2421}24222423int2424ar9300_paprd_is_done(struct ath_hal *ah)2425{2426return 0;2427}24282429void2430ar9300_enable_paprd(struct ath_hal *ah, HAL_BOOL enable_flag, HAL_CHANNEL * chan)2431{2432return;2433}24342435void2436ar9300_populate_paprd_single_table(struct ath_hal *ah, HAL_CHANNEL * chan,2437int chain_num)2438{2439return;2440}24412442void2443ar9300_paprd_dec_tx_pwr(struct ath_hal *ah)2444{2445return;2446}24472448int ar9300_paprd_thermal_send(struct ath_hal *ah)2449{2450return 1;2451}2452#endif /* ATH_SUPPORT_PAPRD */245324542455