2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
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.
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.
20 #include "ah_internal.h"
22 #include "ar9300/ar9300.h"
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
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
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 */
41 /* MCS RATE CODES - first and last */
42 #define AR9300_MCS0_RATE_CODE 0x80
43 #define AR9300_MCS23_RATE_CODE 0x97
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,
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 static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah,
59 const HAL_RATE_TABLE *rt, HAL_BOOL is40,
60 int rt_ss_offset, int rt_ds_offset,
61 int rt_ts_offset, u_int8_t chainmask);
63 #define AR9300_11A_RT_OFDM_OFFSET 0
64 HAL_RATE_TABLE ar9300_11a_table = {
65 8, /* number of rates */
69 /* valid rate_code Preamble dot11Rate Rate */
70 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 },
71 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 },
72 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 },
73 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 },
74 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 },
75 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 },
76 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 },
77 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 },
81 HAL_RATE_TABLE ar9300_11a_half_table = {
82 8, /* number of rates */
86 /* valid rate_code Preamble dot11Rate Rate */
87 /* 6 Mb */ { AH_TRUE, OFDM, 3000, 0x0b, 0x00, (0x80 | 6), 0 },
88 /* 9 Mb */ { AH_TRUE, OFDM, 4500, 0x0f, 0x00, 9, 0 },
89 /* 12 Mb */ { AH_TRUE, OFDM, 6000, 0x0a, 0x00, (0x80 | 12), 2 },
90 /* 18 Mb */ { AH_TRUE, OFDM, 9000, 0x0e, 0x00, 18, 2 },
91 /* 24 Mb */ { AH_TRUE, OFDM, 12000, 0x09, 0x00, (0x80 | 24), 4 },
92 /* 36 Mb */ { AH_TRUE, OFDM, 18000, 0x0d, 0x00, 36, 4 },
93 /* 48 Mb */ { AH_TRUE, OFDM, 24000, 0x08, 0x00, 48, 4 },
94 /* 54 Mb */ { AH_TRUE, OFDM, 27000, 0x0c, 0x00, 54, 4 },
98 HAL_RATE_TABLE ar9300_11a_quarter_table = {
99 8, /* number of rates */
103 /* valid rate_code Preamble dot11Rate Rate */
104 /* 6 Mb */ { AH_TRUE, OFDM, 1500, 0x0b, 0x00, (0x80 | 3), 0 },
105 /* 9 Mb */ { AH_TRUE, OFDM, 2250, 0x0f, 0x00, 4 , 0 },
106 /* 12 Mb */ { AH_TRUE, OFDM, 3000, 0x0a, 0x00, (0x80 | 6), 2 },
107 /* 18 Mb */ { AH_TRUE, OFDM, 4500, 0x0e, 0x00, 9, 2 },
108 /* 24 Mb */ { AH_TRUE, OFDM, 6000, 0x09, 0x00, (0x80 | 12), 4 },
109 /* 36 Mb */ { AH_TRUE, OFDM, 9000, 0x0d, 0x00, 18, 4 },
110 /* 48 Mb */ { AH_TRUE, OFDM, 12000, 0x08, 0x00, 24, 4 },
111 /* 54 Mb */ { AH_TRUE, OFDM, 13500, 0x0c, 0x00, 27, 4 },
115 HAL_RATE_TABLE ar9300_turbo_table = {
116 8, /* number of rates */
120 /* valid rate_code Preamble dot11Rate Rate */
121 /* 6 Mb */ { AH_TRUE, TURBO, 6000, 0x0b, 0x00, (0x80 | 12), 0 },
122 /* 9 Mb */ { AH_TRUE, TURBO, 9000, 0x0f, 0x00, 18, 0 },
123 /* 12 Mb */ { AH_TRUE, TURBO, 12000, 0x0a, 0x00, (0x80 | 24), 2 },
124 /* 18 Mb */ { AH_TRUE, TURBO, 18000, 0x0e, 0x00, 36, 2 },
125 /* 24 Mb */ { AH_TRUE, TURBO, 24000, 0x09, 0x00, (0x80 | 48), 4 },
126 /* 36 Mb */ { AH_TRUE, TURBO, 36000, 0x0d, 0x00, 72, 4 },
127 /* 48 Mb */ { AH_TRUE, TURBO, 48000, 0x08, 0x00, 96, 4 },
128 /* 54 Mb */ { AH_TRUE, TURBO, 54000, 0x0c, 0x00, 108, 4 },
132 HAL_RATE_TABLE ar9300_11b_table = {
133 4, /* number of rates */
137 /* valid rate_code Preamble dot11Rate Rate */
138 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },
139 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },
140 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 1 },
141 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 1 },
146 /* Venice TODO: round_up_rate() is broken when the rate table does not represent
147 * rates in increasing order e.g. 5.5, 11, 6, 9.
148 * An average rate of 6 Mbps will currently map to 11 Mbps.
150 #define AR9300_11G_RT_OFDM_OFFSET 4
151 HAL_RATE_TABLE ar9300_11g_table = {
152 12, /* number of rates */
156 /* valid rate_code Preamble dot11Rate Rate */
157 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },
158 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },
159 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 },
160 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 },
161 /* Hardware workaround - remove rates 6, 9 from rate ctrl */
162 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, 12, 4 },
163 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4 },
164 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 },
165 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 },
166 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 },
167 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 },
168 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 },
169 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 },
174 HAL_RATE_TABLE ar9300_xr_table = {
175 13, /* number of rates */
179 /* valid rate_code Preamble dot11Rate Rate */
180 /* 0.25 Mb */ {AH_TRUE, XR, 250, 0x03, 0x00, (0x80 | 1), 0, 612, 612 },
181 /* 0.5 Mb */ {AH_TRUE, XR, 500, 0x07, 0x00, (0x80 | 1), 0, 457, 457 },
182 /* 1 Mb */ {AH_TRUE, XR, 1000, 0x02, 0x00, (0x80 | 2), 1, 228, 228 },
183 /* 2 Mb */ {AH_TRUE, XR, 2000, 0x06, 0x00, (0x80 | 4), 2, 160, 160 },
184 /* 3 Mb */ {AH_TRUE, XR, 3000, 0x01, 0x00, (0x80 | 6), 3, 140, 140 },
185 /* 6 Mb */ {AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 4, 60, 60 },
186 /* 9 Mb */ {AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 4, 60, 60 },
187 /* 12 Mb */ {AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 6, 48, 48 },
188 /* 18 Mb */ {AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6, 48, 48 },
189 /* 24 Mb */ {AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8, 44, 44 },
190 /* 36 Mb */ {AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8, 44, 44 },
191 /* 48 Mb */ {AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8, 44, 44 },
192 /* 54 Mb */ {AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8, 44, 44 },
197 #define AR9300_11NG_RT_OFDM_OFFSET 4
198 #define AR9300_11NG_RT_HT_SS_OFFSET 12
199 #define AR9300_11NG_RT_HT_DS_OFFSET 20
200 #define AR9300_11NG_RT_HT_TS_OFFSET 28
201 HAL_RATE_TABLE ar9300_11ng_table = {
203 36, /* number of rates */
207 /* valid rate_code Preamble dot11Rate Rate */
208 /* 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0 },
209 /* 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1 },
210 /* 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80 | 11), 2 },
211 /* 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80 | 22), 3 },
212 /* Hardware workaround - remove rates 6, 9 from rate ctrl */
213 /* 6 Mb */ { AH_FALSE, OFDM, 6000, 0x0b, 0x00, 12, 4 },
214 /* 9 Mb */ { AH_FALSE, OFDM, 9000, 0x0f, 0x00, 18, 4 },
215 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, 24, 6 },
216 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 6 },
217 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, 48, 8 },
218 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 8 },
219 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 8 },
220 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 8 },
221 /*--- HT SS rates ---*/
222 /* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 4 },
223 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 6 },
224 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 6 },
225 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 },
226 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 8 },
227 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 8 },
228 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 8 },
229 /* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 8 },
230 /*--- HT DS rates ---*/
231 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 4 },
232 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 6 },
233 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 6 },
234 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 8 },
235 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 8 },
236 /* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 8 },
237 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 8 },
238 /* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 8 },
239 /*--- HT TS rates ---*/
240 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 4 },
241 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 6 },
242 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 6 },
243 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 8 },
244 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 8 },
245 /* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 8 },
246 /*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 8 },
247 /* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 8 },
251 #define AR9300_11NA_RT_OFDM_OFFSET 0
252 #define AR9300_11NA_RT_HT_SS_OFFSET 8
253 #define AR9300_11NA_RT_HT_DS_OFFSET 16
254 #define AR9300_11NA_RT_HT_TS_OFFSET 24
255 static HAL_RATE_TABLE ar9300_11na_table = {
257 32, /* number of rates */
261 /* valid rate_code Preamble dot11Rate Rate */
262 /* 6 Mb */ { AH_TRUE, OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0 },
263 /* 9 Mb */ { AH_TRUE, OFDM, 9000, 0x0f, 0x00, 18, 0 },
264 /* 12 Mb */ { AH_TRUE, OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2 },
265 /* 18 Mb */ { AH_TRUE, OFDM, 18000, 0x0e, 0x00, 36, 2 },
266 /* 24 Mb */ { AH_TRUE, OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4 },
267 /* 36 Mb */ { AH_TRUE, OFDM, 36000, 0x0d, 0x00, 72, 4 },
268 /* 48 Mb */ { AH_TRUE, OFDM, 48000, 0x08, 0x00, 96, 4 },
269 /* 54 Mb */ { AH_TRUE, OFDM, 54000, 0x0c, 0x00, 108, 4 },
270 /*--- HT SS rates ---*/
271 /* 6.5 Mb */ { AH_TRUE, HT, 6500, 0x80, 0x00, 0, 0 },
272 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x81, 0x00, 1, 2 },
273 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x82, 0x00, 2, 2 },
274 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 4 },
275 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x84, 0x00, 4, 4 },
276 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x85, 0x00, 5, 4 },
277 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x86, 0x00, 6, 4 },
278 /* 65 Mb */ { AH_TRUE, HT, 65000, 0x87, 0x00, 7, 4 },
279 /*--- HT DS rates ---*/
280 /* 13 Mb */ { AH_TRUE, HT, 13000, 0x88, 0x00, 8, 0 },
281 /* 26 Mb */ { AH_TRUE, HT, 26000, 0x89, 0x00, 9, 2 },
282 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x8a, 0x00, 10, 2 },
283 /* 52 Mb */ { AH_TRUE, HT, 52000, 0x8b, 0x00, 11, 4 },
284 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x8c, 0x00, 12, 4 },
285 /* 104 Mb */ { AH_TRUE, HT, 104000, 0x8d, 0x00, 13, 4 },
286 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x8e, 0x00, 14, 4 },
287 /* 130 Mb */ { AH_TRUE, HT, 130000, 0x8f, 0x00, 15, 4 },
288 /*--- HT TS rates ---*/
289 /*19.5 Mb */ { AH_TRUE, HT, 19500, 0x90, 0x00, 16, 0 },
290 /* 39 Mb */ { AH_TRUE, HT, 39000, 0x91, 0x00, 17, 2 },
291 /*58.5 Mb */ { AH_TRUE, HT, 58500, 0x92, 0x00, 18, 2 },
292 /* 78 Mb */ { AH_TRUE, HT, 78000, 0x93, 0x00, 19, 4 },
293 /* 117 Mb */ { AH_TRUE, HT, 117000, 0x94, 0x00, 20, 4 },
294 /* 156 Mb */ { AH_TRUE, HT, 156000, 0x95, 0x00, 21, 4 },
295 /*175.5Mb */ { AH_TRUE, HT, 175500, 0x96, 0x00, 22, 4 },
296 /* 195 Mb */ { AH_TRUE, HT, 195000, 0x97, 0x00, 23, 4 },
307 const HAL_RATE_TABLE *
308 ar9300_get_rate_table(struct ath_hal *ah, u_int mode)
310 struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
311 HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps;
316 rt = &ar9300_11a_table;
318 case HAL_MODE_11A_HALF_RATE:
319 if (p_cap->halChanHalfRate) {
320 rt = &ar9300_11a_half_table;
324 case HAL_MODE_11A_QUARTER_RATE:
325 if (p_cap->halChanQuarterRate) {
326 rt = &ar9300_11a_quarter_table;
331 rt = &ar9300_11b_table;
334 rt = &ar9300_11g_table;
338 rt = &ar9300_turbo_table;
342 rt = &ar9300_xr_table;
345 case HAL_MODE_11NG_HT20:
346 case HAL_MODE_11NG_HT40PLUS:
347 case HAL_MODE_11NG_HT40MINUS:
348 rt = &ar9300_11ng_table;
350 case HAL_MODE_11NA_HT20:
351 case HAL_MODE_11NA_HT40PLUS:
352 case HAL_MODE_11NA_HT40MINUS:
353 rt = &ar9300_11na_table;
356 HALDEBUG(ah, HAL_DEBUG_CHANNEL,
357 "%s: invalid mode 0x%x\n", __func__, mode);
360 ath_hal_setupratetable(ah, rt);
365 ar9300_invalid_stbc_cfg(int tx_chains, u_int8_t rate_code)
368 case 0: /* Single Chain */
371 case 1: /* 2 Chains */
372 if ((rate_code < 0x80) || (rate_code > 0x87)) {
378 case 2: /* 3 Chains */
379 if ((rate_code < 0x80) || (rate_code > 0x87)) {
394 ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index,
395 u_int8_t chainmask, u_int8_t xmit_mode)
397 struct ath_hal_9300 *ahp = AH9300(ah);
398 int num_chains = ar9300_get_ntxchains(chainmask);
401 case AR9300_DEF_MODE:
402 return ahp->txpower[rate_index][num_chains-1];
405 case AR9300_STBC_MODE:
406 return ahp->txpower_stbc[rate_index][num_chains-1];
409 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",
410 __func__, xmit_mode);
415 return ahp->txpower[rate_index][num_chains-1];
419 ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah,
420 u_int8_t power_per_rate[])
423 struct ath_hal_9300 *ahp = AH9300(ah);
424 int16_t twice_array_gain, cdd_power = 0;
428 * Adjust the upper limit for CDD factoring in the array gain .
429 * The array gain is the same as TxBF, hence reuse the same defines.
431 switch (ahp->ah_tx_chainmask) {
433 case OSPREY_1_CHAINMASK:
434 cdd_power = ahp->upper_limit[0];
437 case OSPREY_2LOHI_CHAINMASK:
438 case OSPREY_2LOMID_CHAINMASK:
440 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
441 -(AR9300_TXBF_2TX_ARRAY_GAIN) :
442 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
443 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
444 cdd_power = ahp->upper_limit[1] + twice_array_gain;
445 /* Adjust OFDM legacy rates as well */
446 for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {
447 if (power_per_rate[i] > cdd_power) {
448 power_per_rate[i] = cdd_power;
452 /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 20*/
453 for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_7; i++) {
454 if (power_per_rate[i] > cdd_power) {
455 power_per_rate[i] = cdd_power;
459 /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7 HT 40*/
460 for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_7; i++) {
461 if (power_per_rate[i] > cdd_power) {
462 power_per_rate[i] = cdd_power;
467 case OSPREY_3_CHAINMASK:
469 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
470 -(AR9300_TXBF_3TX_ARRAY_GAIN) :
471 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
472 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
473 cdd_power = ahp->upper_limit[2] + twice_array_gain;
474 /* Adjust OFDM legacy rates as well */
475 for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {
476 if (power_per_rate[i] > cdd_power) {
477 power_per_rate[i] = cdd_power;
480 /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT20 */
481 for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_15; i++) {
482 if (power_per_rate[i] > cdd_power) {
483 power_per_rate[i] = cdd_power;
487 /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT40 */
488 for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_15; i++) {
489 if (power_per_rate[i] > cdd_power) {
490 power_per_rate[i] = cdd_power;
497 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
498 __func__, ahp->ah_tx_chainmask);
506 ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode,
507 const struct ieee80211_channel *chan,
508 u_int8_t power_per_rate[], u_int8_t chainmask)
510 const HAL_RATE_TABLE *rt;
511 HAL_BOOL is40 = IEEE80211_IS_CHAN_HT40(chan);
513 rt = ar9300_get_rate_table(ah, mode);
514 HALASSERT(rt != NULL);
518 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
519 AR9300_11A_RT_OFDM_OFFSET, chainmask);
521 case HAL_MODE_11NA_HT20:
522 case HAL_MODE_11NA_HT40PLUS:
523 case HAL_MODE_11NA_HT40MINUS:
524 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
525 AR9300_11NA_RT_OFDM_OFFSET, chainmask);
526 ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
527 AR9300_11NA_RT_HT_SS_OFFSET,
528 AR9300_11NA_RT_HT_DS_OFFSET,
529 AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
530 ar9300_init_rate_txpower_stbc(ah, rt, is40,
531 AR9300_11NA_RT_HT_SS_OFFSET,
532 AR9300_11NA_RT_HT_DS_OFFSET,
533 AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
534 /* For FCC the array gain has to be factored for CDD mode */
535 if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {
536 ar9300_adjust_rate_txpower_cdd(ah, rt, is40,
537 AR9300_11NA_RT_HT_SS_OFFSET,
538 AR9300_11NA_RT_HT_DS_OFFSET,
539 AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
543 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
544 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
545 AR9300_11G_RT_OFDM_OFFSET, chainmask);
548 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
550 case HAL_MODE_11NG_HT20:
551 case HAL_MODE_11NG_HT40PLUS:
552 case HAL_MODE_11NG_HT40MINUS:
553 ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
554 ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
555 AR9300_11NG_RT_OFDM_OFFSET, chainmask);
556 ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
557 AR9300_11NG_RT_HT_SS_OFFSET,
558 AR9300_11NG_RT_HT_DS_OFFSET,
559 AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
560 ar9300_init_rate_txpower_stbc(ah, rt, is40,
561 AR9300_11NG_RT_HT_SS_OFFSET,
562 AR9300_11NG_RT_HT_DS_OFFSET,
563 AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
564 /* For FCC the array gain needs to be factored for CDD mode */
565 if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {
566 ar9300_adjust_rate_txpower_cdd(ah, rt, is40,
567 AR9300_11NG_RT_HT_SS_OFFSET,
568 AR9300_11NG_RT_HT_DS_OFFSET,
569 AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
573 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",
582 ar9300_init_rate_txpower_cck(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
583 u_int8_t rates_array[], u_int8_t chainmask)
585 struct ath_hal_9300 *ahp = AH9300(ah);
587 * Pick the lower of the long-preamble txpower, and short-preamble tx power.
588 * Unfortunately, the rate table doesn't have separate entries for these!.
591 case OSPREY_1_CHAINMASK:
592 ahp->txpower[0][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];
593 ahp->txpower[1][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];
594 ahp->txpower[2][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
595 rates_array[ALL_TARGET_LEGACY_5S]);
596 ahp->txpower[3][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
597 rates_array[ALL_TARGET_LEGACY_11S]);
599 case OSPREY_2LOHI_CHAINMASK:
600 case OSPREY_2LOMID_CHAINMASK:
601 ahp->txpower[0][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];
602 ahp->txpower[1][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];
603 ahp->txpower[2][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
604 rates_array[ALL_TARGET_LEGACY_5S]);
605 ahp->txpower[3][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
606 rates_array[ALL_TARGET_LEGACY_11S]);
608 case OSPREY_3_CHAINMASK:
609 ahp->txpower[0][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];
610 ahp->txpower[1][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];
611 ahp->txpower[2][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
612 rates_array[ALL_TARGET_LEGACY_5S]);
613 ahp->txpower[3][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
614 rates_array[ALL_TARGET_LEGACY_11S]);
617 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
618 __func__, chainmask);
624 ar9300_init_rate_txpower_ofdm(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
625 u_int8_t rates_array[], int rt_offset,
628 struct ath_hal_9300 *ahp = AH9300(ah);
629 int16_t twice_array_gain, cdd_power = 0;
631 u_int8_t ofdm_rt_2_pwr_idx[8] =
633 ALL_TARGET_LEGACY_6_24,
634 ALL_TARGET_LEGACY_6_24,
635 ALL_TARGET_LEGACY_6_24,
636 ALL_TARGET_LEGACY_6_24,
637 ALL_TARGET_LEGACY_6_24,
638 ALL_TARGET_LEGACY_36,
639 ALL_TARGET_LEGACY_48,
640 ALL_TARGET_LEGACY_54,
644 * For FCC adjust the upper limit for CDD factoring in the array gain.
645 * The array gain is the same as TxBF, hence reuse the same defines.
647 for (i = rt_offset; i < rt_offset + AR9300_NUM_OFDM_RATES; i++) {
649 /* Get the correct OFDM rate to Power table Index */
650 j = ofdm_rt_2_pwr_idx[i- rt_offset];
653 case OSPREY_1_CHAINMASK:
654 ahp->txpower[i][0] = rates_array[j];
656 case OSPREY_2LOHI_CHAINMASK:
657 case OSPREY_2LOMID_CHAINMASK:
658 ahp->txpower[i][1] = rates_array[j];
659 if (is_reg_dmn_fcc(ahp->reg_dmn)){
660 twice_array_gain = (ahp->twice_antenna_gain >=
661 ahp->twice_antenna_reduction)?
662 -(AR9300_TXBF_2TX_ARRAY_GAIN) :
663 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
664 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
665 cdd_power = ahp->upper_limit[1] + twice_array_gain;
666 if (ahp->txpower[i][1] > cdd_power){
667 ahp->txpower[i][1] = cdd_power;
671 case OSPREY_3_CHAINMASK:
672 ahp->txpower[i][2] = rates_array[j];
673 if (is_reg_dmn_fcc(ahp->reg_dmn)) {
675 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
676 -(AR9300_TXBF_3TX_ARRAY_GAIN):
677 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
678 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
679 cdd_power = ahp->upper_limit[2] + twice_array_gain;
680 if (ahp->txpower[i][2] > cdd_power){
681 ahp->txpower[i][2] = cdd_power;
686 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
687 __func__, chainmask);
693 static u_int8_t mcs_rate_2_pwr_idx_ht20[24] =
695 ALL_TARGET_HT20_0_8_16,
696 ALL_TARGET_HT20_1_3_9_11_17_19,
697 ALL_TARGET_HT20_1_3_9_11_17_19,
698 ALL_TARGET_HT20_1_3_9_11_17_19,
703 ALL_TARGET_HT20_0_8_16,
704 ALL_TARGET_HT20_1_3_9_11_17_19,
705 ALL_TARGET_HT20_1_3_9_11_17_19,
706 ALL_TARGET_HT20_1_3_9_11_17_19,
711 ALL_TARGET_HT20_0_8_16,
712 ALL_TARGET_HT20_1_3_9_11_17_19,
713 ALL_TARGET_HT20_1_3_9_11_17_19,
714 ALL_TARGET_HT20_1_3_9_11_17_19,
721 static u_int8_t mcs_rate_2_pwr_idx_ht40[24] =
723 ALL_TARGET_HT40_0_8_16,
724 ALL_TARGET_HT40_1_3_9_11_17_19,
725 ALL_TARGET_HT40_1_3_9_11_17_19,
726 ALL_TARGET_HT40_1_3_9_11_17_19,
731 ALL_TARGET_HT40_0_8_16,
732 ALL_TARGET_HT40_1_3_9_11_17_19,
733 ALL_TARGET_HT40_1_3_9_11_17_19,
734 ALL_TARGET_HT40_1_3_9_11_17_19,
739 ALL_TARGET_HT40_0_8_16,
740 ALL_TARGET_HT40_1_3_9_11_17_19,
741 ALL_TARGET_HT40_1_3_9_11_17_19,
742 ALL_TARGET_HT40_1_3_9_11_17_19,
750 ar9300_init_rate_txpower_ht(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
752 u_int8_t rates_array[],
753 int rt_ss_offset, int rt_ds_offset,
754 int rt_ts_offset, u_int8_t chainmask)
757 struct ath_hal_9300 *ahp = AH9300(ah);
759 u_int8_t mcs_index = 0;
762 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
763 /* Get the correct MCS rate to Power table Index */
764 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
765 mcs_rate_2_pwr_idx_ht20[mcs_index];
767 case OSPREY_1_CHAINMASK:
768 ahp->txpower[i][0] = rates_array[j];
770 case OSPREY_2LOHI_CHAINMASK:
771 case OSPREY_2LOMID_CHAINMASK:
772 ahp->txpower[i][1] = rates_array[j];
774 case OSPREY_3_CHAINMASK:
775 ahp->txpower[i][2] = rates_array[j];
778 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
779 __func__, chainmask);
785 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
786 /* Get the correct MCS rate to Power table Index */
787 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
788 mcs_rate_2_pwr_idx_ht20[mcs_index];
790 case OSPREY_1_CHAINMASK:
791 ahp->txpower[i][0] = rates_array[j];
793 case OSPREY_2LOHI_CHAINMASK:
794 case OSPREY_2LOMID_CHAINMASK:
795 ahp->txpower[i][1] = rates_array[j];
797 case OSPREY_3_CHAINMASK:
798 ahp->txpower[i][2] = rates_array[j];
801 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
802 __func__, chainmask);
808 for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {
809 /* Get the correct MCS rate to Power table Index */
810 j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
811 mcs_rate_2_pwr_idx_ht20[mcs_index];
813 case OSPREY_1_CHAINMASK:
814 ahp->txpower[i][0] = rates_array[j];
816 case OSPREY_2LOHI_CHAINMASK:
817 case OSPREY_2LOMID_CHAINMASK:
818 ahp->txpower[i][1] = rates_array[j];
820 case OSPREY_3_CHAINMASK:
821 ahp->txpower[i][2] = rates_array[j];
824 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
825 __func__, chainmask);
833 ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
835 int rt_ss_offset, int rt_ds_offset,
836 int rt_ts_offset, u_int8_t chainmask)
839 struct ath_hal_9300 *ahp = AH9300(ah);
841 int16_t twice_array_gain, stbc_power = 0;
842 u_int8_t mcs_index = 0;
844 /* Upper Limit with STBC */
846 case OSPREY_1_CHAINMASK:
847 stbc_power = ahp->upper_limit[0];
849 case OSPREY_2LOHI_CHAINMASK:
850 case OSPREY_2LOMID_CHAINMASK:
851 stbc_power = ahp->upper_limit[1];
853 case OSPREY_3_CHAINMASK:
854 stbc_power = ahp->upper_limit[2];
855 /* Ony FCC requires that we back off with 3 transmit chains */
856 if (is_reg_dmn_fcc(ahp->reg_dmn)) {
858 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
859 -(AR9300_STBC_3TX_ARRAY_GAIN) :
860 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
861 (ahp->twice_antenna_gain + AR9300_STBC_3TX_ARRAY_GAIN)), 0));
862 stbc_power = ahp->upper_limit[2] + twice_array_gain;
867 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
868 __func__, chainmask);
873 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
875 case OSPREY_1_CHAINMASK:
876 ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
878 case OSPREY_2LOHI_CHAINMASK:
879 case OSPREY_2LOMID_CHAINMASK:
880 ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
882 case OSPREY_3_CHAINMASK:
883 ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
884 /* 3 TX/1 stream STBC gain adjustment */
885 if (ahp->txpower_stbc[i][2] > stbc_power){
886 ahp->txpower_stbc[i][2] = stbc_power;
890 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
891 __func__, chainmask);
897 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
899 case OSPREY_1_CHAINMASK:
900 ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
902 case OSPREY_2LOHI_CHAINMASK:
903 case OSPREY_2LOMID_CHAINMASK:
904 ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
906 case OSPREY_3_CHAINMASK:
907 ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
908 /* 3 TX/2 stream STBC gain adjustment */
909 if (ahp->txpower_stbc[i][2] > stbc_power){
910 ahp->txpower_stbc[i][2] = stbc_power;
914 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
915 __func__, chainmask);
921 for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {
923 case OSPREY_1_CHAINMASK:
924 ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
926 case OSPREY_2LOHI_CHAINMASK:
927 case OSPREY_2LOMID_CHAINMASK:
928 ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
930 case OSPREY_3_CHAINMASK:
931 ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
934 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
935 __func__, chainmask);
945 ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
947 int rt_ss_offset, int rt_ds_offset,
948 int rt_ts_offset, u_int8_t chainmask)
951 struct ath_hal_9300 *ahp = AH9300(ah);
953 int16_t twice_array_gain, cdd_power = 0;
954 u_int8_t mcs_index = 0;
957 * Adjust the upper limit for CDD factoring in the array gain .
958 * The array gain is the same as TxBF, hence reuse the same defines.
961 case OSPREY_1_CHAINMASK:
962 cdd_power = ahp->upper_limit[0];
965 case OSPREY_2LOHI_CHAINMASK:
966 case OSPREY_2LOMID_CHAINMASK:
968 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
969 -(AR9300_TXBF_2TX_ARRAY_GAIN) :
970 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
971 (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
972 cdd_power = ahp->upper_limit[1] + twice_array_gain;
975 case OSPREY_3_CHAINMASK:
977 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
978 -(AR9300_TXBF_3TX_ARRAY_GAIN) :
979 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
980 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
981 cdd_power = ahp->upper_limit[2] + twice_array_gain;
985 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
986 __func__, chainmask);
991 for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
993 case OSPREY_1_CHAINMASK:
996 case OSPREY_2LOHI_CHAINMASK:
997 case OSPREY_2LOMID_CHAINMASK:
998 /* 2 TX/1 stream CDD gain adjustment */
999 if (ahp->txpower[i][1] > cdd_power){
1000 ahp->txpower[i][1] = cdd_power;
1003 case OSPREY_3_CHAINMASK:
1004 /* 3 TX/1 stream CDD gain adjustment */
1005 if (ahp->txpower[i][2] > cdd_power){
1006 ahp->txpower[i][2] = cdd_power;
1010 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
1011 __func__, chainmask);
1017 for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
1018 switch (chainmask) {
1019 case OSPREY_1_CHAINMASK:
1020 case OSPREY_2LOHI_CHAINMASK:
1021 case OSPREY_2LOMID_CHAINMASK:
1023 case OSPREY_3_CHAINMASK:
1024 /* 3 TX/2 stream TxBF gain adjustment */
1025 if (ahp->txpower[i][2] > cdd_power){
1026 ahp->txpower[i][2] = cdd_power;
1030 HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
1031 __func__, chainmask);
1041 void ar9300_disp_tpc_tables(struct ath_hal *ah)
1043 struct ath_hal_9300 *ahp = AH9300(ah);
1044 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
1045 u_int mode = ath_hal_get_curmode(ah, chan);
1046 const HAL_RATE_TABLE *rt;
1049 /* Check whether TPC is enabled */
1050 if (!ah->ah_config.ath_hal_desc_tpc) {
1051 ath_hal_printf(ah, "\n TPC Register method in use\n");
1055 rt = ar9300_get_rate_table(ah, mode);
1056 HALASSERT(rt != NULL);
1058 ath_hal_printf(ah, "\n===TARGET POWER TABLE===\n");
1059 for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
1060 for (i = 0; i < rt->rateCount; i++) {
1061 int16_t txpower[AR9300_MAX_CHAINS];
1062 txpower[j] = ahp->txpower[i][j];
1063 ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "
1064 "Power (%d Chain) [%2d.%1d dBm]\n",
1065 i, rt->info[i].rateCode, rt->info[i].rateKbps,
1066 j + 1, txpower[j] / 2, txpower[j]%2 * 5);
1069 ath_hal_printf(ah, "\n");
1071 ath_hal_printf(ah, "\n\n===TARGET POWER TABLE with STBC===\n");
1072 for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
1073 for (i = 0; i < rt->rateCount; i++) {
1074 int16_t txpower[AR9300_MAX_CHAINS];
1075 txpower[j] = ahp->txpower_stbc[i][j];
1077 /* Do not display invalid configurations */
1078 if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||
1079 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||
1080 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {
1084 ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "
1085 "Power (%d Chain) [%2d.%1d dBm]\n",
1086 i, rt->info[i].rateCode , rt->info[i].rateKbps,
1087 j + 1, txpower[j] / 2, txpower[j]%2 * 5);
1090 ath_hal_printf(ah, "\n");
1094 * The followings are customer specific APIs for querying power limit.
1095 * Power limit is based on regulatory domain, chipset, and transmission rate.
1096 * Here we only consider EEPROM values, no array gain/CTL considered here.
1099 struct rate_power_tbl {
1100 u_int8_t rateIdx; /* rate index in the rate table */
1101 u_int32_t rateKbps; /* transfer rate in kbs */
1102 u_int8_t rateCode; /* rate for h/w descriptors */
1103 u_int8_t txbf: 1, /* txbf eligible */
1104 stbc: 1, /* stbc eligible */
1105 chain1: 1, /* one-chain eligible */
1106 chain2: 1, /* two-chain eligible */
1107 chain3: 1; /* three-chain eligible */
1108 int16_t txpower[AR9300_MAX_CHAINS]; /* txpower for different chainmasks */
1109 int16_t txpower_stbc[AR9300_MAX_CHAINS];
1112 u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah)
1114 struct ath_hal_9300 *ahp = AH9300(ah);
1115 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
1116 u_int mode = ath_hal_get_curmode(ah, chan);
1117 const HAL_RATE_TABLE *rt;
1119 struct rate_power_tbl *table;
1122 /* Check whether TPC is enabled */
1123 if (! ah->ah_config.ath_hal_desc_tpc) {
1124 ath_hal_printf(ah, "\n TPC Register method in use\n");
1128 rt = (const HAL_RATE_TABLE *)ar9300_get_rate_table(ah, mode);
1129 HALASSERT(rt != NULL);
1131 data = (u_int8_t *)ath_hal_malloc(
1132 1 + rt->rateCount * sizeof(struct rate_power_tbl));
1136 OS_MEMZERO(data, 1 + rt->rateCount * sizeof(struct rate_power_tbl));
1137 /* store the rate count at the beginning */
1138 *data = rt->rateCount;
1139 table = (struct rate_power_tbl *)&data[1];
1141 for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
1142 for (i = 0; i < rt->rateCount; i++) {
1143 table[i].rateIdx = i;
1144 table[i].rateCode = rt->info[i].rateCode;
1145 table[i].rateKbps = rt->info[i].rateKbps;
1148 table[i].chain1 = rt->info[i].rateCode <= 0x87 ? 1 : 0;
1151 table[i].chain2 = rt->info[i].rateCode <= 0x8f ? 1 : 0;
1154 table[i].chain3 = 1;
1159 if ((j == 0 && table[i].chain1) ||
1160 (j == 1 && table[i].chain2) ||
1161 (j == 2 && table[i].chain3))
1162 table[i].txpower[j] = ahp->txpower[i][j];
1166 for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
1167 for (i = 0; i < rt->rateCount; i++) {
1168 /* Do not display invalid configurations */
1169 if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||
1170 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||
1171 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {
1176 table[i].txpower_stbc[j] = ahp->txpower_stbc[i][j];
1181 /* the caller is responsible to free data */
1185 ath_hal_get_rate_power_limit_from_eeprom(struct ath_hal *ah, u_int16_t freq,
1186 int8_t *max_rate_power, int8_t *min_rate_power)
1189 * Used for AR9300 series chip only
1191 if (ah->ah_magic == AR9300_MAGIC) {
1192 u_int8_t target_rate_power_limit_val_t2[ar9300_rate_size];
1195 *max_rate_power = 0;
1196 *min_rate_power = AR9300_MAX_RATE_POWER;
1198 ar9300_set_target_power_from_eeprom(ah, freq, target_rate_power_limit_val_t2);
1200 for (i=0; i<ar9300_rate_size; i++) {
1201 if (target_rate_power_limit_val_t2[i] > *max_rate_power)
1202 *max_rate_power = target_rate_power_limit_val_t2[i];
1203 if (target_rate_power_limit_val_t2[i] < *min_rate_power)
1204 *min_rate_power = target_rate_power_limit_val_t2[i];
1207 *max_rate_power = 0;
1208 *min_rate_power = 0;