Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c
48525 views
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
1228