1 /* 2 * Copyright (c) 2013 Qualcomm Atheros, Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "opt_ah.h" 18 19 #include "ah.h" 20 #include "ah_internal.h" 21 22 #include "ar9300/ar9300.h" 23 24 /* shorthands to compact tables for readability */ 25 #define OFDM IEEE80211_T_OFDM 26 #define CCK IEEE80211_T_CCK 27 #define TURBO IEEE80211_T_TURBO 28 #define XR ATHEROS_T_XR 29 #define HT IEEE80211_T_HT 30 31 #define AR9300_NUM_OFDM_RATES 8 32 #define AR9300_NUM_HT_SS_RATES 8 33 #define AR9300_NUM_HT_DS_RATES 8 34 #define AR9300_NUM_HT_TS_RATES 8 35 36 /* Array Gain defined for TxBF */ 37 #define AR9300_TXBF_2TX_ARRAY_GAIN 6 /* 2TX/SS 3 */ 38 #define AR9300_TXBF_3TX_ARRAY_GAIN 10 /* 3TX/SS or 3TX/DS 4.8 */ 39 #define AR9300_STBC_3TX_ARRAY_GAIN 10 /* 3TX/SS or 3TX/DS 4.8 */ 40 41 /* MCS RATE CODES - first and last */ 42 #define AR9300_MCS0_RATE_CODE 0x80 43 #define AR9300_MCS23_RATE_CODE 0x97 44 45 static inline void ar9300_init_rate_txpower_cck(struct ath_hal *ah, 46 const HAL_RATE_TABLE *rt, u_int8_t rates_array[], u_int8_t chainmask); 47 static inline void ar9300_init_rate_txpower_ofdm(struct ath_hal* ah, 48 const HAL_RATE_TABLE *rt, u_int8_t rates_array[], int rt_offset, 49 u_int8_t chainmask); 50 static inline void ar9300_init_rate_txpower_ht(struct ath_hal *ah, 51 const HAL_RATE_TABLE *rt, HAL_BOOL is40, u_int8_t rates_array[], 52 int rt_ss_offset, int rt_ds_offset, 53 int rt_ts_offset, u_int8_t chainmask); 54 static inline void ar9300_init_rate_txpower_stbc(struct ath_hal *ah, 55 const HAL_RATE_TABLE *rt, HAL_BOOL is40, 56 int rt_ss_offset, int rt_ds_offset, 57 int rt_ts_offset, u_int8_t chainmask); 58 #if 0 59 static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, 60 const HAL_RATE_TABLE *rt, HAL_BOOL is40, 61 int rt_ss_offset, int rt_ds_offset, 62 int rt_ts_offset, u_int8_t chainmask); 63 #endif 64 65 #define AR9300_11A_RT_OFDM_OFFSET 0 66 HAL_RATE_TABLE ar9300_11a_table = { 67 8, /* number of rates */ 68 { 0 }, 69 { 70 /* short ctrl */ 71 /* valid rate_code Preamble dot11Rate Rate */ 72 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 }, 73 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, 74 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 }, 75 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, 76 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 }, 77 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, 78 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, 79 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 }, 80 }, 81 }; 82 83 HAL_RATE_TABLE ar9300_11a_half_table = { 84 8, /* number of rates */ 85 { 0 }, 86 { 87 /* short ctrl */ 88 /* valid rate_code Preamble dot11Rate Rate */ 89 /* 6 Mb */ { AH_TRUE, OFDM, 3000, 0x0b, 0x00, (0x80 | 6), 0 }, 90 /* 9 Mb */ { AH_TRUE, OFDM, 4500, 0x0f, 0x00, 9, 0 }, 91 /* 12 Mb */ { AH_TRUE, OFDM, 6000, 0x0a, 0x00, (0x80 | 12), 2 }, 92 /* 18 Mb */ { AH_TRUE, OFDM, 9000, 0x0e, 0x00, 18, 2 }, 93 /* 24 Mb */ { AH_TRUE, OFDM, 12000, 0x09, 0x00, (0x80 | 24), 4 }, 94 /* 36 Mb */ { AH_TRUE, OFDM, 18000, 0x0d, 0x00, 36, 4 }, 95 /* 48 Mb */ { AH_TRUE, OFDM, 24000, 0x08, 0x00, 48, 4 }, 96 /* 54 Mb */ { AH_TRUE, OFDM, 27000, 0x0c, 0x00, 54, 4 }, 97 }, 98 }; 99 100 HAL_RATE_TABLE ar9300_11a_quarter_table = { 101 8, /* number of rates */ 102 { 0 }, 103 { 104 /* short ctrl */ 105 /* valid rate_code Preamble dot11Rate Rate */ 106 /* 6 Mb */ { AH_TRUE, OFDM, 1500, 0x0b, 0x00, (0x80 | 3), 0 }, 107 /* 9 Mb */ { AH_TRUE, OFDM, 2250, 0x0f, 0x00, 4 , 0 }, 108 /* 12 Mb */ { AH_TRUE, OFDM, 3000, 0x0a, 0x00, (0x80 | 6), 2 }, 109 /* 18 Mb */ { AH_TRUE, OFDM, 4500, 0x0e, 0x00, 9, 2 }, 110 /* 24 Mb */ { AH_TRUE, OFDM, 6000, 0x09, 0x00, (0x80 | 12), 4 }, 111 /* 36 Mb */ { AH_TRUE, OFDM, 9000, 0x0d, 0x00, 18, 4 }, 112 /* 48 Mb */ { AH_TRUE, OFDM, 12000, 0x08, 0x00, 24, 4 }, 113 /* 54 Mb */ { AH_TRUE, OFDM, 13500, 0x0c, 0x00, 27, 4 }, 114 }, 115 }; 116 117 HAL_RATE_TABLE ar9300_turbo_table = { 118 8, /* number of rates */ 119 { 0 }, 120 { 121 /* short ctrl */ 122 /* valid rate_code Preamble dot11Rate Rate */ 123 /* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80 | 12), 0 }, 124 /* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 }, 125 /* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80 | 24), 2 }, 126 /* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 }, 127 /* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80 | 48), 4 }, 128 /* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 }, 129 /* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 }, 130 /* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 }, 131 }, 132 }; 133 134 HAL_RATE_TABLE ar9300_11b_table = { 135 4, /* number of rates */ 136 { 0 }, 137 { 138 /* short ctrl */ 139 /* valid rate_code Preamble dot11Rate Rate */ 140 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 }, 141 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 }, 142 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 1 }, 143 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 1 }, 144 }, 145 }; 146 147 148 /* Venice TODO: round_up_rate() is broken when the rate table does not represent 149 * rates in increasing order e.g. 5.5, 11, 6, 9. 150 * An average rate of 6 Mbps will currently map to 11 Mbps. 151 */ 152 #define AR9300_11G_RT_OFDM_OFFSET 4 153 HAL_RATE_TABLE ar9300_11g_table = { 154 12, /* number of rates */ 155 { 0 }, 156 { 157 /* short ctrl */ 158 /* valid rate_code Preamble dot11Rate Rate */ 159 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 }, 160 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 }, 161 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 }, 162 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 }, 163 /* Hardware workaround - remove rates 6, 9 from rate ctrl */ 164 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, 165 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, 166 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, 167 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, 168 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, 169 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, 170 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, 171 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, 172 }, 173 }; 174 175 #if 0 176 HAL_RATE_TABLE ar9300_xr_table = { 177 13, /* number of rates */ 178 { 0 }, 179 { 180 /* short ctrl */ 181 /* valid rate_code Preamble dot11Rate Rate */ 182 /* 0.25 Mb */ {AH_TRUE, XR, 250, 0x03, 0x00, (0x80 | 1), 0, 612, 612 }, 183 /* 0.5 Mb */ {AH_TRUE, XR, 500, 0x07, 0x00, (0x80 | 1), 0, 457, 457 }, 184 /* 1 Mb */ {AH_TRUE, XR, 1000, 0x02, 0x00, (0x80 | 2), 1, 228, 228 }, 185 /* 2 Mb */ {AH_TRUE, XR, 2000, 0x06, 0x00, (0x80 | 4), 2, 160, 160 }, 186 /* 3 Mb */ {AH_TRUE, XR, 3000, 0x01, 0x00, (0x80 | 6), 3, 140, 140 }, 187 /* 6 Mb */ {AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 4, 60, 60 }, 188 /* 9 Mb */ {AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4, 60, 60 }, 189 /* 12 Mb */ {AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 6, 48, 48 }, 190 /* 18 Mb */ {AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6, 48, 48 }, 191 /* 24 Mb */ {AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8, 44, 44 }, 192 /* 36 Mb */ {AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8, 44, 44 }, 193 /* 48 Mb */ {AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8, 44, 44 }, 194 /* 54 Mb */ {AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8, 44, 44 }, 195 }, 196 }; 197 #endif 198 199 #define AR9300_11NG_RT_OFDM_OFFSET 4 200 #define AR9300_11NG_RT_HT_SS_OFFSET 12 201 #define AR9300_11NG_RT_HT_DS_OFFSET 20 202 #define AR9300_11NG_RT_HT_TS_OFFSET 28 203 HAL_RATE_TABLE ar9300_11ng_table = { 204 205 36, /* number of rates */ 206 { 0 }, 207 { 208 /* short ctrl */ 209 /* valid rate_code Preamble dot11Rate Rate */ 210 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 }, 211 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 }, 212 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 }, 213 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 }, 214 /* Hardware workaround - remove rates 6, 9 from rate ctrl */ 215 /* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 }, 216 /* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 }, 217 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 }, 218 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 }, 219 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 }, 220 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 }, 221 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 }, 222 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 }, 223 /*--- HT SS rates ---*/ 224 /* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 4 }, 225 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 6 }, 226 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 6 }, 227 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 }, 228 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 }, 229 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 }, 230 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 }, 231 /* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 }, 232 /*--- HT DS rates ---*/ 233 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 4 }, 234 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 6 }, 235 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 6 }, 236 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 }, 237 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 }, 238 /* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 }, 239 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 }, 240 /* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 }, 241 /*--- HT TS rates ---*/ 242 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 4 }, 243 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 6 }, 244 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 6 }, 245 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 8 }, 246 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 8 }, 247 /* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 8 }, 248 /*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 8 }, 249 /* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 8 }, 250 }, 251 }; 252 253 #define AR9300_11NA_RT_OFDM_OFFSET 0 254 #define AR9300_11NA_RT_HT_SS_OFFSET 8 255 #define AR9300_11NA_RT_HT_DS_OFFSET 16 256 #define AR9300_11NA_RT_HT_TS_OFFSET 24 257 static HAL_RATE_TABLE ar9300_11na_table = { 258 259 32, /* number of rates */ 260 { 0 }, 261 { 262 /* short ctrl */ 263 /* valid rate_code Preamble dot11Rate Rate */ 264 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 }, 265 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 }, 266 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 }, 267 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 }, 268 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 }, 269 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 }, 270 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 }, 271 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 }, 272 /*--- HT SS rates ---*/ 273 /* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 0 }, 274 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 2 }, 275 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 2 }, 276 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 4 }, 277 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 4 }, 278 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 4 }, 279 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 4 }, 280 /* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 4 }, 281 /*--- HT DS rates ---*/ 282 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 0 }, 283 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 2 }, 284 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 2 }, 285 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 4 }, 286 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 4 }, 287 /* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 4 }, 288 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 4 }, 289 /* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 4 }, 290 /*--- HT TS rates ---*/ 291 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 0 }, 292 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 2 }, 293 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 2 }, 294 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 4 }, 295 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 4 }, 296 /* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 4 }, 297 /*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 4 }, 298 /* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 4 }, 299 }, 300 }; 301 302 #undef OFDM 303 #undef CCK 304 #undef TURBO 305 #undef XR 306 #undef HT 307 #undef HT_HGI 308 309 const HAL_RATE_TABLE * 310 ar9300_get_rate_table(struct ath_hal *ah, u_int mode) 311 { 312 struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 313 HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps; 314 HAL_RATE_TABLE *rt; 315 316 switch (mode) { 317 case HAL_MODE_11A: 318 rt = &ar9300_11a_table; 319 break; 320 case HAL_MODE_11A_HALF_RATE: 321 if (p_cap->halChanHalfRate) { 322 rt = &ar9300_11a_half_table; 323 break; 324 } 325 return AH_NULL; 326 case HAL_MODE_11A_QUARTER_RATE: 327 if (p_cap->halChanQuarterRate) { 328 rt = &ar9300_11a_quarter_table; 329 break; 330 } 331 return AH_NULL; 332 case HAL_MODE_11B: 333 rt = &ar9300_11b_table; 334 break; 335 case HAL_MODE_11G: 336 rt = &ar9300_11g_table; 337 break; 338 case HAL_MODE_TURBO: 339 case HAL_MODE_108G: 340 rt = &ar9300_turbo_table; 341 break; 342 #if 0 343 case HAL_MODE_XR: 344 rt = &ar9300_xr_table; 345 break; 346 #endif 347 case HAL_MODE_11NG_HT20: 348 case HAL_MODE_11NG_HT40PLUS: 349 case HAL_MODE_11NG_HT40MINUS: 350 rt = &ar9300_11ng_table; 351 break; 352 case HAL_MODE_11NA_HT20: 353 case HAL_MODE_11NA_HT40PLUS: 354 case HAL_MODE_11NA_HT40MINUS: 355 rt = &ar9300_11na_table; 356 break; 357 default: 358 HALDEBUG(ah, HAL_DEBUG_CHANNEL, 359 "%s: invalid mode 0x%x\n", __func__, mode); 360 return AH_NULL; 361 } 362 ath_hal_setupratetable(ah, rt); 363 return rt; 364 } 365 366 static HAL_BOOL 367 ar9300_invalid_stbc_cfg(int tx_chains, u_int8_t rate_code) 368 { 369 switch (tx_chains) { 370 case 0: /* Single Chain */ 371 return AH_TRUE; 372 373 case 1: /* 2 Chains */ 374 if ((rate_code < 0x80) || (rate_code > 0x87)) { 375 return AH_TRUE; 376 } else { 377 return AH_FALSE; 378 } 379 380 case 2: /* 3 Chains */ 381 if ((rate_code < 0x80) || (rate_code > 0x87)) { 382 return AH_TRUE; 383 } else { 384 return AH_FALSE; 385 } 386 387 default: 388 HALASSERT(0); 389 break; 390 } 391 392 return AH_TRUE; 393 } 394 395 int16_t 396 ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index, 397 u_int8_t chainmask, u_int8_t xmit_mode) 398 { 399 struct ath_hal_9300 *ahp = AH9300(ah); 400 int num_chains = ar9300_get_ntxchains(chainmask); 401 402 switch (xmit_mode) { 403 case AR9300_DEF_MODE: 404 return ahp->txpower[rate_index][num_chains-1]; 405 406 407 case AR9300_STBC_MODE: 408 return ahp->txpower_stbc[rate_index][num_chains-1]; 409 410 default: 411 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n", 412 __func__, xmit_mode); 413 HALASSERT(0); 414 break; 415 } 416 417 return ahp->txpower[rate_index][num_chains-1]; 418 } 419 420 extern void 421 ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, 422 u_int8_t power_per_rate[]) 423 424 { 425 struct ath_hal_9300 *ahp = AH9300(ah); 426 int16_t twice_array_gain, cdd_power = 0; 427 int i; 428 429 /* 430 * Adjust the upper limit for CDD factoring in the array gain . 431 * The array gain is the same as TxBF, hence reuse the same defines. 432 */ 433 switch (ahp->ah_tx_chainmask) { 434 435 case OSPREY_1_CHAINMASK: 436 cdd_power = ahp->upper_limit[0]; 437 break; 438 439 case OSPREY_2LOHI_CHAINMASK: 440 case OSPREY_2LOMID_CHAINMASK: 441 twice_array_gain = 442 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 443 -(AR9300_TXBF_2TX_ARRAY_GAIN) : 444 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 445 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); 446 cdd_power = ahp->upper_limit[1] + twice_array_gain; 447 448 HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 2 chain; cdd_power=%d", __func__, cdd_power); 449 /* Adjust OFDM legacy rates as well */ 450 for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { 451 if (power_per_rate[i] > cdd_power) { 452 power_per_rate[i] = cdd_power; 453 } 454 } 455 456 /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 20*/ 457 for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_7; i++) { 458 if (power_per_rate[i] > cdd_power) { 459 power_per_rate[i] = cdd_power; 460 } 461 } 462 463 /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 40*/ 464 for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_7; i++) { 465 if (power_per_rate[i] > cdd_power) { 466 power_per_rate[i] = cdd_power; 467 } 468 } 469 break; 470 471 case OSPREY_3_CHAINMASK: 472 twice_array_gain = 473 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 474 -(AR9300_TXBF_3TX_ARRAY_GAIN) : 475 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 476 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); 477 cdd_power = ahp->upper_limit[2] + twice_array_gain; 478 HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 3 chain; cdd_power=%d", __func__, cdd_power); 479 /* Adjust OFDM legacy rates as well */ 480 for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { 481 if (power_per_rate[i] > cdd_power) { 482 power_per_rate[i] = cdd_power; 483 } 484 } 485 /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT20 */ 486 for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_15; i++) { 487 if (power_per_rate[i] > cdd_power) { 488 power_per_rate[i] = cdd_power; 489 } 490 } 491 492 /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT40 */ 493 for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_15; i++) { 494 if (power_per_rate[i] > cdd_power) { 495 power_per_rate[i] = cdd_power; 496 } 497 } 498 499 break; 500 501 default: 502 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 503 __func__, ahp->ah_tx_chainmask); 504 break; 505 } 506 507 return; 508 } 509 510 extern void 511 ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, 512 const struct ieee80211_channel *chan, 513 u_int8_t power_per_rate[], u_int8_t chainmask) 514 { 515 const HAL_RATE_TABLE *rt; 516 HAL_BOOL is40 = IEEE80211_IS_CHAN_HT40(chan); 517 518 rt = ar9300_get_rate_table(ah, mode); 519 HALASSERT(rt != NULL); 520 521 switch (mode) { 522 case HAL_MODE_11A: 523 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate, 524 AR9300_11A_RT_OFDM_OFFSET, chainmask); 525 break; 526 case HAL_MODE_11NA_HT20: 527 case HAL_MODE_11NA_HT40PLUS: 528 case HAL_MODE_11NA_HT40MINUS: 529 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate, 530 AR9300_11NA_RT_OFDM_OFFSET, chainmask); 531 ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate, 532 AR9300_11NA_RT_HT_SS_OFFSET, 533 AR9300_11NA_RT_HT_DS_OFFSET, 534 AR9300_11NA_RT_HT_TS_OFFSET, chainmask); 535 ar9300_init_rate_txpower_stbc(ah, rt, is40, 536 AR9300_11NA_RT_HT_SS_OFFSET, 537 AR9300_11NA_RT_HT_DS_OFFSET, 538 AR9300_11NA_RT_HT_TS_OFFSET, chainmask); 539 #if 0 540 /* For FCC the array gain has to be factored for CDD mode */ 541 if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) { 542 ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 543 AR9300_11NA_RT_HT_SS_OFFSET, 544 AR9300_11NA_RT_HT_DS_OFFSET, 545 AR9300_11NA_RT_HT_TS_OFFSET, chainmask); 546 } 547 #endif 548 break; 549 case HAL_MODE_11G: 550 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask); 551 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate, 552 AR9300_11G_RT_OFDM_OFFSET, chainmask); 553 break; 554 case HAL_MODE_11B: 555 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask); 556 break; 557 case HAL_MODE_11NG_HT20: 558 case HAL_MODE_11NG_HT40PLUS: 559 case HAL_MODE_11NG_HT40MINUS: 560 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask); 561 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate, 562 AR9300_11NG_RT_OFDM_OFFSET, chainmask); 563 ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate, 564 AR9300_11NG_RT_HT_SS_OFFSET, 565 AR9300_11NG_RT_HT_DS_OFFSET, 566 AR9300_11NG_RT_HT_TS_OFFSET, chainmask); 567 ar9300_init_rate_txpower_stbc(ah, rt, is40, 568 AR9300_11NG_RT_HT_SS_OFFSET, 569 AR9300_11NG_RT_HT_DS_OFFSET, 570 AR9300_11NG_RT_HT_TS_OFFSET, chainmask); 571 #if 0 572 /* For FCC the array gain needs to be factored for CDD mode */ 573 if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) { 574 ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 575 AR9300_11NG_RT_HT_SS_OFFSET, 576 AR9300_11NG_RT_HT_DS_OFFSET, 577 AR9300_11NG_RT_HT_TS_OFFSET, chainmask); 578 } 579 #endif 580 break; 581 default: 582 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n", 583 __func__, mode); 584 HALASSERT(0); 585 break; 586 } 587 588 } 589 590 static inline void 591 ar9300_init_rate_txpower_cck(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 592 u_int8_t rates_array[], u_int8_t chainmask) 593 { 594 struct ath_hal_9300 *ahp = AH9300(ah); 595 /* 596 * Pick the lower of the long-preamble txpower, and short-preamble tx power. 597 * Unfortunately, the rate table doesn't have separate entries for these!. 598 */ 599 switch (chainmask) { 600 case OSPREY_1_CHAINMASK: 601 ahp->txpower[0][0] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 602 ahp->txpower[1][0] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 603 ahp->txpower[2][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], 604 rates_array[ALL_TARGET_LEGACY_5S]); 605 ahp->txpower[3][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], 606 rates_array[ALL_TARGET_LEGACY_11S]); 607 break; 608 case OSPREY_2LOHI_CHAINMASK: 609 case OSPREY_2LOMID_CHAINMASK: 610 ahp->txpower[0][1] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 611 ahp->txpower[1][1] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 612 ahp->txpower[2][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], 613 rates_array[ALL_TARGET_LEGACY_5S]); 614 ahp->txpower[3][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], 615 rates_array[ALL_TARGET_LEGACY_11S]); 616 break; 617 case OSPREY_3_CHAINMASK: 618 ahp->txpower[0][2] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 619 ahp->txpower[1][2] = rates_array[ALL_TARGET_LEGACY_1L_5L]; 620 ahp->txpower[2][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L], 621 rates_array[ALL_TARGET_LEGACY_5S]); 622 ahp->txpower[3][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L], 623 rates_array[ALL_TARGET_LEGACY_11S]); 624 break; 625 default: 626 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 627 __func__, chainmask); 628 break; 629 } 630 } 631 632 static inline void 633 ar9300_init_rate_txpower_ofdm(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 634 u_int8_t rates_array[], int rt_offset, 635 u_int8_t chainmask) 636 { 637 struct ath_hal_9300 *ahp = AH9300(ah); 638 int16_t twice_array_gain, cdd_power = 0; 639 int i, j; 640 u_int8_t ofdm_rt_2_pwr_idx[8] = 641 { 642 ALL_TARGET_LEGACY_6_24, 643 ALL_TARGET_LEGACY_6_24, 644 ALL_TARGET_LEGACY_6_24, 645 ALL_TARGET_LEGACY_6_24, 646 ALL_TARGET_LEGACY_6_24, 647 ALL_TARGET_LEGACY_36, 648 ALL_TARGET_LEGACY_48, 649 ALL_TARGET_LEGACY_54, 650 }; 651 652 /* 653 * For FCC adjust the upper limit for CDD factoring in the array gain. 654 * The array gain is the same as TxBF, hence reuse the same defines. 655 */ 656 for (i = rt_offset; i < rt_offset + AR9300_NUM_OFDM_RATES; i++) { 657 658 /* Get the correct OFDM rate to Power table Index */ 659 j = ofdm_rt_2_pwr_idx[i- rt_offset]; 660 661 switch (chainmask) { 662 case OSPREY_1_CHAINMASK: 663 ahp->txpower[i][0] = rates_array[j]; 664 break; 665 case OSPREY_2LOHI_CHAINMASK: 666 case OSPREY_2LOMID_CHAINMASK: 667 ahp->txpower[i][1] = rates_array[j]; 668 if (is_reg_dmn_fcc(ahp->reg_dmn)){ 669 twice_array_gain = (ahp->twice_antenna_gain >= 670 ahp->twice_antenna_reduction)? 671 -(AR9300_TXBF_2TX_ARRAY_GAIN) : 672 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 673 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); 674 cdd_power = ahp->upper_limit[1] + twice_array_gain; 675 if (ahp->txpower[i][1] > cdd_power){ 676 ahp->txpower[i][1] = cdd_power; 677 } 678 } 679 break; 680 case OSPREY_3_CHAINMASK: 681 ahp->txpower[i][2] = rates_array[j]; 682 if (is_reg_dmn_fcc(ahp->reg_dmn)) { 683 twice_array_gain = 684 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 685 -(AR9300_TXBF_3TX_ARRAY_GAIN): 686 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 687 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); 688 cdd_power = ahp->upper_limit[2] + twice_array_gain; 689 if (ahp->txpower[i][2] > cdd_power){ 690 ahp->txpower[i][2] = cdd_power; 691 } 692 } 693 break; 694 default: 695 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 696 __func__, chainmask); 697 break; 698 } 699 } 700 } 701 702 static u_int8_t mcs_rate_2_pwr_idx_ht20[24] = 703 { 704 ALL_TARGET_HT20_0_8_16, 705 ALL_TARGET_HT20_1_3_9_11_17_19, 706 ALL_TARGET_HT20_1_3_9_11_17_19, 707 ALL_TARGET_HT20_1_3_9_11_17_19, 708 ALL_TARGET_HT20_4, 709 ALL_TARGET_HT20_5, 710 ALL_TARGET_HT20_6, 711 ALL_TARGET_HT20_7, 712 ALL_TARGET_HT20_0_8_16, 713 ALL_TARGET_HT20_1_3_9_11_17_19, 714 ALL_TARGET_HT20_1_3_9_11_17_19, 715 ALL_TARGET_HT20_1_3_9_11_17_19, 716 ALL_TARGET_HT20_12, 717 ALL_TARGET_HT20_13, 718 ALL_TARGET_HT20_14, 719 ALL_TARGET_HT20_15, 720 ALL_TARGET_HT20_0_8_16, 721 ALL_TARGET_HT20_1_3_9_11_17_19, 722 ALL_TARGET_HT20_1_3_9_11_17_19, 723 ALL_TARGET_HT20_1_3_9_11_17_19, 724 ALL_TARGET_HT20_20, 725 ALL_TARGET_HT20_21, 726 ALL_TARGET_HT20_22, 727 ALL_TARGET_HT20_23 728 }; 729 730 static u_int8_t mcs_rate_2_pwr_idx_ht40[24] = 731 { 732 ALL_TARGET_HT40_0_8_16, 733 ALL_TARGET_HT40_1_3_9_11_17_19, 734 ALL_TARGET_HT40_1_3_9_11_17_19, 735 ALL_TARGET_HT40_1_3_9_11_17_19, 736 ALL_TARGET_HT40_4, 737 ALL_TARGET_HT40_5, 738 ALL_TARGET_HT40_6, 739 ALL_TARGET_HT40_7, 740 ALL_TARGET_HT40_0_8_16, 741 ALL_TARGET_HT40_1_3_9_11_17_19, 742 ALL_TARGET_HT40_1_3_9_11_17_19, 743 ALL_TARGET_HT40_1_3_9_11_17_19, 744 ALL_TARGET_HT40_12, 745 ALL_TARGET_HT40_13, 746 ALL_TARGET_HT40_14, 747 ALL_TARGET_HT40_15, 748 ALL_TARGET_HT40_0_8_16, 749 ALL_TARGET_HT40_1_3_9_11_17_19, 750 ALL_TARGET_HT40_1_3_9_11_17_19, 751 ALL_TARGET_HT40_1_3_9_11_17_19, 752 ALL_TARGET_HT40_20, 753 ALL_TARGET_HT40_21, 754 ALL_TARGET_HT40_22, 755 ALL_TARGET_HT40_23, 756 }; 757 758 static inline void 759 ar9300_init_rate_txpower_ht(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 760 HAL_BOOL is40, 761 u_int8_t rates_array[], 762 int rt_ss_offset, int rt_ds_offset, 763 int rt_ts_offset, u_int8_t chainmask) 764 { 765 766 struct ath_hal_9300 *ahp = AH9300(ah); 767 int i, j; 768 u_int8_t mcs_index = 0; 769 770 771 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) { 772 /* Get the correct MCS rate to Power table Index */ 773 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] : 774 mcs_rate_2_pwr_idx_ht20[mcs_index]; 775 switch (chainmask) { 776 case OSPREY_1_CHAINMASK: 777 ahp->txpower[i][0] = rates_array[j]; 778 break; 779 case OSPREY_2LOHI_CHAINMASK: 780 case OSPREY_2LOMID_CHAINMASK: 781 ahp->txpower[i][1] = rates_array[j]; 782 break; 783 case OSPREY_3_CHAINMASK: 784 ahp->txpower[i][2] = rates_array[j]; 785 break; 786 default: 787 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 788 __func__, chainmask); 789 break; 790 } 791 mcs_index++; 792 } 793 794 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) { 795 /* Get the correct MCS rate to Power table Index */ 796 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] : 797 mcs_rate_2_pwr_idx_ht20[mcs_index]; 798 switch (chainmask) { 799 case OSPREY_1_CHAINMASK: 800 ahp->txpower[i][0] = rates_array[j]; 801 break; 802 case OSPREY_2LOHI_CHAINMASK: 803 case OSPREY_2LOMID_CHAINMASK: 804 ahp->txpower[i][1] = rates_array[j]; 805 break; 806 case OSPREY_3_CHAINMASK: 807 ahp->txpower[i][2] = rates_array[j]; 808 break; 809 default: 810 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 811 __func__, chainmask); 812 break; 813 } 814 mcs_index++; 815 } 816 817 for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) { 818 /* Get the correct MCS rate to Power table Index */ 819 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] : 820 mcs_rate_2_pwr_idx_ht20[mcs_index]; 821 switch (chainmask) { 822 case OSPREY_1_CHAINMASK: 823 ahp->txpower[i][0] = rates_array[j]; 824 break; 825 case OSPREY_2LOHI_CHAINMASK: 826 case OSPREY_2LOMID_CHAINMASK: 827 ahp->txpower[i][1] = rates_array[j]; 828 break; 829 case OSPREY_3_CHAINMASK: 830 ahp->txpower[i][2] = rates_array[j]; 831 break; 832 default: 833 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 834 __func__, chainmask); 835 break; 836 } 837 mcs_index++; 838 } 839 } 840 841 static inline void 842 ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 843 HAL_BOOL is40, 844 int rt_ss_offset, int rt_ds_offset, 845 int rt_ts_offset, u_int8_t chainmask) 846 { 847 848 struct ath_hal_9300 *ahp = AH9300(ah); 849 int i; 850 int16_t twice_array_gain, stbc_power = 0; 851 u_int8_t mcs_index = 0; 852 853 /* Upper Limit with STBC */ 854 switch (chainmask) { 855 case OSPREY_1_CHAINMASK: 856 stbc_power = ahp->upper_limit[0]; 857 break; 858 case OSPREY_2LOHI_CHAINMASK: 859 case OSPREY_2LOMID_CHAINMASK: 860 stbc_power = ahp->upper_limit[1]; 861 break; 862 case OSPREY_3_CHAINMASK: 863 stbc_power = ahp->upper_limit[2]; 864 /* Ony FCC requires that we back off with 3 transmit chains */ 865 if (is_reg_dmn_fcc(ahp->reg_dmn)) { 866 twice_array_gain = 867 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 868 -(AR9300_STBC_3TX_ARRAY_GAIN) : 869 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 870 (ahp->twice_antenna_gain + AR9300_STBC_3TX_ARRAY_GAIN)), 0)); 871 stbc_power = ahp->upper_limit[2] + twice_array_gain; 872 } 873 break; 874 875 default: 876 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 877 __func__, chainmask); 878 break; 879 } 880 881 882 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) { 883 switch (chainmask) { 884 case OSPREY_1_CHAINMASK: 885 ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; 886 break; 887 case OSPREY_2LOHI_CHAINMASK: 888 case OSPREY_2LOMID_CHAINMASK: 889 ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; 890 break; 891 case OSPREY_3_CHAINMASK: 892 ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; 893 /* 3 TX/1 stream STBC gain adjustment */ 894 if (ahp->txpower_stbc[i][2] > stbc_power){ 895 ahp->txpower_stbc[i][2] = stbc_power; 896 } 897 break; 898 default: 899 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 900 __func__, chainmask); 901 break; 902 } 903 mcs_index++; 904 } 905 906 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) { 907 switch (chainmask) { 908 case OSPREY_1_CHAINMASK: 909 ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; 910 break; 911 case OSPREY_2LOHI_CHAINMASK: 912 case OSPREY_2LOMID_CHAINMASK: 913 ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; 914 break; 915 case OSPREY_3_CHAINMASK: 916 ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; 917 /* 3 TX/2 stream STBC gain adjustment */ 918 if (ahp->txpower_stbc[i][2] > stbc_power){ 919 ahp->txpower_stbc[i][2] = stbc_power; 920 } 921 break; 922 default: 923 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 924 __func__, chainmask); 925 break; 926 } 927 mcs_index++; 928 } 929 930 for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) { 931 switch (chainmask) { 932 case OSPREY_1_CHAINMASK: 933 ahp->txpower_stbc[i][0] = ahp->txpower[i][0]; 934 break; 935 case OSPREY_2LOHI_CHAINMASK: 936 case OSPREY_2LOMID_CHAINMASK: 937 ahp->txpower_stbc[i][1] = ahp->txpower[i][1]; 938 break; 939 case OSPREY_3_CHAINMASK: 940 ahp->txpower_stbc[i][2] = ahp->txpower[i][2]; 941 break; 942 default: 943 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 944 __func__, chainmask); 945 break; 946 } 947 mcs_index++; 948 } 949 950 return; 951 } 952 953 /* 954 * To see why this is disabled, look at ar9300_eeprom.c for FCC/OET 13TR1003. 955 */ 956 #if 0 957 static inline void 958 ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 959 HAL_BOOL is40, 960 int rt_ss_offset, int rt_ds_offset, 961 int rt_ts_offset, u_int8_t chainmask) 962 { 963 964 struct ath_hal_9300 *ahp = AH9300(ah); 965 int i; 966 int16_t twice_array_gain, cdd_power = 0; 967 u_int8_t mcs_index = 0; 968 969 /* 970 * Adjust the upper limit for CDD factoring in the array gain . 971 * The array gain is the same as TxBF, hence reuse the same defines. 972 */ 973 switch (chainmask) { 974 case OSPREY_1_CHAINMASK: 975 cdd_power = ahp->upper_limit[0]; 976 break; 977 978 case OSPREY_2LOHI_CHAINMASK: 979 case OSPREY_2LOMID_CHAINMASK: 980 twice_array_gain = 981 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 982 -(AR9300_TXBF_2TX_ARRAY_GAIN) : 983 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 984 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); 985 cdd_power = ahp->upper_limit[1] + twice_array_gain; 986 break; 987 988 case OSPREY_3_CHAINMASK: 989 twice_array_gain = 990 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 991 -(AR9300_TXBF_3TX_ARRAY_GAIN) : 992 ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 993 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); 994 cdd_power = ahp->upper_limit[2] + twice_array_gain; 995 break; 996 997 default: 998 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 999 __func__, chainmask); 1000 break; 1001 } 1002 1003 1004 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) { 1005 switch (chainmask) { 1006 case OSPREY_1_CHAINMASK: 1007 break; 1008 1009 case OSPREY_2LOHI_CHAINMASK: 1010 case OSPREY_2LOMID_CHAINMASK: 1011 /* 2 TX/1 stream CDD gain adjustment */ 1012 if (ahp->txpower[i][1] > cdd_power){ 1013 ahp->txpower[i][1] = cdd_power; 1014 } 1015 break; 1016 case OSPREY_3_CHAINMASK: 1017 /* 3 TX/1 stream CDD gain adjustment */ 1018 if (ahp->txpower[i][2] > cdd_power){ 1019 ahp->txpower[i][2] = cdd_power; 1020 } 1021 break; 1022 default: 1023 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 1024 __func__, chainmask); 1025 break; 1026 } 1027 mcs_index++; 1028 } 1029 1030 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) { 1031 switch (chainmask) { 1032 case OSPREY_1_CHAINMASK: 1033 case OSPREY_2LOHI_CHAINMASK: 1034 case OSPREY_2LOMID_CHAINMASK: 1035 break; 1036 case OSPREY_3_CHAINMASK: 1037 /* 3 TX/2 stream TxBF gain adjustment */ 1038 if (ahp->txpower[i][2] > cdd_power){ 1039 ahp->txpower[i][2] = cdd_power; 1040 } 1041 break; 1042 default: 1043 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n", 1044 __func__, chainmask); 1045 break; 1046 } 1047 mcs_index++; 1048 } 1049 1050 return; 1051 1052 } 1053 #endif 1054 1055 void ar9300_disp_tpc_tables(struct ath_hal *ah) 1056 { 1057 struct ath_hal_9300 *ahp = AH9300(ah); 1058 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 1059 u_int mode = ath_hal_get_curmode(ah, chan); 1060 const HAL_RATE_TABLE *rt; 1061 int i, j; 1062 1063 /* Check whether TPC is enabled */ 1064 if (!ah->ah_config.ath_hal_desc_tpc) { 1065 ath_hal_printf(ah, "\n TPC Register method in use\n"); 1066 return; 1067 } 1068 1069 rt = ar9300_get_rate_table(ah, mode); 1070 HALASSERT(rt != NULL); 1071 1072 ath_hal_printf(ah, "\n===TARGET POWER TABLE===\n"); 1073 for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) { 1074 for (i = 0; i < rt->rateCount; i++) { 1075 int16_t txpower[AR9300_MAX_CHAINS]; 1076 txpower[j] = ahp->txpower[i][j]; 1077 ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps " 1078 "Power (%d Chain) [%2d.%1d dBm]\n", 1079 i, rt->info[i].rateCode, rt->info[i].rateKbps, 1080 j + 1, txpower[j] / 2, txpower[j]%2 * 5); 1081 } 1082 } 1083 ath_hal_printf(ah, "\n"); 1084 1085 ath_hal_printf(ah, "\n\n===TARGET POWER TABLE with STBC===\n"); 1086 for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) { 1087 for (i = 0; i < rt->rateCount; i++) { 1088 int16_t txpower[AR9300_MAX_CHAINS]; 1089 txpower[j] = ahp->txpower_stbc[i][j]; 1090 1091 /* Do not display invalid configurations */ 1092 if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) || 1093 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) || 1094 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) { 1095 continue; 1096 } 1097 1098 ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps " 1099 "Power (%d Chain) [%2d.%1d dBm]\n", 1100 i, rt->info[i].rateCode , rt->info[i].rateKbps, 1101 j + 1, txpower[j] / 2, txpower[j]%2 * 5); 1102 } 1103 } 1104 ath_hal_printf(ah, "\n"); 1105 } 1106 1107 /* 1108 * The followings are customer specific APIs for querying power limit. 1109 * Power limit is based on regulatory domain, chipset, and transmission rate. 1110 * Here we only consider EEPROM values, no array gain/CTL considered here. 1111 */ 1112 1113 struct rate_power_tbl { 1114 u_int8_t rateIdx; /* rate index in the rate table */ 1115 u_int32_t rateKbps; /* transfer rate in kbs */ 1116 u_int8_t rateCode; /* rate for h/w descriptors */ 1117 u_int8_t txbf: 1, /* txbf eligible */ 1118 stbc: 1, /* stbc eligible */ 1119 chain1: 1, /* one-chain eligible */ 1120 chain2: 1, /* two-chain eligible */ 1121 chain3: 1; /* three-chain eligible */ 1122 int16_t txpower[AR9300_MAX_CHAINS]; /* txpower for different chainmasks */ 1123 int16_t txpower_stbc[AR9300_MAX_CHAINS]; 1124 }; 1125 1126 u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah) 1127 { 1128 struct ath_hal_9300 *ahp = AH9300(ah); 1129 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 1130 u_int mode = ath_hal_get_curmode(ah, chan); 1131 const HAL_RATE_TABLE *rt; 1132 u_int8_t *data; 1133 struct rate_power_tbl *table; 1134 int i, j; 1135 1136 /* Check whether TPC is enabled */ 1137 if (! ah->ah_config.ath_hal_desc_tpc) { 1138 ath_hal_printf(ah, "\n TPC Register method in use\n"); 1139 return NULL; 1140 } 1141 1142 rt = (const HAL_RATE_TABLE *)ar9300_get_rate_table(ah, mode); 1143 HALASSERT(rt != NULL); 1144 1145 data = (u_int8_t *)ath_hal_malloc( 1146 1 + rt->rateCount * sizeof(struct rate_power_tbl)); 1147 if (data == NULL) 1148 return NULL; 1149 1150 OS_MEMZERO(data, 1 + rt->rateCount * sizeof(struct rate_power_tbl)); 1151 /* store the rate count at the beginning */ 1152 *data = rt->rateCount; 1153 table = (struct rate_power_tbl *)&data[1]; 1154 1155 for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) { 1156 for (i = 0; i < rt->rateCount; i++) { 1157 table[i].rateIdx = i; 1158 table[i].rateCode = rt->info[i].rateCode; 1159 table[i].rateKbps = rt->info[i].rateKbps; 1160 switch (j) { 1161 case 0: 1162 table[i].chain1 = rt->info[i].rateCode <= 0x87 ? 1 : 0; 1163 break; 1164 case 1: 1165 table[i].chain2 = rt->info[i].rateCode <= 0x8f ? 1 : 0; 1166 break; 1167 case 2: 1168 table[i].chain3 = 1; 1169 break; 1170 default: 1171 break; 1172 } 1173 if ((j == 0 && table[i].chain1) || 1174 (j == 1 && table[i].chain2) || 1175 (j == 2 && table[i].chain3)) 1176 table[i].txpower[j] = ahp->txpower[i][j]; 1177 } 1178 } 1179 1180 for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) { 1181 for (i = 0; i < rt->rateCount; i++) { 1182 /* Do not display invalid configurations */ 1183 if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) || 1184 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) || 1185 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) { 1186 continue; 1187 } 1188 1189 table[i].stbc = 1; 1190 table[i].txpower_stbc[j] = ahp->txpower_stbc[i][j]; 1191 } 1192 } 1193 1194 return data; 1195 /* the caller is responsible to free data */ 1196 } 1197 1198 HAL_STATUS 1199 ath_hal_get_rate_power_limit_from_eeprom(struct ath_hal *ah, u_int16_t freq, 1200 int8_t *max_rate_power, int8_t *min_rate_power) 1201 { 1202 /* 1203 * Used for AR9300 series chip only 1204 */ 1205 if (ah->ah_magic == AR9300_MAGIC) { 1206 u_int8_t target_rate_power_limit_val_t2[ar9300_rate_size]; 1207 int i; 1208 1209 *max_rate_power = 0; 1210 *min_rate_power = AR9300_MAX_RATE_POWER; 1211 1212 ar9300_set_target_power_from_eeprom(ah, freq, target_rate_power_limit_val_t2); 1213 1214 for (i=0; i<ar9300_rate_size; i++) { 1215 if (target_rate_power_limit_val_t2[i] > *max_rate_power) 1216 *max_rate_power = target_rate_power_limit_val_t2[i]; 1217 if (target_rate_power_limit_val_t2[i] < *min_rate_power) 1218 *min_rate_power = target_rate_power_limit_val_t2[i]; 1219 } 1220 } else { 1221 *max_rate_power = 0; 1222 *min_rate_power = 0; 1223 } 1224 1225 return HAL_OK; 1226 } 1227