Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.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"1718#include "ah.h"19#include "ah_internal.h"2021#include "ar9300/ar9300.h"2223/* shorthands to compact tables for readability */24#define OFDM IEEE80211_T_OFDM25#define CCK IEEE80211_T_CCK26#define TURBO IEEE80211_T_TURBO27#define XR ATHEROS_T_XR28#define HT IEEE80211_T_HT2930#define AR9300_NUM_OFDM_RATES 831#define AR9300_NUM_HT_SS_RATES 832#define AR9300_NUM_HT_DS_RATES 833#define AR9300_NUM_HT_TS_RATES 83435/* Array Gain defined for TxBF */36#define AR9300_TXBF_2TX_ARRAY_GAIN 6 /* 2TX/SS 3 */37#define AR9300_TXBF_3TX_ARRAY_GAIN 10 /* 3TX/SS or 3TX/DS 4.8 */38#define AR9300_STBC_3TX_ARRAY_GAIN 10 /* 3TX/SS or 3TX/DS 4.8 */3940/* MCS RATE CODES - first and last */41#define AR9300_MCS0_RATE_CODE 0x8042#define AR9300_MCS23_RATE_CODE 0x974344static inline void ar9300_init_rate_txpower_cck(struct ath_hal *ah,45const HAL_RATE_TABLE *rt, u_int8_t rates_array[], u_int8_t chainmask);46static inline void ar9300_init_rate_txpower_ofdm(struct ath_hal* ah,47const HAL_RATE_TABLE *rt, u_int8_t rates_array[], int rt_offset,48u_int8_t chainmask);49static inline void ar9300_init_rate_txpower_ht(struct ath_hal *ah,50const HAL_RATE_TABLE *rt, HAL_BOOL is40, u_int8_t rates_array[],51int rt_ss_offset, int rt_ds_offset,52int rt_ts_offset, u_int8_t chainmask);53static inline void ar9300_init_rate_txpower_stbc(struct ath_hal *ah,54const HAL_RATE_TABLE *rt, HAL_BOOL is40,55int rt_ss_offset, int rt_ds_offset,56int rt_ts_offset, u_int8_t chainmask);57#if 058static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah,59const HAL_RATE_TABLE *rt, HAL_BOOL is40,60int rt_ss_offset, int rt_ds_offset,61int rt_ts_offset, u_int8_t chainmask);62#endif6364#define AR9300_11A_RT_OFDM_OFFSET 065HAL_RATE_TABLE ar9300_11a_table = {668, /* number of rates */67{ 0 },68{69/* short ctrl */70/* valid rate_code Preamble dot11Rate Rate */71/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 },72/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 },73/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 },74/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 },75/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 },76/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 },77/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 },78/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 },79},80};8182HAL_RATE_TABLE ar9300_11a_half_table = {838, /* number of rates */84{ 0 },85{86/* short ctrl */87/* valid rate_code Preamble dot11Rate Rate */88/* 6 Mb */ { AH_TRUE, OFDM, 3000, 0x0b, 0x00, (0x80 | 6), 0 },89/* 9 Mb */ { AH_TRUE, OFDM, 4500, 0x0f, 0x00, 9, 0 },90/* 12 Mb */ { AH_TRUE, OFDM, 6000, 0x0a, 0x00, (0x80 | 12), 2 },91/* 18 Mb */ { AH_TRUE, OFDM, 9000, 0x0e, 0x00, 18, 2 },92/* 24 Mb */ { AH_TRUE, OFDM, 12000, 0x09, 0x00, (0x80 | 24), 4 },93/* 36 Mb */ { AH_TRUE, OFDM, 18000, 0x0d, 0x00, 36, 4 },94/* 48 Mb */ { AH_TRUE, OFDM, 24000, 0x08, 0x00, 48, 4 },95/* 54 Mb */ { AH_TRUE, OFDM, 27000, 0x0c, 0x00, 54, 4 },96},97};9899HAL_RATE_TABLE ar9300_11a_quarter_table = {1008, /* number of rates */101{ 0 },102{103/* short ctrl */104/* valid rate_code Preamble dot11Rate Rate */105/* 6 Mb */ { AH_TRUE, OFDM, 1500, 0x0b, 0x00, (0x80 | 3), 0 },106/* 9 Mb */ { AH_TRUE, OFDM, 2250, 0x0f, 0x00, 4 , 0 },107/* 12 Mb */ { AH_TRUE, OFDM, 3000, 0x0a, 0x00, (0x80 | 6), 2 },108/* 18 Mb */ { AH_TRUE, OFDM, 4500, 0x0e, 0x00, 9, 2 },109/* 24 Mb */ { AH_TRUE, OFDM, 6000, 0x09, 0x00, (0x80 | 12), 4 },110/* 36 Mb */ { AH_TRUE, OFDM, 9000, 0x0d, 0x00, 18, 4 },111/* 48 Mb */ { AH_TRUE, OFDM, 12000, 0x08, 0x00, 24, 4 },112/* 54 Mb */ { AH_TRUE, OFDM, 13500, 0x0c, 0x00, 27, 4 },113},114};115116HAL_RATE_TABLE ar9300_turbo_table = {1178, /* number of rates */118{ 0 },119{120/* short ctrl */121/* valid rate_code Preamble dot11Rate Rate */122/* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80 | 12), 0 },123/* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 },124/* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80 | 24), 2 },125/* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 },126/* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80 | 48), 4 },127/* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 },128/* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 },129/* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 },130},131};132133HAL_RATE_TABLE ar9300_11b_table = {1344, /* number of rates */135{ 0 },136{137/* short ctrl */138/* valid rate_code Preamble dot11Rate Rate */139/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },140/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },141/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 1 },142/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 1 },143},144};145146147/* Venice TODO: round_up_rate() is broken when the rate table does not represent148* rates in increasing order e.g. 5.5, 11, 6, 9.149* An average rate of 6 Mbps will currently map to 11 Mbps.150*/151#define AR9300_11G_RT_OFDM_OFFSET 4152HAL_RATE_TABLE ar9300_11g_table = {15312, /* number of rates */154{ 0 },155{156/* short ctrl */157/* valid rate_code Preamble dot11Rate Rate */158/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },159/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },160/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 },161/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 },162/* Hardware workaround - remove rates 6, 9 from rate ctrl */163/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, 12, 4 },164/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4 },165/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 },166/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 },167/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 },168/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 },169/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 },170/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 },171},172};173174#if 0175HAL_RATE_TABLE ar9300_xr_table = {17613, /* number of rates */177{ 0 },178{179/* short ctrl */180/* valid rate_code Preamble dot11Rate Rate */181/* 0.25 Mb */ {AH_TRUE, XR, 250, 0x03, 0x00, (0x80 | 1), 0, 612, 612 },182/* 0.5 Mb */ {AH_TRUE, XR, 500, 0x07, 0x00, (0x80 | 1), 0, 457, 457 },183/* 1 Mb */ {AH_TRUE, XR, 1000, 0x02, 0x00, (0x80 | 2), 1, 228, 228 },184/* 2 Mb */ {AH_TRUE, XR, 2000, 0x06, 0x00, (0x80 | 4), 2, 160, 160 },185/* 3 Mb */ {AH_TRUE, XR, 3000, 0x01, 0x00, (0x80 | 6), 3, 140, 140 },186/* 6 Mb */ {AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 4, 60, 60 },187/* 9 Mb */ {AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4, 60, 60 },188/* 12 Mb */ {AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 6, 48, 48 },189/* 18 Mb */ {AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6, 48, 48 },190/* 24 Mb */ {AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8, 44, 44 },191/* 36 Mb */ {AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8, 44, 44 },192/* 48 Mb */ {AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8, 44, 44 },193/* 54 Mb */ {AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8, 44, 44 },194},195};196#endif197198#define AR9300_11NG_RT_OFDM_OFFSET 4199#define AR9300_11NG_RT_HT_SS_OFFSET 12200#define AR9300_11NG_RT_HT_DS_OFFSET 20201#define AR9300_11NG_RT_HT_TS_OFFSET 28202HAL_RATE_TABLE ar9300_11ng_table = {20320436, /* number of rates */205{ 0 },206{207/* short ctrl */208/* valid rate_code Preamble dot11Rate Rate */209/* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },210/* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },211/* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 },212/* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 },213/* Hardware workaround - remove rates 6, 9 from rate ctrl */214/* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 },215/* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 },216/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 },217/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 },218/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 },219/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 },220/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 },221/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 },222/*--- HT SS rates ---*/223/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 4 },224/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 6 },225/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 6 },226/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 },227/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 },228/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 },229/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 },230/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 },231/*--- HT DS rates ---*/232/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 4 },233/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 6 },234/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 6 },235/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 },236/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 },237/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 },238/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 },239/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 },240/*--- HT TS rates ---*/241/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 4 },242/* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 6 },243/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 6 },244/* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 8 },245/* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 8 },246/* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 8 },247/*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 8 },248/* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 8 },249},250};251252#define AR9300_11NA_RT_OFDM_OFFSET 0253#define AR9300_11NA_RT_HT_SS_OFFSET 8254#define AR9300_11NA_RT_HT_DS_OFFSET 16255#define AR9300_11NA_RT_HT_TS_OFFSET 24256static HAL_RATE_TABLE ar9300_11na_table = {25725832, /* number of rates */259{ 0 },260{261/* short ctrl */262/* valid rate_code Preamble dot11Rate Rate */263/* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 },264/* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 },265/* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 },266/* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 },267/* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 },268/* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 },269/* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 },270/* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 },271/*--- HT SS rates ---*/272/* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 0 },273/* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 2 },274/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 2 },275/* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 4 },276/* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 4 },277/* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 4 },278/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 4 },279/* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 4 },280/*--- HT DS rates ---*/281/* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 0 },282/* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 2 },283/* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 2 },284/* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 4 },285/* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 4 },286/* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 4 },287/* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 4 },288/* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 4 },289/*--- HT TS rates ---*/290/*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 0 },291/* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 2 },292/*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 2 },293/* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 4 },294/* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 4 },295/* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 4 },296/*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 4 },297/* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 4 },298},299};300301#undef OFDM302#undef CCK303#undef TURBO304#undef XR305#undef HT306#undef HT_HGI307308const HAL_RATE_TABLE *309ar9300_get_rate_table(struct ath_hal *ah, u_int mode)310{311struct ath_hal_private *ahpriv = AH_PRIVATE(ah);312HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps;313HAL_RATE_TABLE *rt;314315switch (mode) {316case HAL_MODE_11A:317rt = &ar9300_11a_table;318break;319case HAL_MODE_11A_HALF_RATE:320if (p_cap->halChanHalfRate) {321rt = &ar9300_11a_half_table;322break;323}324return AH_NULL;325case HAL_MODE_11A_QUARTER_RATE:326if (p_cap->halChanQuarterRate) {327rt = &ar9300_11a_quarter_table;328break;329}330return AH_NULL;331case HAL_MODE_11B:332rt = &ar9300_11b_table;333break;334case HAL_MODE_11G:335rt = &ar9300_11g_table;336break;337case HAL_MODE_TURBO:338case HAL_MODE_108G:339rt = &ar9300_turbo_table;340break;341#if 0342case HAL_MODE_XR:343rt = &ar9300_xr_table;344break;345#endif346case HAL_MODE_11NG_HT20:347case HAL_MODE_11NG_HT40PLUS:348case HAL_MODE_11NG_HT40MINUS:349rt = &ar9300_11ng_table;350break;351case HAL_MODE_11NA_HT20:352case HAL_MODE_11NA_HT40PLUS:353case HAL_MODE_11NA_HT40MINUS:354rt = &ar9300_11na_table;355break;356default:357HALDEBUG(ah, HAL_DEBUG_CHANNEL,358"%s: invalid mode 0x%x\n", __func__, mode);359return AH_NULL;360}361ath_hal_setupratetable(ah, rt);362return rt;363}364365static HAL_BOOL366ar9300_invalid_stbc_cfg(int tx_chains, u_int8_t rate_code)367{368switch (tx_chains) {369case 0: /* Single Chain */370return AH_TRUE;371372case 1: /* 2 Chains */373if ((rate_code < 0x80) || (rate_code > 0x87)) {374return AH_TRUE;375} else {376return AH_FALSE;377}378379case 2: /* 3 Chains */380if ((rate_code < 0x80) || (rate_code > 0x87)) {381return AH_TRUE;382} else {383return AH_FALSE;384}385386default:387HALASSERT(0);388break;389}390391return AH_TRUE;392}393394int16_t395ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index,396u_int8_t chainmask, u_int8_t xmit_mode)397{398struct ath_hal_9300 *ahp = AH9300(ah);399int num_chains = ar9300_get_ntxchains(chainmask);400401switch (xmit_mode) {402case AR9300_DEF_MODE:403return ahp->txpower[rate_index][num_chains-1];404405406case AR9300_STBC_MODE:407return ahp->txpower_stbc[rate_index][num_chains-1];408409default:410HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",411__func__, xmit_mode);412HALASSERT(0);413break;414}415416return ahp->txpower[rate_index][num_chains-1];417}418419extern void420ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah,421u_int8_t power_per_rate[])422423{424struct ath_hal_9300 *ahp = AH9300(ah);425int16_t twice_array_gain, cdd_power = 0;426int i;427428/*429* Adjust the upper limit for CDD factoring in the array gain .430* The array gain is the same as TxBF, hence reuse the same defines.431*/432switch (ahp->ah_tx_chainmask) {433434case OSPREY_1_CHAINMASK:435cdd_power = ahp->upper_limit[0];436break;437438case OSPREY_2LOHI_CHAINMASK:439case OSPREY_2LOMID_CHAINMASK:440twice_array_gain =441(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?442-(AR9300_TXBF_2TX_ARRAY_GAIN) :443((int16_t)AH_MIN((ahp->twice_antenna_reduction -444(ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));445cdd_power = ahp->upper_limit[1] + twice_array_gain;446447HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 2 chain; cdd_power=%d", __func__, cdd_power);448/* Adjust OFDM legacy rates as well */449for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {450if (power_per_rate[i] > cdd_power) {451power_per_rate[i] = cdd_power;452}453}454455/* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 20*/456for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_7; i++) {457if (power_per_rate[i] > cdd_power) {458power_per_rate[i] = cdd_power;459}460}461462/* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 40*/463for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_7; i++) {464if (power_per_rate[i] > cdd_power) {465power_per_rate[i] = cdd_power;466}467}468break;469470case OSPREY_3_CHAINMASK:471twice_array_gain =472(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?473-(AR9300_TXBF_3TX_ARRAY_GAIN) :474((int16_t)AH_MIN((ahp->twice_antenna_reduction -475(ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));476cdd_power = ahp->upper_limit[2] + twice_array_gain;477HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 3 chain; cdd_power=%d", __func__, cdd_power);478/* Adjust OFDM legacy rates as well */479for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {480if (power_per_rate[i] > cdd_power) {481power_per_rate[i] = cdd_power;482}483}484/* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT20 */485for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_15; i++) {486if (power_per_rate[i] > cdd_power) {487power_per_rate[i] = cdd_power;488}489}490491/* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT40 */492for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_15; i++) {493if (power_per_rate[i] > cdd_power) {494power_per_rate[i] = cdd_power;495}496}497498break;499500default:501HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",502__func__, ahp->ah_tx_chainmask);503break;504}505506return;507}508509extern void510ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode,511const struct ieee80211_channel *chan,512u_int8_t power_per_rate[], u_int8_t chainmask)513{514const HAL_RATE_TABLE *rt;515HAL_BOOL is40 = IEEE80211_IS_CHAN_HT40(chan);516517rt = ar9300_get_rate_table(ah, mode);518HALASSERT(rt != NULL);519520switch (mode) {521case HAL_MODE_11A:522ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,523AR9300_11A_RT_OFDM_OFFSET, chainmask);524break;525case HAL_MODE_11NA_HT20:526case HAL_MODE_11NA_HT40PLUS:527case HAL_MODE_11NA_HT40MINUS:528ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,529AR9300_11NA_RT_OFDM_OFFSET, chainmask);530ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,531AR9300_11NA_RT_HT_SS_OFFSET,532AR9300_11NA_RT_HT_DS_OFFSET,533AR9300_11NA_RT_HT_TS_OFFSET, chainmask);534ar9300_init_rate_txpower_stbc(ah, rt, is40,535AR9300_11NA_RT_HT_SS_OFFSET,536AR9300_11NA_RT_HT_DS_OFFSET,537AR9300_11NA_RT_HT_TS_OFFSET, chainmask);538#if 0539/* For FCC the array gain has to be factored for CDD mode */540if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {541ar9300_adjust_rate_txpower_cdd(ah, rt, is40,542AR9300_11NA_RT_HT_SS_OFFSET,543AR9300_11NA_RT_HT_DS_OFFSET,544AR9300_11NA_RT_HT_TS_OFFSET, chainmask);545}546#endif547break;548case HAL_MODE_11G:549ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);550ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,551AR9300_11G_RT_OFDM_OFFSET, chainmask);552break;553case HAL_MODE_11B:554ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);555break;556case HAL_MODE_11NG_HT20:557case HAL_MODE_11NG_HT40PLUS:558case HAL_MODE_11NG_HT40MINUS:559ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);560ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,561AR9300_11NG_RT_OFDM_OFFSET, chainmask);562ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,563AR9300_11NG_RT_HT_SS_OFFSET,564AR9300_11NG_RT_HT_DS_OFFSET,565AR9300_11NG_RT_HT_TS_OFFSET, chainmask);566ar9300_init_rate_txpower_stbc(ah, rt, is40,567AR9300_11NG_RT_HT_SS_OFFSET,568AR9300_11NG_RT_HT_DS_OFFSET,569AR9300_11NG_RT_HT_TS_OFFSET, chainmask);570#if 0571/* For FCC the array gain needs to be factored for CDD mode */572if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {573ar9300_adjust_rate_txpower_cdd(ah, rt, is40,574AR9300_11NG_RT_HT_SS_OFFSET,575AR9300_11NG_RT_HT_DS_OFFSET,576AR9300_11NG_RT_HT_TS_OFFSET, chainmask);577}578#endif579break;580default:581HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",582__func__, mode);583HALASSERT(0);584break;585}586587}588589static inline void590ar9300_init_rate_txpower_cck(struct ath_hal *ah, const HAL_RATE_TABLE *rt,591u_int8_t rates_array[], u_int8_t chainmask)592{593struct ath_hal_9300 *ahp = AH9300(ah);594/*595* Pick the lower of the long-preamble txpower, and short-preamble tx power.596* Unfortunately, the rate table doesn't have separate entries for these!.597*/598switch (chainmask) {599case OSPREY_1_CHAINMASK:600ahp->txpower[0][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];601ahp->txpower[1][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];602ahp->txpower[2][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],603rates_array[ALL_TARGET_LEGACY_5S]);604ahp->txpower[3][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],605rates_array[ALL_TARGET_LEGACY_11S]);606break;607case OSPREY_2LOHI_CHAINMASK:608case OSPREY_2LOMID_CHAINMASK:609ahp->txpower[0][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];610ahp->txpower[1][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];611ahp->txpower[2][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],612rates_array[ALL_TARGET_LEGACY_5S]);613ahp->txpower[3][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],614rates_array[ALL_TARGET_LEGACY_11S]);615break;616case OSPREY_3_CHAINMASK:617ahp->txpower[0][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];618ahp->txpower[1][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];619ahp->txpower[2][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],620rates_array[ALL_TARGET_LEGACY_5S]);621ahp->txpower[3][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],622rates_array[ALL_TARGET_LEGACY_11S]);623break;624default:625HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",626__func__, chainmask);627break;628}629}630631static inline void632ar9300_init_rate_txpower_ofdm(struct ath_hal *ah, const HAL_RATE_TABLE *rt,633u_int8_t rates_array[], int rt_offset,634u_int8_t chainmask)635{636struct ath_hal_9300 *ahp = AH9300(ah);637int16_t twice_array_gain, cdd_power = 0;638int i, j;639u_int8_t ofdm_rt_2_pwr_idx[8] =640{641ALL_TARGET_LEGACY_6_24,642ALL_TARGET_LEGACY_6_24,643ALL_TARGET_LEGACY_6_24,644ALL_TARGET_LEGACY_6_24,645ALL_TARGET_LEGACY_6_24,646ALL_TARGET_LEGACY_36,647ALL_TARGET_LEGACY_48,648ALL_TARGET_LEGACY_54,649};650651/*652* For FCC adjust the upper limit for CDD factoring in the array gain.653* The array gain is the same as TxBF, hence reuse the same defines.654*/655for (i = rt_offset; i < rt_offset + AR9300_NUM_OFDM_RATES; i++) {656657/* Get the correct OFDM rate to Power table Index */658j = ofdm_rt_2_pwr_idx[i- rt_offset];659660switch (chainmask) {661case OSPREY_1_CHAINMASK:662ahp->txpower[i][0] = rates_array[j];663break;664case OSPREY_2LOHI_CHAINMASK:665case OSPREY_2LOMID_CHAINMASK:666ahp->txpower[i][1] = rates_array[j];667if (is_reg_dmn_fcc(ahp->reg_dmn)){668twice_array_gain = (ahp->twice_antenna_gain >=669ahp->twice_antenna_reduction)?670-(AR9300_TXBF_2TX_ARRAY_GAIN) :671((int16_t)AH_MIN((ahp->twice_antenna_reduction -672(ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));673cdd_power = ahp->upper_limit[1] + twice_array_gain;674if (ahp->txpower[i][1] > cdd_power){675ahp->txpower[i][1] = cdd_power;676}677}678break;679case OSPREY_3_CHAINMASK:680ahp->txpower[i][2] = rates_array[j];681if (is_reg_dmn_fcc(ahp->reg_dmn)) {682twice_array_gain =683(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?684-(AR9300_TXBF_3TX_ARRAY_GAIN):685((int16_t)AH_MIN((ahp->twice_antenna_reduction -686(ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));687cdd_power = ahp->upper_limit[2] + twice_array_gain;688if (ahp->txpower[i][2] > cdd_power){689ahp->txpower[i][2] = cdd_power;690}691}692break;693default:694HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",695__func__, chainmask);696break;697}698}699}700701static u_int8_t mcs_rate_2_pwr_idx_ht20[24] =702{703ALL_TARGET_HT20_0_8_16,704ALL_TARGET_HT20_1_3_9_11_17_19,705ALL_TARGET_HT20_1_3_9_11_17_19,706ALL_TARGET_HT20_1_3_9_11_17_19,707ALL_TARGET_HT20_4,708ALL_TARGET_HT20_5,709ALL_TARGET_HT20_6,710ALL_TARGET_HT20_7,711ALL_TARGET_HT20_0_8_16,712ALL_TARGET_HT20_1_3_9_11_17_19,713ALL_TARGET_HT20_1_3_9_11_17_19,714ALL_TARGET_HT20_1_3_9_11_17_19,715ALL_TARGET_HT20_12,716ALL_TARGET_HT20_13,717ALL_TARGET_HT20_14,718ALL_TARGET_HT20_15,719ALL_TARGET_HT20_0_8_16,720ALL_TARGET_HT20_1_3_9_11_17_19,721ALL_TARGET_HT20_1_3_9_11_17_19,722ALL_TARGET_HT20_1_3_9_11_17_19,723ALL_TARGET_HT20_20,724ALL_TARGET_HT20_21,725ALL_TARGET_HT20_22,726ALL_TARGET_HT20_23727};728729static u_int8_t mcs_rate_2_pwr_idx_ht40[24] =730{731ALL_TARGET_HT40_0_8_16,732ALL_TARGET_HT40_1_3_9_11_17_19,733ALL_TARGET_HT40_1_3_9_11_17_19,734ALL_TARGET_HT40_1_3_9_11_17_19,735ALL_TARGET_HT40_4,736ALL_TARGET_HT40_5,737ALL_TARGET_HT40_6,738ALL_TARGET_HT40_7,739ALL_TARGET_HT40_0_8_16,740ALL_TARGET_HT40_1_3_9_11_17_19,741ALL_TARGET_HT40_1_3_9_11_17_19,742ALL_TARGET_HT40_1_3_9_11_17_19,743ALL_TARGET_HT40_12,744ALL_TARGET_HT40_13,745ALL_TARGET_HT40_14,746ALL_TARGET_HT40_15,747ALL_TARGET_HT40_0_8_16,748ALL_TARGET_HT40_1_3_9_11_17_19,749ALL_TARGET_HT40_1_3_9_11_17_19,750ALL_TARGET_HT40_1_3_9_11_17_19,751ALL_TARGET_HT40_20,752ALL_TARGET_HT40_21,753ALL_TARGET_HT40_22,754ALL_TARGET_HT40_23,755};756757static inline void758ar9300_init_rate_txpower_ht(struct ath_hal *ah, const HAL_RATE_TABLE *rt,759HAL_BOOL is40,760u_int8_t rates_array[],761int rt_ss_offset, int rt_ds_offset,762int rt_ts_offset, u_int8_t chainmask)763{764765struct ath_hal_9300 *ahp = AH9300(ah);766int i, j;767u_int8_t mcs_index = 0;768769770for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {771/* Get the correct MCS rate to Power table Index */772j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :773mcs_rate_2_pwr_idx_ht20[mcs_index];774switch (chainmask) {775case OSPREY_1_CHAINMASK:776ahp->txpower[i][0] = rates_array[j];777break;778case OSPREY_2LOHI_CHAINMASK:779case OSPREY_2LOMID_CHAINMASK:780ahp->txpower[i][1] = rates_array[j];781break;782case OSPREY_3_CHAINMASK:783ahp->txpower[i][2] = rates_array[j];784break;785default:786HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",787__func__, chainmask);788break;789}790mcs_index++;791}792793for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {794/* Get the correct MCS rate to Power table Index */795j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :796mcs_rate_2_pwr_idx_ht20[mcs_index];797switch (chainmask) {798case OSPREY_1_CHAINMASK:799ahp->txpower[i][0] = rates_array[j];800break;801case OSPREY_2LOHI_CHAINMASK:802case OSPREY_2LOMID_CHAINMASK:803ahp->txpower[i][1] = rates_array[j];804break;805case OSPREY_3_CHAINMASK:806ahp->txpower[i][2] = rates_array[j];807break;808default:809HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",810__func__, chainmask);811break;812}813mcs_index++;814}815816for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {817/* Get the correct MCS rate to Power table Index */818j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :819mcs_rate_2_pwr_idx_ht20[mcs_index];820switch (chainmask) {821case OSPREY_1_CHAINMASK:822ahp->txpower[i][0] = rates_array[j];823break;824case OSPREY_2LOHI_CHAINMASK:825case OSPREY_2LOMID_CHAINMASK:826ahp->txpower[i][1] = rates_array[j];827break;828case OSPREY_3_CHAINMASK:829ahp->txpower[i][2] = rates_array[j];830break;831default:832HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",833__func__, chainmask);834break;835}836mcs_index++;837}838}839840static inline void841ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt,842HAL_BOOL is40,843int rt_ss_offset, int rt_ds_offset,844int rt_ts_offset, u_int8_t chainmask)845{846847struct ath_hal_9300 *ahp = AH9300(ah);848int i;849int16_t twice_array_gain, stbc_power = 0;850u_int8_t mcs_index = 0;851852/* Upper Limit with STBC */853switch (chainmask) {854case OSPREY_1_CHAINMASK:855stbc_power = ahp->upper_limit[0];856break;857case OSPREY_2LOHI_CHAINMASK:858case OSPREY_2LOMID_CHAINMASK:859stbc_power = ahp->upper_limit[1];860break;861case OSPREY_3_CHAINMASK:862stbc_power = ahp->upper_limit[2];863/* Ony FCC requires that we back off with 3 transmit chains */864if (is_reg_dmn_fcc(ahp->reg_dmn)) {865twice_array_gain =866(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?867-(AR9300_STBC_3TX_ARRAY_GAIN) :868((int16_t)AH_MIN((ahp->twice_antenna_reduction -869(ahp->twice_antenna_gain + AR9300_STBC_3TX_ARRAY_GAIN)), 0));870stbc_power = ahp->upper_limit[2] + twice_array_gain;871}872break;873874default:875HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",876__func__, chainmask);877break;878}879880881for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {882switch (chainmask) {883case OSPREY_1_CHAINMASK:884ahp->txpower_stbc[i][0] = ahp->txpower[i][0];885break;886case OSPREY_2LOHI_CHAINMASK:887case OSPREY_2LOMID_CHAINMASK:888ahp->txpower_stbc[i][1] = ahp->txpower[i][1];889break;890case OSPREY_3_CHAINMASK:891ahp->txpower_stbc[i][2] = ahp->txpower[i][2];892/* 3 TX/1 stream STBC gain adjustment */893if (ahp->txpower_stbc[i][2] > stbc_power){894ahp->txpower_stbc[i][2] = stbc_power;895}896break;897default:898HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",899__func__, chainmask);900break;901}902mcs_index++;903}904905for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {906switch (chainmask) {907case OSPREY_1_CHAINMASK:908ahp->txpower_stbc[i][0] = ahp->txpower[i][0];909break;910case OSPREY_2LOHI_CHAINMASK:911case OSPREY_2LOMID_CHAINMASK:912ahp->txpower_stbc[i][1] = ahp->txpower[i][1];913break;914case OSPREY_3_CHAINMASK:915ahp->txpower_stbc[i][2] = ahp->txpower[i][2];916/* 3 TX/2 stream STBC gain adjustment */917if (ahp->txpower_stbc[i][2] > stbc_power){918ahp->txpower_stbc[i][2] = stbc_power;919}920break;921default:922HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",923__func__, chainmask);924break;925}926mcs_index++;927}928929for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {930switch (chainmask) {931case OSPREY_1_CHAINMASK:932ahp->txpower_stbc[i][0] = ahp->txpower[i][0];933break;934case OSPREY_2LOHI_CHAINMASK:935case OSPREY_2LOMID_CHAINMASK:936ahp->txpower_stbc[i][1] = ahp->txpower[i][1];937break;938case OSPREY_3_CHAINMASK:939ahp->txpower_stbc[i][2] = ahp->txpower[i][2];940break;941default:942HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",943__func__, chainmask);944break;945}946mcs_index++;947}948949return;950}951952/*953* To see why this is disabled, look at ar9300_eeprom.c for FCC/OET 13TR1003.954*/955#if 0956static inline void957ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt,958HAL_BOOL is40,959int rt_ss_offset, int rt_ds_offset,960int rt_ts_offset, u_int8_t chainmask)961{962963struct ath_hal_9300 *ahp = AH9300(ah);964int i;965int16_t twice_array_gain, cdd_power = 0;966u_int8_t mcs_index = 0;967968/*969* Adjust the upper limit for CDD factoring in the array gain .970* The array gain is the same as TxBF, hence reuse the same defines.971*/972switch (chainmask) {973case OSPREY_1_CHAINMASK:974cdd_power = ahp->upper_limit[0];975break;976977case OSPREY_2LOHI_CHAINMASK:978case OSPREY_2LOMID_CHAINMASK:979twice_array_gain =980(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?981-(AR9300_TXBF_2TX_ARRAY_GAIN) :982((int16_t)AH_MIN((ahp->twice_antenna_reduction -983(ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));984cdd_power = ahp->upper_limit[1] + twice_array_gain;985break;986987case OSPREY_3_CHAINMASK:988twice_array_gain =989(ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?990-(AR9300_TXBF_3TX_ARRAY_GAIN) :991((int16_t)AH_MIN((ahp->twice_antenna_reduction -992(ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));993cdd_power = ahp->upper_limit[2] + twice_array_gain;994break;995996default:997HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",998__func__, chainmask);999break;1000}100110021003for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {1004switch (chainmask) {1005case OSPREY_1_CHAINMASK:1006break;10071008case OSPREY_2LOHI_CHAINMASK:1009case OSPREY_2LOMID_CHAINMASK:1010/* 2 TX/1 stream CDD gain adjustment */1011if (ahp->txpower[i][1] > cdd_power){1012ahp->txpower[i][1] = cdd_power;1013}1014break;1015case OSPREY_3_CHAINMASK:1016/* 3 TX/1 stream CDD gain adjustment */1017if (ahp->txpower[i][2] > cdd_power){1018ahp->txpower[i][2] = cdd_power;1019}1020break;1021default:1022HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",1023__func__, chainmask);1024break;1025}1026mcs_index++;1027}10281029for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {1030switch (chainmask) {1031case OSPREY_1_CHAINMASK:1032case OSPREY_2LOHI_CHAINMASK:1033case OSPREY_2LOMID_CHAINMASK:1034break;1035case OSPREY_3_CHAINMASK:1036/* 3 TX/2 stream TxBF gain adjustment */1037if (ahp->txpower[i][2] > cdd_power){1038ahp->txpower[i][2] = cdd_power;1039}1040break;1041default:1042HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",1043__func__, chainmask);1044break;1045}1046mcs_index++;1047}10481049return;10501051}1052#endif10531054void ar9300_disp_tpc_tables(struct ath_hal *ah)1055{1056struct ath_hal_9300 *ahp = AH9300(ah);1057const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;1058u_int mode = ath_hal_get_curmode(ah, chan);1059const HAL_RATE_TABLE *rt;1060int i, j;10611062/* Check whether TPC is enabled */1063if (!ah->ah_config.ath_hal_desc_tpc) {1064ath_hal_printf(ah, "\n TPC Register method in use\n");1065return;1066}10671068rt = ar9300_get_rate_table(ah, mode);1069HALASSERT(rt != NULL);10701071ath_hal_printf(ah, "\n===TARGET POWER TABLE===\n");1072for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {1073for (i = 0; i < rt->rateCount; i++) {1074int16_t txpower[AR9300_MAX_CHAINS];1075txpower[j] = ahp->txpower[i][j];1076ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "1077"Power (%d Chain) [%2d.%1d dBm]\n",1078i, rt->info[i].rateCode, rt->info[i].rateKbps,1079j + 1, txpower[j] / 2, txpower[j]%2 * 5);1080}1081}1082ath_hal_printf(ah, "\n");10831084ath_hal_printf(ah, "\n\n===TARGET POWER TABLE with STBC===\n");1085for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {1086for (i = 0; i < rt->rateCount; i++) {1087int16_t txpower[AR9300_MAX_CHAINS];1088txpower[j] = ahp->txpower_stbc[i][j];10891090/* Do not display invalid configurations */1091if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||1092(rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||1093ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {1094continue;1095}10961097ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "1098"Power (%d Chain) [%2d.%1d dBm]\n",1099i, rt->info[i].rateCode , rt->info[i].rateKbps,1100j + 1, txpower[j] / 2, txpower[j]%2 * 5);1101}1102}1103ath_hal_printf(ah, "\n");1104}11051106/*1107* The followings are customer specific APIs for querying power limit.1108* Power limit is based on regulatory domain, chipset, and transmission rate.1109* Here we only consider EEPROM values, no array gain/CTL considered here.1110*/11111112struct rate_power_tbl {1113u_int8_t rateIdx; /* rate index in the rate table */1114u_int32_t rateKbps; /* transfer rate in kbs */1115u_int8_t rateCode; /* rate for h/w descriptors */1116u_int8_t txbf: 1, /* txbf eligible */1117stbc: 1, /* stbc eligible */1118chain1: 1, /* one-chain eligible */1119chain2: 1, /* two-chain eligible */1120chain3: 1; /* three-chain eligible */1121int16_t txpower[AR9300_MAX_CHAINS]; /* txpower for different chainmasks */1122int16_t txpower_stbc[AR9300_MAX_CHAINS];1123};11241125u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah)1126{1127struct ath_hal_9300 *ahp = AH9300(ah);1128const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;1129u_int mode = ath_hal_get_curmode(ah, chan);1130const HAL_RATE_TABLE *rt;1131u_int8_t *data;1132struct rate_power_tbl *table;1133int i, j;11341135/* Check whether TPC is enabled */1136if (! ah->ah_config.ath_hal_desc_tpc) {1137ath_hal_printf(ah, "\n TPC Register method in use\n");1138return NULL;1139}11401141rt = (const HAL_RATE_TABLE *)ar9300_get_rate_table(ah, mode);1142HALASSERT(rt != NULL);11431144data = (u_int8_t *)ath_hal_malloc(11451 + rt->rateCount * sizeof(struct rate_power_tbl));1146if (data == NULL)1147return NULL;11481149OS_MEMZERO(data, 1 + rt->rateCount * sizeof(struct rate_power_tbl));1150/* store the rate count at the beginning */1151*data = rt->rateCount;1152table = (struct rate_power_tbl *)&data[1];11531154for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {1155for (i = 0; i < rt->rateCount; i++) {1156table[i].rateIdx = i;1157table[i].rateCode = rt->info[i].rateCode;1158table[i].rateKbps = rt->info[i].rateKbps;1159switch (j) {1160case 0:1161table[i].chain1 = rt->info[i].rateCode <= 0x87 ? 1 : 0;1162break;1163case 1:1164table[i].chain2 = rt->info[i].rateCode <= 0x8f ? 1 : 0;1165break;1166case 2:1167table[i].chain3 = 1;1168break;1169default:1170break;1171}1172if ((j == 0 && table[i].chain1) ||1173(j == 1 && table[i].chain2) ||1174(j == 2 && table[i].chain3))1175table[i].txpower[j] = ahp->txpower[i][j];1176}1177}11781179for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {1180for (i = 0; i < rt->rateCount; i++) {1181/* Do not display invalid configurations */1182if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||1183(rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||1184ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {1185continue;1186}11871188table[i].stbc = 1;1189table[i].txpower_stbc[j] = ahp->txpower_stbc[i][j];1190}1191}11921193return data;1194/* the caller is responsible to free data */1195}11961197HAL_STATUS1198ath_hal_get_rate_power_limit_from_eeprom(struct ath_hal *ah, u_int16_t freq,1199int8_t *max_rate_power, int8_t *min_rate_power)1200{1201/*1202* Used for AR9300 series chip only1203*/1204if (ah->ah_magic == AR9300_MAGIC) {1205u_int8_t target_rate_power_limit_val_t2[ar9300_rate_size];1206int i;12071208*max_rate_power = 0;1209*min_rate_power = AR9300_MAX_RATE_POWER;12101211ar9300_set_target_power_from_eeprom(ah, freq, target_rate_power_limit_val_t2);12121213for (i=0; i<ar9300_rate_size; i++) {1214if (target_rate_power_limit_val_t2[i] > *max_rate_power)1215*max_rate_power = target_rate_power_limit_val_t2[i];1216if (target_rate_power_limit_val_t2[i] < *min_rate_power)1217*min_rate_power = target_rate_power_limit_val_t2[i];1218}1219} else {1220*max_rate_power = 0;1221*min_rate_power = 0;1222}12231224return HAL_OK;1225}122612271228