OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / hal_com_phycfg.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _HAL_COM_PHYCFG_C_
16
17 #include <drv_types.h>
18 #include <hal_data.h>
19
20 #define PG_TXPWR_1PATH_BYTE_NUM_2G 18
21 #define PG_TXPWR_BASE_BYTE_NUM_2G 11
22
23 #define PG_TXPWR_1PATH_BYTE_NUM_5G 24
24 #define PG_TXPWR_BASE_BYTE_NUM_5G 14
25
26 #define PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) (((_pg_v) & 0xf0) >> 4)
27 #define PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) ((_pg_v) & 0x0f)
28 #define PG_TXPWR_MSB_DIFF_TO_S8BIT(_pg_v) ((PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) & BIT3) ? (PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) | 0xF0) : PG_TXPWR_MSB_DIFF_S4BIT(_pg_v))
29 #define PG_TXPWR_LSB_DIFF_TO_S8BIT(_pg_v) ((PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) & BIT3) ? (PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) | 0xF0) : PG_TXPWR_LSB_DIFF_S4BIT(_pg_v))
30 #define IS_PG_TXPWR_BASE_INVALID(hal_spec, _base) ((_base) > hal_spec->txgi_max)
31 #define IS_PG_TXPWR_DIFF_INVALID(_diff) ((_diff) > 7 || (_diff) < -8)
32 #define PG_TXPWR_INVALID_BASE 255
33 #define PG_TXPWR_INVALID_DIFF 8
34
35 #if !IS_PG_TXPWR_DIFF_INVALID(PG_TXPWR_INVALID_DIFF)
36 #error "PG_TXPWR_DIFF definition has problem"
37 #endif
38
39 #define PG_TXPWR_SRC_PG_DATA    0
40 #define PG_TXPWR_SRC_IC_DEF             1
41 #define PG_TXPWR_SRC_DEF                2
42 #define PG_TXPWR_SRC_NUM                3
43
44 const char *const _pg_txpwr_src_str[] = {
45         "PG_DATA",
46         "IC_DEF",
47         "DEF",
48         "UNKNOWN"
49 };
50
51 #define pg_txpwr_src_str(src) (((src) >= PG_TXPWR_SRC_NUM) ? _pg_txpwr_src_str[PG_TXPWR_SRC_NUM] : _pg_txpwr_src_str[(src)])
52
53 #ifndef DBG_PG_TXPWR_READ
54 #define DBG_PG_TXPWR_READ 0
55 #endif
56
57 #if DBG_PG_TXPWR_READ
58 static void dump_pg_txpwr_info_2g(void *sel, TxPowerInfo24G *txpwr_info, u8 rfpath_num, u8 max_tx_cnt)
59 {
60         int path, group, tx_idx;
61
62         RTW_PRINT_SEL(sel, "2.4G\n");
63         RTW_PRINT_SEL(sel, "CCK-1T base:\n");
64         RTW_PRINT_SEL(sel, "%4s ", "");
65         for (group = 0; group < MAX_CHNL_GROUP_24G; group++)
66                 _RTW_PRINT_SEL(sel, "G%02d ", group);
67         _RTW_PRINT_SEL(sel, "\n");
68         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
69                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
70                 for (group = 0; group < MAX_CHNL_GROUP_24G; group++)
71                         _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexCCK_Base[path][group]);
72                 _RTW_PRINT_SEL(sel, "\n");
73         }
74         RTW_PRINT_SEL(sel, "\n");
75
76         RTW_PRINT_SEL(sel, "CCK diff:\n");
77         RTW_PRINT_SEL(sel, "%4s ", "");
78         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
79                 _RTW_PRINT_SEL(sel, "%dT ", path + 1);
80         _RTW_PRINT_SEL(sel, "\n");
81         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
82                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
83                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
84                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->CCK_Diff[path][tx_idx]);
85                 _RTW_PRINT_SEL(sel, "\n");
86         }
87         RTW_PRINT_SEL(sel, "\n");
88
89         RTW_PRINT_SEL(sel, "BW40-1S base:\n");
90         RTW_PRINT_SEL(sel, "%4s ", "");
91         for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++)
92                 _RTW_PRINT_SEL(sel, "G%02d ", group);
93         _RTW_PRINT_SEL(sel, "\n");
94         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
95                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
96                 for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++)
97                         _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexBW40_Base[path][group]);
98                 _RTW_PRINT_SEL(sel, "\n");
99         }
100         RTW_PRINT_SEL(sel, "\n");
101
102         RTW_PRINT_SEL(sel, "OFDM diff:\n");
103         RTW_PRINT_SEL(sel, "%4s ", "");
104         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
105                 _RTW_PRINT_SEL(sel, "%dT ", path + 1);
106         _RTW_PRINT_SEL(sel, "\n");
107         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
108                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
109                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
110                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->OFDM_Diff[path][tx_idx]);
111                 _RTW_PRINT_SEL(sel, "\n");
112         }
113         RTW_PRINT_SEL(sel, "\n");
114
115         RTW_PRINT_SEL(sel, "BW20 diff:\n");
116         RTW_PRINT_SEL(sel, "%4s ", "");
117         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
118                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
119         _RTW_PRINT_SEL(sel, "\n");
120         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
121                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
122                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
123                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW20_Diff[path][tx_idx]);
124                 _RTW_PRINT_SEL(sel, "\n");
125         }
126         RTW_PRINT_SEL(sel, "\n");
127
128         RTW_PRINT_SEL(sel, "BW40 diff:\n");
129         RTW_PRINT_SEL(sel, "%4s ", "");
130         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
131                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
132         _RTW_PRINT_SEL(sel, "\n");
133         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
134                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
135                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
136                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW40_Diff[path][tx_idx]);
137                 _RTW_PRINT_SEL(sel, "\n");
138         }
139         RTW_PRINT_SEL(sel, "\n");
140 }
141
142 static void dump_pg_txpwr_info_5g(void *sel, TxPowerInfo5G *txpwr_info, u8 rfpath_num, u8 max_tx_cnt)
143 {
144         int path, group, tx_idx;
145
146         RTW_PRINT_SEL(sel, "5G\n");
147         RTW_PRINT_SEL(sel, "BW40-1S base:\n");
148         RTW_PRINT_SEL(sel, "%4s ", "");
149         for (group = 0; group < MAX_CHNL_GROUP_5G; group++)
150                 _RTW_PRINT_SEL(sel, "G%02d ", group);
151         _RTW_PRINT_SEL(sel, "\n");
152         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
153                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
154                 for (group = 0; group < MAX_CHNL_GROUP_5G; group++)
155                         _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexBW40_Base[path][group]);
156                 _RTW_PRINT_SEL(sel, "\n");
157         }
158         RTW_PRINT_SEL(sel, "\n");
159
160         RTW_PRINT_SEL(sel, "OFDM diff:\n");
161         RTW_PRINT_SEL(sel, "%4s ", "");
162         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
163                 _RTW_PRINT_SEL(sel, "%dT ", path + 1);
164         _RTW_PRINT_SEL(sel, "\n");
165         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
166                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
167                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
168                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->OFDM_Diff[path][tx_idx]);
169                 _RTW_PRINT_SEL(sel, "\n");
170         }
171         RTW_PRINT_SEL(sel, "\n");
172
173         RTW_PRINT_SEL(sel, "BW20 diff:\n");
174         RTW_PRINT_SEL(sel, "%4s ", "");
175         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
176                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
177         _RTW_PRINT_SEL(sel, "\n");
178         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
179                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
180                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
181                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW20_Diff[path][tx_idx]);
182                 _RTW_PRINT_SEL(sel, "\n");
183         }
184         RTW_PRINT_SEL(sel, "\n");
185
186         RTW_PRINT_SEL(sel, "BW40 diff:\n");
187         RTW_PRINT_SEL(sel, "%4s ", "");
188         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
189                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
190         _RTW_PRINT_SEL(sel, "\n");
191         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
192                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
193                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
194                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW40_Diff[path][tx_idx]);
195                 _RTW_PRINT_SEL(sel, "\n");
196         }
197         RTW_PRINT_SEL(sel, "\n");
198
199         RTW_PRINT_SEL(sel, "BW80 diff:\n");
200         RTW_PRINT_SEL(sel, "%4s ", "");
201         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
202                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
203         _RTW_PRINT_SEL(sel, "\n");
204         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
205                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
206                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
207                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW80_Diff[path][tx_idx]);
208                 _RTW_PRINT_SEL(sel, "\n");
209         }
210         RTW_PRINT_SEL(sel, "\n");
211
212         RTW_PRINT_SEL(sel, "BW160 diff:\n");
213         RTW_PRINT_SEL(sel, "%4s ", "");
214         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++)
215                 _RTW_PRINT_SEL(sel, "%dS ", path + 1);
216         _RTW_PRINT_SEL(sel, "\n");
217         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
218                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
219                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
220                         _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW160_Diff[path][tx_idx]);
221                 _RTW_PRINT_SEL(sel, "\n");
222         }
223         RTW_PRINT_SEL(sel, "\n");
224 }
225 #endif /* DBG_PG_TXPWR_READ */
226
227 const struct map_t pg_txpwr_def_info =
228         MAP_ENT(0xB8, 1, 0xFF
229                 , MAPSEG_ARRAY_ENT(0x10, 168,
230                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE,
231                         0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
232                         0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
233                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A,
234                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
235                         0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24,
236                         0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
237                         0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D,
238                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
239                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE,
240                         0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE)
241         );
242
243 #ifdef CONFIG_RTL8188E
244 static const struct map_t rtl8188e_pg_txpwr_def_info =
245         MAP_ENT(0xB8, 1, 0xFF
246                 , MAPSEG_ARRAY_ENT(0x10, 12,
247                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24)
248         );
249 #endif
250
251 #ifdef CONFIG_RTL8188F
252 static const struct map_t rtl8188f_pg_txpwr_def_info =
253         MAP_ENT(0xB8, 1, 0xFF
254                 , MAPSEG_ARRAY_ENT(0x10, 12,
255                         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27, 0x27, 0x27, 0x27, 0x24)
256         );
257 #endif
258
259 #ifdef CONFIG_RTL8188GTV
260 static const struct map_t rtl8188gtv_pg_txpwr_def_info =
261         MAP_ENT(0xB8, 1, 0xFF
262                 , MAPSEG_ARRAY_ENT(0x10, 12,
263                         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27, 0x27, 0x27, 0x27, 0x24)
264         );
265 #endif
266
267 #ifdef CONFIG_RTL8723B
268 static const struct map_t rtl8723b_pg_txpwr_def_info =
269         MAP_ENT(0xB8, 2, 0xFF
270                 , MAPSEG_ARRAY_ENT(0x10, 12,
271                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xE0)
272                 , MAPSEG_ARRAY_ENT(0x3A, 12,
273                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xE0)
274         );
275 #endif
276
277 #ifdef CONFIG_RTL8703B
278 static const struct map_t rtl8703b_pg_txpwr_def_info =
279         MAP_ENT(0xB8, 1, 0xFF
280                 , MAPSEG_ARRAY_ENT(0x10, 12,
281                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02)
282         );
283 #endif
284
285 #ifdef CONFIG_RTL8723D
286 static const struct map_t rtl8723d_pg_txpwr_def_info =
287         MAP_ENT(0xB8, 2, 0xFF
288                 , MAPSEG_ARRAY_ENT(0x10, 12,
289                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02)
290                 , MAPSEG_ARRAY_ENT(0x3A, 12,
291                         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x02)
292         );
293 #endif
294
295 #ifdef CONFIG_RTL8192E
296 static const struct map_t rtl8192e_pg_txpwr_def_info =
297         MAP_ENT(0xB8, 2, 0xFF
298                 , MAPSEG_ARRAY_ENT(0x10, 14,
299                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE)
300                 , MAPSEG_ARRAY_ENT(0x3A, 14,
301                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE)
302         );
303 #endif
304
305 #ifdef CONFIG_RTL8821A
306 static const struct map_t rtl8821a_pg_txpwr_def_info =
307         MAP_ENT(0xB8, 1, 0xFF
308                 , MAPSEG_ARRAY_ENT(0x10, 39,
309                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xFF, 0xFF, 0xFF, 0xFF,
310                         0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
311                         0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00)
312         );
313 #endif
314
315 #ifdef CONFIG_RTL8821C
316 static const struct map_t rtl8821c_pg_txpwr_def_info =
317         MAP_ENT(0xB8, 1, 0xFF
318                 , MAPSEG_ARRAY_ENT(0x10, 54,
319                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xFF, 0xFF, 0xFF, 0xFF,
320                         0xFF, 0xFF, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
321                         0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xFF, 0xFF, 0xFF, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
322                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02)
323         );
324 #endif
325
326 #ifdef CONFIG_RTL8710B
327 static const struct map_t rtl8710b_pg_txpwr_def_info =
328         MAP_ENT(0xC8, 1, 0xFF
329                 , MAPSEG_ARRAY_ENT(0x20, 12,
330                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x20)
331         );
332 #endif
333
334 #ifdef CONFIG_RTL8812A
335 static const struct map_t rtl8812a_pg_txpwr_def_info =
336         MAP_ENT(0xB8, 1, 0xFF
337                 , MAPSEG_ARRAY_ENT(0x10, 82,
338                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xFF, 0xFF,
339                         0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
340                         0x02, 0xEE, 0xFF, 0xFF, 0xEE, 0xFF, 0x00, 0xEE, 0xFF, 0xFF, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
341                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A,
342                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0xEE, 0xFF, 0xFF, 0xEE, 0xFF,
343                         0x00, 0xEE)
344         );
345 #endif
346
347 #ifdef CONFIG_RTL8822B
348 static const struct map_t rtl8822b_pg_txpwr_def_info =
349         MAP_ENT(0xB8, 1, 0xFF
350                 , MAPSEG_ARRAY_ENT(0x10, 82,
351                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xFF, 0xFF,
352                         0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
353                         0x02, 0xEE, 0xFF, 0xFF, 0xEE, 0xFF, 0xEC, 0xEC, 0xFF, 0xFF, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
354                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A,
355                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0xEE, 0xFF, 0xFF, 0xEE, 0xFF,
356                         0xEC, 0xEC)
357         );
358 #endif
359
360 #ifdef CONFIG_RTL8814A
361 static const struct map_t rtl8814a_pg_txpwr_def_info =
362         MAP_ENT(0xB8, 1, 0xFF
363                 , MAPSEG_ARRAY_ENT(0x10, 168,
364                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xEE, 0xEE,
365                         0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
366                         0x02, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
367                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A,
368                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
369                         0x00, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02,
370                         0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
371                         0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D,
372                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
373                         0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x02, 0xEE,
374                         0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0xEE, 0xEE, 0xEE)
375         );
376 #endif
377
378 #ifdef CONFIG_RTL8192F/*use 8192F default,no document*/
379 static const struct map_t rtl8192f_pg_txpwr_def_info =
380         MAP_ENT(0xB8, 2, 0xFF
381                 , MAPSEG_ARRAY_ENT(0x10, 14,
382                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE)
383                 , MAPSEG_ARRAY_ENT(0x3A, 14,
384                         0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE)
385         );
386 #endif
387
388 const struct map_t *hal_pg_txpwr_def_info(_adapter *adapter)
389 {
390         u8 interface_type = 0;
391         const struct map_t *map = NULL;
392
393         interface_type = rtw_get_intf_type(adapter);
394
395         switch (rtw_get_chip_type(adapter)) {
396 #ifdef CONFIG_RTL8723B
397         case RTL8723B:
398                 map = &rtl8723b_pg_txpwr_def_info;
399                 break;
400 #endif
401 #ifdef CONFIG_RTL8703B
402         case RTL8703B:
403                 map = &rtl8703b_pg_txpwr_def_info;
404                 break;
405 #endif
406 #ifdef CONFIG_RTL8723D
407         case RTL8723D:
408                 map = &rtl8723d_pg_txpwr_def_info;
409                 break;
410 #endif
411 #ifdef CONFIG_RTL8188E
412         case RTL8188E:
413                 map = &rtl8188e_pg_txpwr_def_info;
414                 break;
415 #endif
416 #ifdef CONFIG_RTL8188F
417         case RTL8188F:
418                 map = &rtl8188f_pg_txpwr_def_info;
419                 break;
420 #endif
421 #ifdef CONFIG_RTL8188GTV
422         case RTL8188GTV:
423                 map = &rtl8188gtv_pg_txpwr_def_info;
424                 break;
425 #endif
426 #ifdef CONFIG_RTL8812A
427         case RTL8812:
428                 map = &rtl8812a_pg_txpwr_def_info;
429                 break;
430 #endif
431 #ifdef CONFIG_RTL8821A
432         case RTL8821:
433                 map = &rtl8821a_pg_txpwr_def_info;
434                 break;
435 #endif
436 #ifdef CONFIG_RTL8192E
437         case RTL8192E:
438                 map = &rtl8192e_pg_txpwr_def_info;
439                 break;
440 #endif
441 #ifdef CONFIG_RTL8814A
442         case RTL8814A:
443                 map = &rtl8814a_pg_txpwr_def_info;
444                 break;
445 #endif
446 #ifdef CONFIG_RTL8822B
447         case RTL8822B:
448                 map = &rtl8822b_pg_txpwr_def_info;
449                 break;
450 #endif
451 #ifdef CONFIG_RTL8821C
452         case RTL8821C:
453                 map = &rtl8821c_pg_txpwr_def_info;
454                 break;
455 #endif
456 #ifdef CONFIG_RTL8710B
457         case RTL8710B:
458                 map = &rtl8710b_pg_txpwr_def_info;
459                 break;
460 #endif
461 #ifdef CONFIG_RTL8192F
462         case RTL8192F:
463                 map = &rtl8192f_pg_txpwr_def_info;
464                 break;
465 #endif
466         }
467
468         if (map == NULL) {
469                 RTW_ERR("%s: unknown chip_type:%u\n"
470                         , __func__, rtw_get_chip_type(adapter));
471                 rtw_warn_on(1);
472         }
473
474         return map;
475 }
476
477 static u8 hal_chk_pg_txpwr_info_2g(_adapter *adapter, TxPowerInfo24G *pwr_info)
478 {
479         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
480         u8 path, group, tx_idx;
481
482         if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_2G))
483                 return _SUCCESS;
484
485         for (path = 0; path < MAX_RF_PATH; path++) {
486                 if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path))
487                         continue;
488                 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
489                         if (IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexCCK_Base[path][group])
490                                 || IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexBW40_Base[path][group]))
491                                 return _FAIL;
492                 }
493                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
494                         if (!HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx))
495                                 continue;
496                         if (IS_PG_TXPWR_DIFF_INVALID(pwr_info->CCK_Diff[path][tx_idx])
497                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx])
498                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
499                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx]))
500                                 return _FAIL;
501                 }
502         }
503
504         return _SUCCESS;
505 }
506
507 static u8 hal_chk_pg_txpwr_info_5g(_adapter *adapter, TxPowerInfo5G *pwr_info)
508 {
509 #ifdef CONFIG_IEEE80211_BAND_5GHZ
510         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
511         u8 path, group, tx_idx;
512
513         if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_5G))
514                 return _SUCCESS;
515
516         for (path = 0; path < MAX_RF_PATH; path++) {
517                 if (!HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path))
518                         continue;
519                 for (group = 0; group < MAX_CHNL_GROUP_5G; group++)
520                         if (IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexBW40_Base[path][group]))
521                                 return _FAIL;
522                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
523                         if (!HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx))
524                                 continue;
525                         if (IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx])
526                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
527                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx])
528                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW80_Diff[path][tx_idx])
529                                 || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW160_Diff[path][tx_idx]))
530                                 return _FAIL;
531                 }
532         }
533 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
534         return _SUCCESS;
535 }
536
537 static inline void hal_init_pg_txpwr_info_2g(_adapter *adapter, TxPowerInfo24G *pwr_info)
538 {
539         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
540         u8 path, group, tx_idx;
541
542         if (pwr_info == NULL)
543                 return;
544
545         _rtw_memset(pwr_info, 0, sizeof(TxPowerInfo24G));
546
547         /* init with invalid value */
548         for (path = 0; path < MAX_RF_PATH; path++) {
549                 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
550                         pwr_info->IndexCCK_Base[path][group] = PG_TXPWR_INVALID_BASE;
551                         pwr_info->IndexBW40_Base[path][group] = PG_TXPWR_INVALID_BASE;
552                 }
553                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
554                         pwr_info->CCK_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
555                         pwr_info->OFDM_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
556                         pwr_info->BW20_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
557                         pwr_info->BW40_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
558                 }
559         }
560
561         /* init for dummy base and diff */
562         for (path = 0; path < MAX_RF_PATH; path++) {
563                 if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path))
564                         break;
565                 /* 2.4G BW40 base has 1 less group than CCK base*/
566                 pwr_info->IndexBW40_Base[path][MAX_CHNL_GROUP_24G - 1] = 0;
567
568                 /* dummy diff */
569                 pwr_info->CCK_Diff[path][0] = 0; /* 2.4G CCK-1TX */
570                 pwr_info->BW40_Diff[path][0] = 0; /* 2.4G BW40-1S */
571         }
572 }
573
574 static inline void hal_init_pg_txpwr_info_5g(_adapter *adapter, TxPowerInfo5G *pwr_info)
575 {
576 #ifdef CONFIG_IEEE80211_BAND_5GHZ
577         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
578         u8 path, group, tx_idx;
579
580         if (pwr_info == NULL)
581                 return;
582
583         _rtw_memset(pwr_info, 0, sizeof(TxPowerInfo5G));
584
585         /* init with invalid value */
586         for (path = 0; path < MAX_RF_PATH; path++) {
587                 for (group = 0; group < MAX_CHNL_GROUP_5G; group++)
588                         pwr_info->IndexBW40_Base[path][group] = PG_TXPWR_INVALID_BASE;
589                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
590                         pwr_info->OFDM_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
591                         pwr_info->BW20_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
592                         pwr_info->BW40_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
593                         pwr_info->BW80_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
594                         pwr_info->BW160_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF;
595                 }
596         }
597
598         for (path = 0; path < MAX_RF_PATH; path++) {
599                 if (!HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path))
600                         break;
601                 /* dummy diff */
602                 pwr_info->BW40_Diff[path][0] = 0; /* 5G BW40-1S */
603         }
604 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
605 }
606
607 #if DBG_PG_TXPWR_READ
608 #define LOAD_PG_TXPWR_WARN_COND(_txpwr_src) 1
609 #else
610 #define LOAD_PG_TXPWR_WARN_COND(_txpwr_src) (_txpwr_src > PG_TXPWR_SRC_PG_DATA)
611 #endif
612
613 u16 hal_load_pg_txpwr_info_path_2g(
614         _adapter *adapter,
615         TxPowerInfo24G  *pwr_info,
616         u32 path,
617         u8 txpwr_src,
618         const struct map_t *txpwr_map,
619         u16 pg_offset)
620 {
621         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
622         u16 offset = pg_offset;
623         u8 group, tx_idx;
624         u8 val;
625         u8 tmp_base;
626         s8 tmp_diff;
627
628         if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_2G)) {
629                 offset += PG_TXPWR_1PATH_BYTE_NUM_2G;
630                 goto exit;
631         }
632
633         if (DBG_PG_TXPWR_READ)
634                 RTW_INFO("%s [%c] offset:0x%03x\n", __func__, rf_path_char(path), offset);
635
636         for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
637                 if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) {
638                         tmp_base = map_read8(txpwr_map, offset);
639                         if (!IS_PG_TXPWR_BASE_INVALID(hal_spec, tmp_base)
640                                 && IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexCCK_Base[path][group])
641                         ) {
642                                 pwr_info->IndexCCK_Base[path][group] = tmp_base;
643                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
644                                         RTW_INFO("[%c] 2G G%02d CCK-1T base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src));
645                         }
646                 }
647                 offset++;
648         }
649
650         for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
651                 if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) {
652                         tmp_base = map_read8(txpwr_map, offset);
653                         if (!IS_PG_TXPWR_BASE_INVALID(hal_spec, tmp_base)
654                                 && IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexBW40_Base[path][group])
655                         ) {
656                                 pwr_info->IndexBW40_Base[path][group] = tmp_base;
657                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
658                                         RTW_INFO("[%c] 2G G%02d BW40-1S base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src));
659                         }
660                 }
661                 offset++;
662         }
663
664         for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
665                 if (tx_idx == 0) {
666                         if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
667                                 val = map_read8(txpwr_map, offset);
668                                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
669                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
670                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
671                                 ) {
672                                         pwr_info->BW20_Diff[path][tx_idx] = tmp_diff;
673                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
674                                                 RTW_INFO("[%c] 2G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
675                                 }
676                                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
677                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
678                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx])
679                                 ) {
680                                         pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff;
681                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
682                                                 RTW_INFO("[%c] 2G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
683                                 }
684                         }
685                         offset++;
686                 } else {
687                         if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
688                                 val = map_read8(txpwr_map, offset);
689                                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
690                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
691                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx])
692                                 ) {
693                                         pwr_info->BW40_Diff[path][tx_idx] = tmp_diff;
694                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
695                                                 RTW_INFO("[%c] 2G BW40-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
696
697                                 }
698                                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
699                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
700                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
701                                 ) {
702                                         pwr_info->BW20_Diff[path][tx_idx] = tmp_diff;
703                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
704                                                 RTW_INFO("[%c] 2G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
705                                 }
706                         }
707                         offset++;
708
709                         if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
710                                 val = map_read8(txpwr_map, offset);
711                                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
712                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
713                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx])
714                                 ) {
715                                         pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff;
716                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
717                                                 RTW_INFO("[%c] 2G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
718                                 }
719                                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
720                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
721                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->CCK_Diff[path][tx_idx])
722                                 ) {
723                                         pwr_info->CCK_Diff[path][tx_idx] =      tmp_diff;
724                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
725                                                 RTW_INFO("[%c] 2G CCK-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
726                                 }
727                         }
728                         offset++;
729                 }
730         }
731
732         if (offset != pg_offset + PG_TXPWR_1PATH_BYTE_NUM_2G) {
733                 RTW_ERR("%s parse %d bytes != %d\n", __func__, offset - pg_offset, PG_TXPWR_1PATH_BYTE_NUM_2G);
734                 rtw_warn_on(1);
735         }
736
737 exit:
738         return offset;
739 }
740
741 u16 hal_load_pg_txpwr_info_path_5g(
742         _adapter *adapter,
743         TxPowerInfo5G   *pwr_info,
744         u32 path,
745         u8 txpwr_src,
746         const struct map_t *txpwr_map,
747         u16 pg_offset)
748 {
749         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
750         u16 offset = pg_offset;
751         u8 group, tx_idx;
752         u8 val;
753         u8 tmp_base;
754         s8 tmp_diff;
755
756 #ifdef CONFIG_IEEE80211_BAND_5GHZ
757         if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_5G))
758 #endif
759         {
760                 offset += PG_TXPWR_1PATH_BYTE_NUM_5G;
761                 goto exit;
762         }
763
764 #ifdef CONFIG_IEEE80211_BAND_5GHZ
765         if (DBG_PG_TXPWR_READ)
766                 RTW_INFO("%s[%c] eaddr:0x%03x\n", __func__, rf_path_char(path), offset);
767
768         for (group = 0; group < MAX_CHNL_GROUP_5G; group++) {
769                 if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) {
770                         tmp_base = map_read8(txpwr_map, offset);
771                         if (!IS_PG_TXPWR_BASE_INVALID(hal_spec, tmp_base)
772                                 && IS_PG_TXPWR_BASE_INVALID(hal_spec, pwr_info->IndexBW40_Base[path][group])
773                         ) {
774                                 pwr_info->IndexBW40_Base[path][group] = tmp_base;
775                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
776                                         RTW_INFO("[%c] 5G G%02d BW40-1S base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src));
777                         }
778                 }
779                 offset++;
780         }
781
782         for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
783                 if (tx_idx == 0) {
784                         if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
785                                 val = map_read8(txpwr_map, offset);
786                                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
787                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
788                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
789                                 ) {
790                                         pwr_info->BW20_Diff[path][tx_idx] = tmp_diff;
791                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
792                                                 RTW_INFO("[%c] 5G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
793                                 }
794                                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
795                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
796                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx])
797                                 ) {
798                                         pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff;
799                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
800                                                 RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
801                                 }
802                         }
803                         offset++;
804                 } else {
805                         if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
806                                 val = map_read8(txpwr_map, offset);
807                                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
808                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
809                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx])
810                                 ) {
811                                         pwr_info->BW40_Diff[path][tx_idx] = tmp_diff;
812                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
813                                                 RTW_INFO("[%c] 5G BW40-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
814                                 }
815                                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
816                                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
817                                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx])
818                                 ) {
819                                         pwr_info->BW20_Diff[path][tx_idx] = tmp_diff;
820                                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
821                                                 RTW_INFO("[%c] 5G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
822                                 }
823                         }
824                         offset++;
825                 }
826         }
827
828         /* OFDM diff 2T ~ 3T */
829         if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, 1)) {
830                 val = map_read8(txpwr_map, offset);
831                 tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
832                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
833                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][1])
834                 ) {
835                         pwr_info->OFDM_Diff[path][1] = tmp_diff;
836                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
837                                 RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 2, tmp_diff, pg_txpwr_src_str(txpwr_src));
838                 }
839                 if (HAL_SPEC_CHK_TX_CNT(hal_spec, 2)) {
840                         tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
841                         if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
842                                 && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][2])
843                         ) {
844                                 pwr_info->OFDM_Diff[path][2] = tmp_diff;
845                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
846                                         RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 3, tmp_diff, pg_txpwr_src_str(txpwr_src));
847                         }
848                 }
849         }
850         offset++;
851
852         /* OFDM diff 4T */
853         if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, 3)) {
854                 val = map_read8(txpwr_map, offset);
855                 tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
856                 if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
857                         && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][3])
858                 ) {
859                         pwr_info->OFDM_Diff[path][3] = tmp_diff;
860                         if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
861                                 RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 4, tmp_diff, pg_txpwr_src_str(txpwr_src));
862                 }
863         }
864         offset++;
865
866         for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
867                 if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) {
868                         val = map_read8(txpwr_map, offset);
869                         tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val);
870                         if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
871                                 && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW80_Diff[path][tx_idx])
872                         ) {
873                                 pwr_info->BW80_Diff[path][tx_idx] = tmp_diff;
874                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
875                                         RTW_INFO("[%c] 5G BW80-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
876                         }
877                         tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val);
878                         if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff)
879                                 && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW160_Diff[path][tx_idx])
880                         ) {
881                                 pwr_info->BW160_Diff[path][tx_idx] = tmp_diff;
882                                 if (LOAD_PG_TXPWR_WARN_COND(txpwr_src))
883                                         RTW_INFO("[%c] 5G BW160-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src));
884                         }
885                 }
886                 offset++;
887         }
888
889         if (offset != pg_offset + PG_TXPWR_1PATH_BYTE_NUM_5G) {
890                 RTW_ERR("%s parse %d bytes != %d\n", __func__, offset - pg_offset, PG_TXPWR_1PATH_BYTE_NUM_5G);
891                 rtw_warn_on(1);
892         }
893
894 #endif /* #ifdef CONFIG_IEEE80211_BAND_5GHZ */
895
896 exit:
897         return offset;
898 }
899
900 void hal_load_pg_txpwr_info(
901         _adapter *adapter,
902         TxPowerInfo24G *pwr_info_2g,
903         TxPowerInfo5G *pwr_info_5g,
904         u8 *pg_data,
905         BOOLEAN AutoLoadFail
906 )
907 {
908         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
909         u8 path;
910         u16 pg_offset;
911         u8 txpwr_src = PG_TXPWR_SRC_PG_DATA;
912         struct map_t pg_data_map = MAP_ENT(184, 1, 0xFF, MAPSEG_PTR_ENT(0x00, 184, pg_data));
913         const struct map_t *txpwr_map = NULL;
914
915         /* init with invalid value and some dummy base and diff */
916         hal_init_pg_txpwr_info_2g(adapter, pwr_info_2g);
917         hal_init_pg_txpwr_info_5g(adapter, pwr_info_5g);
918
919 select_src:
920         pg_offset = hal_spec->pg_txpwr_saddr;
921
922         switch (txpwr_src) {
923         case PG_TXPWR_SRC_PG_DATA:
924                 txpwr_map = &pg_data_map;
925                 break;
926         case PG_TXPWR_SRC_IC_DEF:
927                 txpwr_map = hal_pg_txpwr_def_info(adapter);
928                 break;
929         case PG_TXPWR_SRC_DEF:
930         default:
931                 txpwr_map = &pg_txpwr_def_info;
932                 break;
933         };
934
935         if (txpwr_map == NULL)
936                 goto end_parse;
937
938         for (path = 0; path < MAX_RF_PATH ; path++) {
939                 if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && !HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path))
940                         break;
941                 pg_offset = hal_load_pg_txpwr_info_path_2g(adapter, pwr_info_2g, path, txpwr_src, txpwr_map, pg_offset);
942                 pg_offset = hal_load_pg_txpwr_info_path_5g(adapter, pwr_info_5g, path, txpwr_src, txpwr_map, pg_offset);
943         }
944
945         if (hal_chk_pg_txpwr_info_2g(adapter, pwr_info_2g) == _SUCCESS
946                 && hal_chk_pg_txpwr_info_5g(adapter, pwr_info_5g) == _SUCCESS)
947                 goto exit;
948
949 end_parse:
950         txpwr_src++;
951         if (txpwr_src < PG_TXPWR_SRC_NUM)
952                 goto select_src;
953
954         if (hal_chk_pg_txpwr_info_2g(adapter, pwr_info_2g) != _SUCCESS
955                 || hal_chk_pg_txpwr_info_5g(adapter, pwr_info_5g) != _SUCCESS)
956                 rtw_warn_on(1);
957
958 exit:
959         #if DBG_PG_TXPWR_READ
960         if (pwr_info_2g)
961                 dump_pg_txpwr_info_2g(RTW_DBGDUMP, pwr_info_2g, 4, 4);
962         if (pwr_info_5g)
963                 dump_pg_txpwr_info_5g(RTW_DBGDUMP, pwr_info_5g, 4, 4);
964         #endif
965
966         return;
967 }
968
969 #ifdef CONFIG_EFUSE_CONFIG_FILE
970
971 #define EFUSE_POWER_INDEX_INVALID 0xFF
972
973 static u8 _check_phy_efuse_tx_power_info_valid(u8 *pg_data, int base_len, u16 pg_offset)
974 {
975         int ff_cnt = 0;
976         int i;
977
978         for (i = 0; i < base_len; i++) {
979                 if (*(pg_data + pg_offset + i) == 0xFF)
980                         ff_cnt++;
981         }
982
983         if (ff_cnt == 0)
984                 return _TRUE;
985         else if (ff_cnt == base_len)
986                 return _FALSE;
987         else
988                 return EFUSE_POWER_INDEX_INVALID;
989 }
990
991 int check_phy_efuse_tx_power_info_valid(_adapter *adapter)
992 {
993         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
994         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
995         u8 *pg_data = hal_data->efuse_eeprom_data;
996         u16 pg_offset = hal_spec->pg_txpwr_saddr;
997         u8 path;
998         u8 valid_2g_path_bmp = 0;
999 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1000         u8 valid_5g_path_bmp = 0;
1001 #endif
1002         int result = _FALSE;
1003
1004         for (path = 0; path < MAX_RF_PATH; path++) {
1005                 u8 ret = _FALSE;
1006
1007                 if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && !HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path))
1008                         break;
1009
1010                 if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) {
1011                         ret = _check_phy_efuse_tx_power_info_valid(pg_data, PG_TXPWR_BASE_BYTE_NUM_2G, pg_offset);
1012                         if (ret == _TRUE)
1013                                 valid_2g_path_bmp |= BIT(path);
1014                         else if (ret == EFUSE_POWER_INDEX_INVALID)
1015                                 return _FALSE;
1016                 }
1017                 pg_offset += PG_TXPWR_1PATH_BYTE_NUM_2G;
1018
1019                 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1020                 if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) {
1021                         ret = _check_phy_efuse_tx_power_info_valid(pg_data, PG_TXPWR_BASE_BYTE_NUM_5G, pg_offset);
1022                         if (ret == _TRUE)
1023                                 valid_5g_path_bmp |= BIT(path);
1024                         else if (ret == EFUSE_POWER_INDEX_INVALID)
1025                                 return _FALSE;
1026                 }
1027                 #endif
1028                 pg_offset += PG_TXPWR_1PATH_BYTE_NUM_5G;
1029         }
1030
1031         if ((hal_chk_band_cap(adapter, BAND_CAP_2G) && valid_2g_path_bmp)
1032                 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1033                 || (hal_chk_band_cap(adapter, BAND_CAP_5G) && valid_5g_path_bmp)
1034                 #endif
1035         )
1036                 return _TRUE;
1037
1038         return _FALSE;
1039 }
1040 #endif /* CONFIG_EFUSE_CONFIG_FILE */
1041
1042 void hal_load_txpwr_info(
1043         _adapter *adapter,
1044         TxPowerInfo24G *pwr_info_2g,
1045         TxPowerInfo5G *pwr_info_5g,
1046         u8 *pg_data
1047 )
1048 {
1049         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1050         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1051         u8 max_tx_cnt = hal_spec->max_tx_cnt;
1052         u8 rfpath, ch_idx, group, tx_idx;
1053
1054         /* load from pg data (or default value) */
1055         hal_load_pg_txpwr_info(adapter, pwr_info_2g, pwr_info_5g, pg_data, _FALSE);
1056
1057         /* transform to hal_data */
1058         for (rfpath = 0; rfpath < MAX_RF_PATH; rfpath++) {
1059
1060                 if (!pwr_info_2g || !HAL_SPEC_CHK_RF_PATH_2G(hal_spec, rfpath))
1061                         goto bypass_2g;
1062
1063                 /* 2.4G base */
1064                 for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) {
1065                         u8 cck_group;
1066
1067                         if (rtw_get_ch_group(ch_idx + 1, &group, &cck_group) != BAND_ON_2_4G)
1068                                 continue;
1069
1070                         hal_data->Index24G_CCK_Base[rfpath][ch_idx] = pwr_info_2g->IndexCCK_Base[rfpath][cck_group];
1071                         hal_data->Index24G_BW40_Base[rfpath][ch_idx] = pwr_info_2g->IndexBW40_Base[rfpath][group];
1072                 }
1073
1074                 /* 2.4G diff */
1075                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
1076                         if (tx_idx >= max_tx_cnt)
1077                                 break;
1078
1079                         hal_data->CCK_24G_Diff[rfpath][tx_idx] = pwr_info_2g->CCK_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1080                         hal_data->OFDM_24G_Diff[rfpath][tx_idx] = pwr_info_2g->OFDM_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1081                         hal_data->BW20_24G_Diff[rfpath][tx_idx] = pwr_info_2g->BW20_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1082                         hal_data->BW40_24G_Diff[rfpath][tx_idx] = pwr_info_2g->BW40_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1083                 }
1084 bypass_2g:
1085                 ;
1086
1087 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1088                 if (!pwr_info_5g || !HAL_SPEC_CHK_RF_PATH_5G(hal_spec, rfpath))
1089                         goto bypass_5g;
1090
1091                 /* 5G base */
1092                 for (ch_idx = 0; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) {
1093                         if (rtw_get_ch_group(center_ch_5g_all[ch_idx], &group, NULL) != BAND_ON_5G)
1094                                 continue;
1095                         hal_data->Index5G_BW40_Base[rfpath][ch_idx] = pwr_info_5g->IndexBW40_Base[rfpath][group];
1096                 }
1097
1098                 for (ch_idx = 0 ; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++) {
1099                         u8 upper, lower;
1100
1101                         if (rtw_get_ch_group(center_ch_5g_80m[ch_idx], &group, NULL) != BAND_ON_5G)
1102                                 continue;
1103
1104                         upper = pwr_info_5g->IndexBW40_Base[rfpath][group];
1105                         lower = pwr_info_5g->IndexBW40_Base[rfpath][group + 1];
1106                         hal_data->Index5G_BW80_Base[rfpath][ch_idx] = (upper + lower) / 2;
1107                 }
1108
1109                 /* 5G diff */
1110                 for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) {
1111                         if (tx_idx >= max_tx_cnt)
1112                                 break;
1113
1114                         hal_data->OFDM_5G_Diff[rfpath][tx_idx] = pwr_info_5g->OFDM_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1115                         hal_data->BW20_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW20_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1116                         hal_data->BW40_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW40_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1117                         hal_data->BW80_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW80_Diff[rfpath][tx_idx] * hal_spec->pg_txgi_diff_factor;
1118                 }
1119 bypass_5g:
1120                 ;
1121 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
1122         }
1123 }
1124
1125 void dump_hal_txpwr_info_2g(void *sel, _adapter *adapter, u8 rfpath_num, u8 max_tx_cnt)
1126 {
1127         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1128         int path, ch_idx, tx_idx;
1129
1130         RTW_PRINT_SEL(sel, "2.4G\n");
1131         RTW_PRINT_SEL(sel, "CCK-1T base:\n");
1132         RTW_PRINT_SEL(sel, "%4s ", "");
1133         for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++)
1134                 _RTW_PRINT_SEL(sel, "%2d ", center_ch_2g[ch_idx]);
1135         _RTW_PRINT_SEL(sel, "\n");
1136         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1137                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1138                 for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++)
1139                         _RTW_PRINT_SEL(sel, "%2u ", hal_data->Index24G_CCK_Base[path][ch_idx]);
1140                 _RTW_PRINT_SEL(sel, "\n");
1141         }
1142         RTW_PRINT_SEL(sel, "\n");
1143
1144         RTW_PRINT_SEL(sel, "CCK diff:\n");
1145         RTW_PRINT_SEL(sel, "%4s ", "");
1146         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1147                 _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1);
1148         _RTW_PRINT_SEL(sel, "\n");
1149         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1150                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1151                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1152                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->CCK_24G_Diff[path][tx_idx]);
1153                 _RTW_PRINT_SEL(sel, "\n");
1154         }
1155         RTW_PRINT_SEL(sel, "\n");
1156
1157         RTW_PRINT_SEL(sel, "BW40-1S base:\n");
1158         RTW_PRINT_SEL(sel, "%4s ", "");
1159         for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++)
1160                 _RTW_PRINT_SEL(sel, "%2d ", center_ch_2g[ch_idx]);
1161         _RTW_PRINT_SEL(sel, "\n");
1162         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1163                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1164                 for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++)
1165                         _RTW_PRINT_SEL(sel, "%2u ", hal_data->Index24G_BW40_Base[path][ch_idx]);
1166                 _RTW_PRINT_SEL(sel, "\n");
1167         }
1168         RTW_PRINT_SEL(sel, "\n");
1169
1170         RTW_PRINT_SEL(sel, "OFDM diff:\n");
1171         RTW_PRINT_SEL(sel, "%4s ", "");
1172         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1173                 _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1);
1174         _RTW_PRINT_SEL(sel, "\n");
1175         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1176                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1177                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1178                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->OFDM_24G_Diff[path][tx_idx]);
1179                 _RTW_PRINT_SEL(sel, "\n");
1180         }
1181         RTW_PRINT_SEL(sel, "\n");
1182
1183         RTW_PRINT_SEL(sel, "BW20 diff:\n");
1184         RTW_PRINT_SEL(sel, "%4s ", "");
1185         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1186                 _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1);
1187         _RTW_PRINT_SEL(sel, "\n");
1188         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1189                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1190                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1191                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW20_24G_Diff[path][tx_idx]);
1192                 _RTW_PRINT_SEL(sel, "\n");
1193         }
1194         RTW_PRINT_SEL(sel, "\n");
1195
1196         RTW_PRINT_SEL(sel, "BW40 diff:\n");
1197         RTW_PRINT_SEL(sel, "%4s ", "");
1198         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1199                 _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1);
1200         _RTW_PRINT_SEL(sel, "\n");
1201         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1202                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1203                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1204                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW40_24G_Diff[path][tx_idx]);
1205                 _RTW_PRINT_SEL(sel, "\n");
1206         }
1207         RTW_PRINT_SEL(sel, "\n");
1208 }
1209
1210 void dump_hal_txpwr_info_5g(void *sel, _adapter *adapter, u8 rfpath_num, u8 max_tx_cnt)
1211 {
1212 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1213         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1214         int path, ch_idx, tx_idx;
1215         u8 dump_section = 0;
1216         u8 ch_idx_s = 0;
1217
1218         RTW_PRINT_SEL(sel, "5G\n");
1219         RTW_PRINT_SEL(sel, "BW40-1S base:\n");
1220         do {
1221                 #define DUMP_5G_BW40_BASE_SECTION_NUM 3
1222                 u8 end[DUMP_5G_BW40_BASE_SECTION_NUM] = {64, 144, 177};
1223
1224                 RTW_PRINT_SEL(sel, "%4s ", "");
1225                 for (ch_idx = ch_idx_s; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) {
1226                         _RTW_PRINT_SEL(sel, "%3d ", center_ch_5g_all[ch_idx]);
1227                         if (end[dump_section] == center_ch_5g_all[ch_idx])
1228                                 break;
1229                 }
1230                 _RTW_PRINT_SEL(sel, "\n");
1231                 for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1232                         RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1233                         for (ch_idx = ch_idx_s; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) {
1234                                 _RTW_PRINT_SEL(sel, "%3u ", hal_data->Index5G_BW40_Base[path][ch_idx]);
1235                                 if (end[dump_section] == center_ch_5g_all[ch_idx])
1236                                         break;
1237                         }
1238                         _RTW_PRINT_SEL(sel, "\n");
1239                 }
1240                 RTW_PRINT_SEL(sel, "\n");
1241
1242                 ch_idx_s = ch_idx + 1;
1243                 dump_section++;
1244                 if (dump_section >= DUMP_5G_BW40_BASE_SECTION_NUM)
1245                         break;
1246         } while (1);
1247
1248         RTW_PRINT_SEL(sel, "BW80-1S base:\n");
1249         RTW_PRINT_SEL(sel, "%4s ", "");
1250         for (ch_idx = 0; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++)
1251                 _RTW_PRINT_SEL(sel, "%3d ", center_ch_5g_80m[ch_idx]);
1252         _RTW_PRINT_SEL(sel, "\n");
1253         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1254                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1255                 for (ch_idx = 0; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++)
1256                         _RTW_PRINT_SEL(sel, "%3u ", hal_data->Index5G_BW80_Base[path][ch_idx]);
1257                 _RTW_PRINT_SEL(sel, "\n");
1258         }
1259         RTW_PRINT_SEL(sel, "\n");
1260
1261         RTW_PRINT_SEL(sel, "OFDM diff:\n");
1262         RTW_PRINT_SEL(sel, "%4s ", "");
1263         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1264                 _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1);
1265         _RTW_PRINT_SEL(sel, "\n");
1266         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1267                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1268                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1269                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->OFDM_5G_Diff[path][tx_idx]);
1270                 _RTW_PRINT_SEL(sel, "\n");
1271         }
1272         RTW_PRINT_SEL(sel, "\n");
1273
1274         RTW_PRINT_SEL(sel, "BW20 diff:\n");
1275         RTW_PRINT_SEL(sel, "%4s ", "");
1276         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1277                 _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1);
1278         _RTW_PRINT_SEL(sel, "\n");
1279         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1280                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1281                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1282                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW20_5G_Diff[path][tx_idx]);
1283                 _RTW_PRINT_SEL(sel, "\n");
1284         }
1285         RTW_PRINT_SEL(sel, "\n");
1286
1287         RTW_PRINT_SEL(sel, "BW40 diff:\n");
1288         RTW_PRINT_SEL(sel, "%4s ", "");
1289         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1290                 _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1);
1291         _RTW_PRINT_SEL(sel, "\n");
1292         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1293                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1294                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1295                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW40_5G_Diff[path][tx_idx]);
1296                 _RTW_PRINT_SEL(sel, "\n");
1297         }
1298         RTW_PRINT_SEL(sel, "\n");
1299
1300         RTW_PRINT_SEL(sel, "BW80 diff:\n");
1301         RTW_PRINT_SEL(sel, "%4s ", "");
1302         for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1303                 _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1);
1304         _RTW_PRINT_SEL(sel, "\n");
1305         for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) {
1306                 RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path));
1307                 for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++)
1308                         _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW80_5G_Diff[path][tx_idx]);
1309                 _RTW_PRINT_SEL(sel, "\n");
1310         }
1311         RTW_PRINT_SEL(sel, "\n");
1312 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
1313 }
1314
1315 /*
1316 * rtw_regsty_get_target_tx_power -
1317 *
1318 * Return dBm or -1 for undefined
1319 */
1320 s8 rtw_regsty_get_target_tx_power(
1321         IN      PADAPTER                Adapter,
1322         IN      u8                              Band,
1323         IN      u8                              RfPath,
1324         IN      RATE_SECTION    RateSection
1325 )
1326 {
1327         struct registry_priv *regsty = adapter_to_regsty(Adapter);
1328         s8 value = 0;
1329
1330         if (RfPath > RF_PATH_D) {
1331                 RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath);
1332                 return -1;
1333         }
1334
1335         if (Band != BAND_ON_2_4G
1336                 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1337                 && Band != BAND_ON_5G
1338                 #endif
1339         ) {
1340                 RTW_PRINT("%s invalid Band:%d\n", __func__, Band);
1341                 return -1;
1342         }
1343
1344         if (RateSection >= RATE_SECTION_NUM
1345                 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1346                 || (Band == BAND_ON_5G && RateSection == CCK)
1347                 #endif
1348         ) {
1349                 RTW_PRINT("%s invalid RateSection:%d in Band:%d, RfPath:%d\n", __func__
1350                         , RateSection, Band, RfPath);
1351                 return -1;
1352         }
1353
1354         if (Band == BAND_ON_2_4G)
1355                 value = regsty->target_tx_pwr_2g[RfPath][RateSection];
1356 #ifdef CONFIG_IEEE80211_BAND_5GHZ
1357         else /* BAND_ON_5G */
1358                 value = regsty->target_tx_pwr_5g[RfPath][RateSection - 1];
1359 #endif
1360
1361         return value;
1362 }
1363
1364 bool rtw_regsty_chk_target_tx_power_valid(_adapter *adapter)
1365 {
1366         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1367         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1368         int path, tx_num, band, rs;
1369         s8 target;
1370
1371         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
1372                 if (!hal_is_band_support(adapter, band))
1373                         continue;
1374
1375                 for (path = 0; path < RF_PATH_MAX; path++) {
1376                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
1377                                 break;
1378
1379                         for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
1380                                 tx_num = rate_section_to_tx_num(rs);
1381                                 if (tx_num >= hal_spec->tx_nss_num)
1382                                         continue;
1383
1384                                 if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
1385                                         continue;
1386
1387                                 if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
1388                                         continue;
1389
1390                                 target = rtw_regsty_get_target_tx_power(adapter, band, path, rs);
1391                                 if (target == -1) {
1392                                         RTW_PRINT("%s return _FALSE for band:%d, path:%d, rs:%d, t:%d\n", __func__, band, path, rs, target);
1393                                         return _FALSE;
1394                                 }
1395                         }
1396                 }
1397         }
1398
1399         return _TRUE;
1400 }
1401
1402 /*
1403 * PHY_GetTxPowerByRateBase -
1404 *
1405 * Return value in unit of TX Gain Index
1406 */
1407 u8
1408 PHY_GetTxPowerByRateBase(
1409         IN      PADAPTER                Adapter,
1410         IN      u8                              Band,
1411         IN      u8                              RfPath,
1412         IN      RATE_SECTION    RateSection
1413 )
1414 {
1415         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
1416         u8 value = 0;
1417
1418         if (RfPath > RF_PATH_D) {
1419                 RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath);
1420                 return 0;
1421         }
1422
1423         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
1424                 RTW_PRINT("%s invalid Band:%d\n", __func__, Band);
1425                 return 0;
1426         }
1427
1428         if (RateSection >= RATE_SECTION_NUM
1429                 || (Band == BAND_ON_5G && RateSection == CCK)
1430         ) {
1431                 RTW_PRINT("%s invalid RateSection:%d in Band:%d, RfPath:%d\n", __func__
1432                         , RateSection, Band, RfPath);
1433                 return 0;
1434         }
1435
1436         if (Band == BAND_ON_2_4G)
1437                 value = pHalData->TxPwrByRateBase2_4G[RfPath][RateSection];
1438         else /* BAND_ON_5G */
1439                 value = pHalData->TxPwrByRateBase5G[RfPath][RateSection - 1];
1440
1441         return value;
1442 }
1443
1444 VOID
1445 phy_SetTxPowerByRateBase(
1446         IN      PADAPTER                Adapter,
1447         IN      u8                              Band,
1448         IN      u8                              RfPath,
1449         IN      RATE_SECTION    RateSection,
1450         IN      u8                              Value
1451 )
1452 {
1453         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
1454
1455         if (RfPath > RF_PATH_D) {
1456                 RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath);
1457                 return;
1458         }
1459
1460         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
1461                 RTW_PRINT("%s invalid Band:%d\n", __func__, Band);
1462                 return;
1463         }
1464
1465         if (RateSection >= RATE_SECTION_NUM
1466                 || (Band == BAND_ON_5G && RateSection == CCK)
1467         ) {
1468                 RTW_PRINT("%s invalid RateSection:%d in %sG, RfPath:%d\n", __func__
1469                         , RateSection, (Band == BAND_ON_2_4G) ? "2.4" : "5", RfPath);
1470                 return;
1471         }
1472
1473         if (Band == BAND_ON_2_4G)
1474                 pHalData->TxPwrByRateBase2_4G[RfPath][RateSection] = Value;
1475         else /* BAND_ON_5G */
1476                 pHalData->TxPwrByRateBase5G[RfPath][RateSection - 1] = Value;
1477 }
1478
1479 static inline BOOLEAN phy_is_txpwr_by_rate_undefined_of_band_path(_adapter *adapter, u8 band, u8 path)
1480 {
1481         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1482         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1483         u8 rate_idx = 0;
1484
1485         for (rate_idx = 0; rate_idx < TX_PWR_BY_RATE_NUM_RATE; rate_idx++) {
1486                 if (hal_data->TxPwrByRateOffset[band][path][rate_idx] != 0)
1487                         goto exit;
1488         }
1489
1490 exit:
1491         return rate_idx >= TX_PWR_BY_RATE_NUM_RATE ? _TRUE : _FALSE;
1492 }
1493
1494 static inline void phy_txpwr_by_rate_duplicate_band_path(_adapter *adapter, u8 band, u8 s_path, u8 t_path)
1495 {
1496         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1497         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1498         u8 rate_idx = 0;
1499
1500         for (rate_idx = 0; rate_idx < TX_PWR_BY_RATE_NUM_RATE; rate_idx++)
1501                 hal_data->TxPwrByRateOffset[band][t_path][rate_idx] = hal_data->TxPwrByRateOffset[band][s_path][rate_idx];
1502 }
1503
1504 static void phy_txpwr_by_rate_chk_for_path_dup(_adapter *adapter)
1505 {
1506         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1507         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
1508         u8 band, path;
1509         s8 src_path;
1510
1511         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++)
1512                 for (path = RF_PATH_A; path < RF_PATH_MAX; path++)
1513                         hal_data->txpwr_by_rate_undefined_band_path[band][path] = 0;
1514
1515         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
1516                 if (!hal_is_band_support(adapter, band))
1517                         continue;
1518
1519                 for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
1520                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
1521                                 continue;
1522
1523                         if (phy_is_txpwr_by_rate_undefined_of_band_path(adapter, band, path))
1524                                 hal_data->txpwr_by_rate_undefined_band_path[band][path] = 1;
1525                 }
1526         }
1527
1528         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
1529                 if (!hal_is_band_support(adapter, band))
1530                         continue;
1531
1532                 src_path = -1;
1533                 for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
1534                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
1535                                 continue;
1536
1537                         /* find src */
1538                         if (src_path == -1 && hal_data->txpwr_by_rate_undefined_band_path[band][path] == 0)
1539                                 src_path = path;
1540                 }
1541
1542                 if (src_path == -1) {
1543                         RTW_ERR("%s all power by rate undefined\n", __func__);
1544                         continue;
1545                 }
1546
1547                 for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
1548                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
1549                                 continue;
1550
1551                         /* duplicate src to undefined one */
1552                         if (hal_data->txpwr_by_rate_undefined_band_path[band][path] == 1) {
1553                                 RTW_INFO("%s duplicate %s [%c] to [%c]\n", __func__
1554                                         , band_str(band), rf_path_char(src_path), rf_path_char(path));
1555                                 phy_txpwr_by_rate_duplicate_band_path(adapter, band, src_path, path);
1556                         }
1557                 }
1558         }
1559 }
1560
1561 VOID
1562 phy_StoreTxPowerByRateBase(
1563         IN      PADAPTER        pAdapter
1564 )
1565 {
1566         struct hal_spec_t *hal_spec = GET_HAL_SPEC(pAdapter);
1567         struct registry_priv *regsty = adapter_to_regsty(pAdapter);
1568
1569         u8 rate_sec_base[RATE_SECTION_NUM] = {
1570                 MGN_11M,
1571                 MGN_54M,
1572                 MGN_MCS7,
1573                 MGN_MCS15,
1574                 MGN_MCS23,
1575                 MGN_MCS31,
1576                 MGN_VHT1SS_MCS7,
1577                 MGN_VHT2SS_MCS7,
1578                 MGN_VHT3SS_MCS7,
1579                 MGN_VHT4SS_MCS7,
1580         };
1581
1582         u8 band, path, rs, tx_num, base, index;
1583
1584         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
1585                 if (!hal_is_band_support(pAdapter, band))
1586                         continue;
1587
1588                 for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
1589                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
1590                                 break;
1591
1592                         for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
1593                                 tx_num = rate_section_to_tx_num(rs);
1594                                 if (tx_num >= hal_spec->tx_nss_num)
1595                                         continue;
1596
1597                                 if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
1598                                         continue;
1599
1600                                 if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(pAdapter))
1601                                         continue;
1602
1603                                 if (regsty->target_tx_pwr_valid == _TRUE)
1604                                         base = hal_spec->txgi_pdbm * rtw_regsty_get_target_tx_power(pAdapter, band, path, rs);
1605                                 else
1606                                         base = _PHY_GetTxPowerByRate(pAdapter, band, path, rate_sec_base[rs]);
1607                                 phy_SetTxPowerByRateBase(pAdapter, band, path, rs, base);
1608                         }
1609                 }
1610         }
1611 }
1612
1613 static u8 get_val_from_dhex(u32 dhex, u8 i)
1614 {
1615         return (((dhex >> (i * 8 + 4)) & 0xF)) * 10 + ((dhex >> (i * 8)) & 0xF);
1616 }
1617
1618 static u8 get_val_from_hex(u32 hex, u8 i)
1619 {
1620         return (hex >> (i * 8)) & 0xFF;
1621 }
1622
1623 VOID
1624 PHY_GetRateValuesOfTxPowerByRate(
1625         IN      PADAPTER pAdapter,
1626         IN      u32 RegAddr,
1627         IN      u32 BitMask,
1628         IN      u32 Value,
1629         OUT     u8 *Rate,
1630         OUT     s8 *PwrByRateVal,
1631         OUT     u8 *RateNum
1632 )
1633 {
1634         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
1635         struct hal_spec_t *hal_spec = GET_HAL_SPEC(pAdapter);
1636         struct dm_struct                *pDM_Odm = &pHalData->odmpriv;
1637         u8                              index = 0, i = 0;
1638         u8 (*get_val)(u32, u8);
1639
1640         if (hal_spec->txgi_pdbm == 2)
1641                 get_val = get_val_from_dhex;
1642         else
1643                 get_val = get_val_from_hex;
1644
1645         switch (RegAddr) {
1646         case rTxAGC_A_Rate18_06:
1647         case rTxAGC_B_Rate18_06:
1648                 Rate[0] = MGN_6M;
1649                 Rate[1] = MGN_9M;
1650                 Rate[2] = MGN_12M;
1651                 Rate[3] = MGN_18M;
1652                 for (i = 0; i < 4; ++i)
1653                         PwrByRateVal[i] = (s8)get_val(Value, i);
1654                 *RateNum = 4;
1655                 break;
1656
1657         case rTxAGC_A_Rate54_24:
1658         case rTxAGC_B_Rate54_24:
1659                 Rate[0] = MGN_24M;
1660                 Rate[1] = MGN_36M;
1661                 Rate[2] = MGN_48M;
1662                 Rate[3] = MGN_54M;
1663                 for (i = 0; i < 4; ++i)
1664                         PwrByRateVal[i] = (s8)get_val(Value, i);
1665                 *RateNum = 4;
1666                 break;
1667
1668         case rTxAGC_A_CCK1_Mcs32:
1669                 Rate[0] = MGN_1M;
1670                 PwrByRateVal[0] = (s8)get_val(Value, 1);
1671                 *RateNum = 1;
1672                 break;
1673
1674         case rTxAGC_B_CCK11_A_CCK2_11:
1675                 if (BitMask == 0xffffff00) {
1676                         Rate[0] = MGN_2M;
1677                         Rate[1] = MGN_5_5M;
1678                         Rate[2] = MGN_11M;
1679                         for (i = 1; i < 4; ++i)
1680                                 PwrByRateVal[i - 1] = (s8)get_val(Value, i);
1681                         *RateNum = 3;
1682                 } else if (BitMask == 0x000000ff) {
1683                         Rate[0] = MGN_11M;
1684                         PwrByRateVal[0] = (s8)get_val(Value, 0);
1685                         *RateNum = 1;
1686                 }
1687                 break;
1688
1689         case rTxAGC_A_Mcs03_Mcs00:
1690         case rTxAGC_B_Mcs03_Mcs00:
1691                 Rate[0] = MGN_MCS0;
1692                 Rate[1] = MGN_MCS1;
1693                 Rate[2] = MGN_MCS2;
1694                 Rate[3] = MGN_MCS3;
1695                 for (i = 0; i < 4; ++i)
1696                         PwrByRateVal[i] = (s8)get_val(Value, i);
1697                 *RateNum = 4;
1698                 break;
1699
1700         case rTxAGC_A_Mcs07_Mcs04:
1701         case rTxAGC_B_Mcs07_Mcs04:
1702                 Rate[0] = MGN_MCS4;
1703                 Rate[1] = MGN_MCS5;
1704                 Rate[2] = MGN_MCS6;
1705                 Rate[3] = MGN_MCS7;
1706                 for (i = 0; i < 4; ++i)
1707                         PwrByRateVal[i] = (s8)get_val(Value, i);
1708                 *RateNum = 4;
1709                 break;
1710
1711         case rTxAGC_A_Mcs11_Mcs08:
1712         case rTxAGC_B_Mcs11_Mcs08:
1713                 Rate[0] = MGN_MCS8;
1714                 Rate[1] = MGN_MCS9;
1715                 Rate[2] = MGN_MCS10;
1716                 Rate[3] = MGN_MCS11;
1717                 for (i = 0; i < 4; ++i)
1718                         PwrByRateVal[i] = (s8)get_val(Value, i);
1719                 *RateNum = 4;
1720                 break;
1721
1722         case rTxAGC_A_Mcs15_Mcs12:
1723         case rTxAGC_B_Mcs15_Mcs12:
1724                 Rate[0] = MGN_MCS12;
1725                 Rate[1] = MGN_MCS13;
1726                 Rate[2] = MGN_MCS14;
1727                 Rate[3] = MGN_MCS15;
1728                 for (i = 0; i < 4; ++i)
1729                         PwrByRateVal[i] = (s8)get_val(Value, i);
1730                 *RateNum = 4;
1731                 break;
1732
1733         case rTxAGC_B_CCK1_55_Mcs32:
1734                 Rate[0] = MGN_1M;
1735                 Rate[1] = MGN_2M;
1736                 Rate[2] = MGN_5_5M;
1737                 for (i = 1; i < 4; ++i)
1738                         PwrByRateVal[i - 1] = (s8)get_val(Value, i);
1739                 *RateNum = 3;
1740                 break;
1741
1742         case 0xC20:
1743         case 0xE20:
1744         case 0x1820:
1745         case 0x1a20:
1746                 Rate[0] = MGN_1M;
1747                 Rate[1] = MGN_2M;
1748                 Rate[2] = MGN_5_5M;
1749                 Rate[3] = MGN_11M;
1750                 for (i = 0; i < 4; ++i)
1751                         PwrByRateVal[i] = (s8)get_val(Value, i);
1752                 *RateNum = 4;
1753                 break;
1754
1755         case 0xC24:
1756         case 0xE24:
1757         case 0x1824:
1758         case 0x1a24:
1759                 Rate[0] = MGN_6M;
1760                 Rate[1] = MGN_9M;
1761                 Rate[2] = MGN_12M;
1762                 Rate[3] = MGN_18M;
1763                 for (i = 0; i < 4; ++i)
1764                         PwrByRateVal[i] = (s8)get_val(Value, i);
1765                 *RateNum = 4;
1766                 break;
1767
1768         case 0xC28:
1769         case 0xE28:
1770         case 0x1828:
1771         case 0x1a28:
1772                 Rate[0] = MGN_24M;
1773                 Rate[1] = MGN_36M;
1774                 Rate[2] = MGN_48M;
1775                 Rate[3] = MGN_54M;
1776                 for (i = 0; i < 4; ++i)
1777                         PwrByRateVal[i] = (s8)get_val(Value, i);
1778                 *RateNum = 4;
1779                 break;
1780
1781         case 0xC2C:
1782         case 0xE2C:
1783         case 0x182C:
1784         case 0x1a2C:
1785                 Rate[0] = MGN_MCS0;
1786                 Rate[1] = MGN_MCS1;
1787                 Rate[2] = MGN_MCS2;
1788                 Rate[3] = MGN_MCS3;
1789                 for (i = 0; i < 4; ++i)
1790                         PwrByRateVal[i] = (s8)get_val(Value, i);
1791                 *RateNum = 4;
1792                 break;
1793
1794         case 0xC30:
1795         case 0xE30:
1796         case 0x1830:
1797         case 0x1a30:
1798                 Rate[0] = MGN_MCS4;
1799                 Rate[1] = MGN_MCS5;
1800                 Rate[2] = MGN_MCS6;
1801                 Rate[3] = MGN_MCS7;
1802                 for (i = 0; i < 4; ++i)
1803                         PwrByRateVal[i] = (s8)get_val(Value, i);
1804                 *RateNum = 4;
1805                 break;
1806
1807         case 0xC34:
1808         case 0xE34:
1809         case 0x1834:
1810         case 0x1a34:
1811                 Rate[0] = MGN_MCS8;
1812                 Rate[1] = MGN_MCS9;
1813                 Rate[2] = MGN_MCS10;
1814                 Rate[3] = MGN_MCS11;
1815                 for (i = 0; i < 4; ++i)
1816                         PwrByRateVal[i] = (s8)get_val(Value, i);
1817                 *RateNum = 4;
1818                 break;
1819
1820         case 0xC38:
1821         case 0xE38:
1822         case 0x1838:
1823         case 0x1a38:
1824                 Rate[0] = MGN_MCS12;
1825                 Rate[1] = MGN_MCS13;
1826                 Rate[2] = MGN_MCS14;
1827                 Rate[3] = MGN_MCS15;
1828                 for (i = 0; i < 4; ++i)
1829                         PwrByRateVal[i] = (s8)get_val(Value, i);
1830                 *RateNum = 4;
1831                 break;
1832
1833         case 0xC3C:
1834         case 0xE3C:
1835         case 0x183C:
1836         case 0x1a3C:
1837                 Rate[0] = MGN_VHT1SS_MCS0;
1838                 Rate[1] = MGN_VHT1SS_MCS1;
1839                 Rate[2] = MGN_VHT1SS_MCS2;
1840                 Rate[3] = MGN_VHT1SS_MCS3;
1841                 for (i = 0; i < 4; ++i)
1842                         PwrByRateVal[i] = (s8)get_val(Value, i);
1843                 *RateNum = 4;
1844                 break;
1845
1846         case 0xC40:
1847         case 0xE40:
1848         case 0x1840:
1849         case 0x1a40:
1850                 Rate[0] = MGN_VHT1SS_MCS4;
1851                 Rate[1] = MGN_VHT1SS_MCS5;
1852                 Rate[2] = MGN_VHT1SS_MCS6;
1853                 Rate[3] = MGN_VHT1SS_MCS7;
1854                 for (i = 0; i < 4; ++i)
1855                         PwrByRateVal[i] = (s8)get_val(Value, i);
1856                 *RateNum = 4;
1857                 break;
1858
1859         case 0xC44:
1860         case 0xE44:
1861         case 0x1844:
1862         case 0x1a44:
1863                 Rate[0] = MGN_VHT1SS_MCS8;
1864                 Rate[1] = MGN_VHT1SS_MCS9;
1865                 Rate[2] = MGN_VHT2SS_MCS0;
1866                 Rate[3] = MGN_VHT2SS_MCS1;
1867                 for (i = 0; i < 4; ++i)
1868                         PwrByRateVal[i] = (s8)get_val(Value, i);
1869                 *RateNum = 4;
1870                 break;
1871
1872         case 0xC48:
1873         case 0xE48:
1874         case 0x1848:
1875         case 0x1a48:
1876                 Rate[0] = MGN_VHT2SS_MCS2;
1877                 Rate[1] = MGN_VHT2SS_MCS3;
1878                 Rate[2] = MGN_VHT2SS_MCS4;
1879                 Rate[3] = MGN_VHT2SS_MCS5;
1880                 for (i = 0; i < 4; ++i)
1881                         PwrByRateVal[i] = (s8)get_val(Value, i);
1882                 *RateNum = 4;
1883                 break;
1884
1885         case 0xC4C:
1886         case 0xE4C:
1887         case 0x184C:
1888         case 0x1a4C:
1889                 Rate[0] = MGN_VHT2SS_MCS6;
1890                 Rate[1] = MGN_VHT2SS_MCS7;
1891                 Rate[2] = MGN_VHT2SS_MCS8;
1892                 Rate[3] = MGN_VHT2SS_MCS9;
1893                 for (i = 0; i < 4; ++i)
1894                         PwrByRateVal[i] = (s8)get_val(Value, i);
1895                 *RateNum = 4;
1896                 break;
1897
1898         case 0xCD8:
1899         case 0xED8:
1900         case 0x18D8:
1901         case 0x1aD8:
1902                 Rate[0] = MGN_MCS16;
1903                 Rate[1] = MGN_MCS17;
1904                 Rate[2] = MGN_MCS18;
1905                 Rate[3] = MGN_MCS19;
1906                 for (i = 0; i < 4; ++i)
1907                         PwrByRateVal[i] = (s8)get_val(Value, i);
1908                 *RateNum = 4;
1909                 break;
1910
1911         case 0xCDC:
1912         case 0xEDC:
1913         case 0x18DC:
1914         case 0x1aDC:
1915                 Rate[0] = MGN_MCS20;
1916                 Rate[1] = MGN_MCS21;
1917                 Rate[2] = MGN_MCS22;
1918                 Rate[3] = MGN_MCS23;
1919                 for (i = 0; i < 4; ++i)
1920                         PwrByRateVal[i] = (s8)get_val(Value, i);
1921                 *RateNum = 4;
1922                 break;
1923
1924         case 0xCE0:
1925         case 0xEE0:
1926         case 0x18E0:
1927         case 0x1aE0:
1928                 Rate[0] = MGN_VHT3SS_MCS0;
1929                 Rate[1] = MGN_VHT3SS_MCS1;
1930                 Rate[2] = MGN_VHT3SS_MCS2;
1931                 Rate[3] = MGN_VHT3SS_MCS3;
1932                 for (i = 0; i < 4; ++i)
1933                         PwrByRateVal[i] = (s8)get_val(Value, i);
1934                 *RateNum = 4;
1935                 break;
1936
1937         case 0xCE4:
1938         case 0xEE4:
1939         case 0x18E4:
1940         case 0x1aE4:
1941                 Rate[0] = MGN_VHT3SS_MCS4;
1942                 Rate[1] = MGN_VHT3SS_MCS5;
1943                 Rate[2] = MGN_VHT3SS_MCS6;
1944                 Rate[3] = MGN_VHT3SS_MCS7;
1945                 for (i = 0; i < 4; ++i)
1946                         PwrByRateVal[i] = (s8)get_val(Value, i);
1947                 *RateNum = 4;
1948                 break;
1949
1950         case 0xCE8:
1951         case 0xEE8:
1952         case 0x18E8:
1953         case 0x1aE8:
1954                 Rate[0] = MGN_VHT3SS_MCS8;
1955                 Rate[1] = MGN_VHT3SS_MCS9;
1956                 for (i = 0; i < 2; ++i)
1957                         PwrByRateVal[i] = (s8)get_val(Value, i);
1958                 *RateNum = 2;
1959                 break;
1960
1961         default:
1962                 RTW_PRINT("Invalid RegAddr 0x%x in %s()\n", RegAddr, __func__);
1963                 break;
1964         };
1965 }
1966
1967 void
1968 PHY_StoreTxPowerByRateNew(
1969         IN      PADAPTER        pAdapter,
1970         IN      u32                     Band,
1971         IN      u32                     RfPath,
1972         IN      u32                     RegAddr,
1973         IN      u32                     BitMask,
1974         IN      u32                     Data
1975 )
1976 {
1977         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
1978         u8      i = 0, rates[4] = {0}, rateNum = 0;
1979         s8      PwrByRateVal[4] = {0};
1980
1981         PHY_GetRateValuesOfTxPowerByRate(pAdapter, RegAddr, BitMask, Data, rates, PwrByRateVal, &rateNum);
1982
1983         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
1984                 RTW_PRINT("Invalid Band %d\n", Band);
1985                 return;
1986         }
1987
1988         if (RfPath > RF_PATH_D) {
1989                 RTW_PRINT("Invalid RfPath %d\n", RfPath);
1990                 return;
1991         }
1992
1993         for (i = 0; i < rateNum; ++i) {
1994                 u8 rate_idx = PHY_GetRateIndexOfTxPowerByRate(rates[i]);
1995
1996                 pHalData->TxPwrByRateOffset[Band][RfPath][rate_idx] = PwrByRateVal[i];
1997         }
1998 }
1999
2000 VOID
2001 PHY_InitTxPowerByRate(
2002         IN      PADAPTER        pAdapter
2003 )
2004 {
2005         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
2006         u8      band = 0, rfPath = 0, rate = 0, i = 0, j = 0;
2007
2008         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band)
2009                 for (rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath)
2010                                 for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate)
2011                                         pHalData->TxPwrByRateOffset[band][rfPath][rate] = 0;
2012 }
2013
2014 VOID
2015 phy_store_tx_power_by_rate(
2016         IN      PADAPTER        pAdapter,
2017         IN      u32                     Band,
2018         IN      u32                     RfPath,
2019         IN      u32                     TxNum,
2020         IN      u32                     RegAddr,
2021         IN      u32                     BitMask,
2022         IN      u32                     Data
2023 )
2024 {
2025         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
2026         struct dm_struct                *pDM_Odm = &pHalData->odmpriv;
2027
2028         if (pDM_Odm->phy_reg_pg_version > 0)
2029                 PHY_StoreTxPowerByRateNew(pAdapter, Band, RfPath, RegAddr, BitMask, Data);
2030         else
2031                 RTW_INFO("Invalid PHY_REG_PG.txt version %d\n",  pDM_Odm->phy_reg_pg_version);
2032
2033 }
2034
2035 VOID
2036 phy_ConvertTxPowerByRateInDbmToRelativeValues(
2037         IN      PADAPTER        pAdapter
2038 )
2039 {
2040         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
2041         u8                      base = 0, i = 0, value = 0,
2042                                 band = 0, path = 0, index = 0,
2043                                 startIndex = 0, endIndex = 0;
2044         u8      cckRates[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M},
2045                 ofdmRates[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M},
2046                 mcs0_7Rates[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7},
2047                 mcs8_15Rates[8] = {MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15},
2048                 mcs16_23Rates[8] = {MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23},
2049                 vht1ssRates[10] = {MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4,
2050                         MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9},
2051                 vht2ssRates[10] = {MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4,
2052                         MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9},
2053                 vht3ssRates[10] = {MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4,
2054                         MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9};
2055
2056         /* RTW_INFO("===>PHY_ConvertTxPowerByRateInDbmToRelativeValues()\n" ); */
2057
2058         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) {
2059                 for (path = RF_PATH_A; path <= RF_PATH_D; ++path) {
2060                         /* CCK */
2061                         if (band == BAND_ON_2_4G) {
2062                                 base = PHY_GetTxPowerByRateBase(pAdapter, band, path, CCK);
2063                                 for (i = 0; i < sizeof(cckRates); ++i) {
2064                                         value = PHY_GetTxPowerByRate(pAdapter, band, path, cckRates[i]);
2065                                         PHY_SetTxPowerByRate(pAdapter, band, path, cckRates[i], value - base);
2066                                 }
2067                         }
2068
2069                         /* OFDM */
2070                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, OFDM);
2071                         for (i = 0; i < sizeof(ofdmRates); ++i) {
2072                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, ofdmRates[i]);
2073                                 PHY_SetTxPowerByRate(pAdapter, band, path, ofdmRates[i], value - base);
2074                         }
2075
2076                         /* HT MCS0~7 */
2077                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, HT_1SS);
2078                         for (i = 0; i < sizeof(mcs0_7Rates); ++i) {
2079                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, mcs0_7Rates[i]);
2080                                 PHY_SetTxPowerByRate(pAdapter, band, path, mcs0_7Rates[i], value - base);
2081                         }
2082
2083                         /* HT MCS8~15 */
2084                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, HT_2SS);
2085                         for (i = 0; i < sizeof(mcs8_15Rates); ++i) {
2086                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, mcs8_15Rates[i]);
2087                                 PHY_SetTxPowerByRate(pAdapter, band, path, mcs8_15Rates[i], value - base);
2088                         }
2089
2090                         /* HT MCS16~23 */
2091                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, HT_3SS);
2092                         for (i = 0; i < sizeof(mcs16_23Rates); ++i) {
2093                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, mcs16_23Rates[i]);
2094                                 PHY_SetTxPowerByRate(pAdapter, band, path, mcs16_23Rates[i], value - base);
2095                         }
2096
2097                         /* VHT 1SS */
2098                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, VHT_1SS);
2099                         for (i = 0; i < sizeof(vht1ssRates); ++i) {
2100                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, vht1ssRates[i]);
2101                                 PHY_SetTxPowerByRate(pAdapter, band, path, vht1ssRates[i], value - base);
2102                         }
2103
2104                         /* VHT 2SS */
2105                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, VHT_2SS);
2106                         for (i = 0; i < sizeof(vht2ssRates); ++i) {
2107                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, vht2ssRates[i]);
2108                                 PHY_SetTxPowerByRate(pAdapter, band, path, vht2ssRates[i], value - base);
2109                         }
2110
2111                         /* VHT 3SS */
2112                         base = PHY_GetTxPowerByRateBase(pAdapter, band, path, VHT_3SS);
2113                         for (i = 0; i < sizeof(vht3ssRates); ++i) {
2114                                 value = PHY_GetTxPowerByRate(pAdapter, band, path, vht3ssRates[i]);
2115                                 PHY_SetTxPowerByRate(pAdapter, band, path, vht3ssRates[i], value - base);
2116                         }
2117                 }
2118         }
2119
2120         /* RTW_INFO("<===PHY_ConvertTxPowerByRateInDbmToRelativeValues()\n" ); */
2121 }
2122
2123 /*
2124   * This function must be called if the value in the PHY_REG_PG.txt(or header)
2125   * is exact dBm values
2126   */
2127 VOID
2128 PHY_TxPowerByRateConfiguration(
2129         IN  PADAPTER                    pAdapter
2130 )
2131 {
2132         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
2133
2134         phy_txpwr_by_rate_chk_for_path_dup(pAdapter);
2135         phy_StoreTxPowerByRateBase(pAdapter);
2136         phy_ConvertTxPowerByRateInDbmToRelativeValues(pAdapter);
2137 }
2138
2139 VOID
2140 phy_set_tx_power_index_by_rate_section(
2141         IN      PADAPTER                pAdapter,
2142         IN      enum rf_path            RFPath,
2143         IN      u8                              Channel,
2144         IN      u8                              RateSection
2145 )
2146 {
2147         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(pAdapter);
2148
2149         if (RateSection >= RATE_SECTION_NUM) {
2150                 RTW_INFO("Invalid RateSection %d in %s", RateSection, __func__);
2151                 rtw_warn_on(1);
2152                 goto exit;
2153         }
2154
2155         if (RateSection == CCK && pHalData->current_band_type != BAND_ON_2_4G)
2156                 goto exit;
2157
2158         PHY_SetTxPowerIndexByRateArray(pAdapter, RFPath, pHalData->current_channel_bw, Channel,
2159                 rates_by_sections[RateSection].rates, rates_by_sections[RateSection].rate_num);
2160
2161 exit:
2162         return;
2163 }
2164
2165 BOOLEAN
2166 phy_GetChnlIndex(
2167         IN      u8      Channel,
2168         OUT u8  *ChannelIdx
2169 )
2170 {
2171         u8  i = 0;
2172         BOOLEAN bIn24G = _TRUE;
2173
2174         if (Channel <= 14) {
2175                 bIn24G = _TRUE;
2176                 *ChannelIdx = Channel - 1;
2177         } else {
2178                 bIn24G = _FALSE;
2179
2180                 for (i = 0; i < CENTER_CH_5G_ALL_NUM; ++i) {
2181                         if (center_ch_5g_all[i] == Channel) {
2182                                 *ChannelIdx = i;
2183                                 return bIn24G;
2184                         }
2185                 }
2186         }
2187
2188         return bIn24G;
2189 }
2190
2191 u8
2192 PHY_GetTxPowerIndexBase(
2193         IN      PADAPTER                pAdapter,
2194         IN      enum rf_path            RFPath,
2195         IN      u8                              Rate,
2196         u8 ntx_idx,
2197         IN      enum channel_width      BandWidth,
2198         IN      u8                              Channel,
2199         OUT PBOOLEAN            bIn24G
2200 )
2201 {
2202         PHAL_DATA_TYPE          pHalData = GET_HAL_DATA(pAdapter);
2203         struct dm_struct                        *pDM_Odm = &pHalData->odmpriv;
2204         u8                                      i = 0;  /* default set to 1S */
2205         u8                                      txPower = 0;
2206         u8                                      chnlIdx = (Channel - 1);
2207
2208         if (HAL_IsLegalChannel(pAdapter, Channel) == _FALSE) {
2209                 chnlIdx = 0;
2210                 RTW_INFO("Illegal channel!!\n");
2211         }
2212
2213         *bIn24G = phy_GetChnlIndex(Channel, &chnlIdx);
2214
2215         if (0)
2216                 RTW_INFO("[%s] Channel Index: %d\n", (*bIn24G ? "2.4G" : "5G"), chnlIdx);
2217
2218         if (*bIn24G) {
2219                 if (IS_CCK_RATE(Rate)) {
2220                         /* CCK-nTX */
2221                         txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx];
2222                         txPower += pHalData->CCK_24G_Diff[RFPath][RF_1TX];
2223                         if (ntx_idx >= RF_2TX)
2224                                 txPower += pHalData->CCK_24G_Diff[RFPath][RF_2TX];
2225                         if (ntx_idx >= RF_3TX)
2226                                 txPower += pHalData->CCK_24G_Diff[RFPath][RF_3TX];
2227                         if (ntx_idx >= RF_4TX)
2228                                 txPower += pHalData->CCK_24G_Diff[RFPath][RF_4TX];
2229                         goto exit;
2230                 }
2231
2232                 txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx];
2233
2234                 /* OFDM-nTX */
2235                 if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) {
2236                         txPower += pHalData->OFDM_24G_Diff[RFPath][RF_1TX];
2237                         if (ntx_idx >= RF_2TX)
2238                                 txPower += pHalData->OFDM_24G_Diff[RFPath][RF_2TX];
2239                         if (ntx_idx >= RF_3TX)
2240                                 txPower += pHalData->OFDM_24G_Diff[RFPath][RF_3TX];
2241                         if (ntx_idx >= RF_4TX)
2242                                 txPower += pHalData->OFDM_24G_Diff[RFPath][RF_4TX];
2243                         goto exit;
2244                 }
2245
2246                 /* BW20-nS */
2247                 if (BandWidth == CHANNEL_WIDTH_20) {
2248                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2249                                 txPower += pHalData->BW20_24G_Diff[RFPath][RF_1TX];
2250                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2251                                 txPower += pHalData->BW20_24G_Diff[RFPath][RF_2TX];
2252                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2253                                 txPower += pHalData->BW20_24G_Diff[RFPath][RF_3TX];
2254                         if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2255                                 txPower += pHalData->BW20_24G_Diff[RFPath][RF_4TX];
2256                         goto exit;
2257                 }
2258
2259                 /* BW40-nS */
2260                 if (BandWidth == CHANNEL_WIDTH_40) {
2261                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2262                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_1TX];
2263                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2264                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_2TX];
2265                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2266                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_3TX];
2267                         if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2268                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_4TX];
2269                         goto exit;
2270                 }
2271
2272                 /* Willis suggest adopt BW 40M power index while in BW 80 mode */
2273                 if (BandWidth == CHANNEL_WIDTH_80) {
2274                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2275                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_1TX];
2276                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2277                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_2TX];
2278                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2279                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_3TX];
2280                         if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2281                                 txPower += pHalData->BW40_24G_Diff[RFPath][RF_4TX];
2282                         goto exit;
2283                 }
2284         }
2285 #ifdef CONFIG_IEEE80211_BAND_5GHZ
2286         else {
2287                 if (Rate >= MGN_6M)
2288                         txPower = pHalData->Index5G_BW40_Base[RFPath][chnlIdx];
2289                 else {
2290                         RTW_INFO("===>PHY_GetTxPowerIndexBase: INVALID Rate(0x%02x).\n", Rate);
2291                         goto exit;
2292                 }
2293
2294                 /* OFDM-nTX */
2295                 if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) {
2296                         txPower += pHalData->OFDM_5G_Diff[RFPath][RF_1TX];
2297                         if (ntx_idx >= RF_2TX)
2298                                 txPower += pHalData->OFDM_5G_Diff[RFPath][RF_2TX];
2299                         if (ntx_idx >= RF_3TX)
2300                                 txPower += pHalData->OFDM_5G_Diff[RFPath][RF_3TX];
2301                         if (ntx_idx >= RF_4TX)
2302                                 txPower += pHalData->OFDM_5G_Diff[RFPath][RF_4TX];
2303                         goto exit;
2304                 }
2305
2306                 /* BW20-nS */
2307                 if (BandWidth == CHANNEL_WIDTH_20) {
2308                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31)  || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2309                                 txPower += pHalData->BW20_5G_Diff[RFPath][RF_1TX];
2310                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2311                                 txPower += pHalData->BW20_5G_Diff[RFPath][RF_2TX];
2312                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2313                                 txPower += pHalData->BW20_5G_Diff[RFPath][RF_3TX];
2314                         if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2315                                 txPower += pHalData->BW20_5G_Diff[RFPath][RF_4TX];
2316                         goto exit;
2317                 }
2318
2319                 /* BW40-nS */
2320                 if (BandWidth == CHANNEL_WIDTH_40) {
2321                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31)  || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2322                                 txPower += pHalData->BW40_5G_Diff[RFPath][RF_1TX];
2323                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2324                                 txPower += pHalData->BW40_5G_Diff[RFPath][RF_2TX];
2325                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2326                                 txPower += pHalData->BW40_5G_Diff[RFPath][RF_3TX];
2327                         if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2328                                 txPower += pHalData->BW40_5G_Diff[RFPath][RF_4TX];
2329                         goto exit;
2330                 }
2331
2332                 /* BW80-nS */
2333                 if (BandWidth == CHANNEL_WIDTH_80) {
2334                         /* get 80MHz cch index */
2335                         for (i = 0; i < CENTER_CH_5G_80M_NUM; ++i) {
2336                                 if (center_ch_5g_80m[i] == Channel) {
2337                                         chnlIdx = i;
2338                                         break;
2339                                 }
2340                         }
2341                         if (i >= CENTER_CH_5G_80M_NUM) {
2342                         #ifdef CONFIG_MP_INCLUDED
2343                                 if (rtw_mp_mode_check(pAdapter) == _FALSE)
2344                         #endif
2345                                         rtw_warn_on(1);
2346                                 txPower = 0;
2347                                 goto exit;
2348                         }
2349
2350                         txPower = pHalData->Index5G_BW80_Base[RFPath][chnlIdx];
2351
2352                         if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31)  || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2353                                 txPower += + pHalData->BW80_5G_Diff[RFPath][RF_1TX];
2354                         if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2355                                 txPower += pHalData->BW80_5G_Diff[RFPath][RF_2TX];
2356                         if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2357                                 txPower += pHalData->BW80_5G_Diff[RFPath][RF_3TX];
2358                         if ((MGN_MCS23 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9))
2359                                 txPower += pHalData->BW80_5G_Diff[RFPath][RF_4TX];
2360                         goto exit;
2361                 }
2362
2363                 /* TODO: BW160-nS */
2364                 rtw_warn_on(1);
2365         }
2366 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
2367
2368 exit:
2369         return txPower;
2370 }
2371
2372 s8
2373 PHY_GetTxPowerTrackingOffset(
2374         PADAPTER        pAdapter,
2375         enum rf_path    RFPath,
2376         u8                      Rate
2377 )
2378 {
2379         PHAL_DATA_TYPE          pHalData = GET_HAL_DATA(pAdapter);
2380         struct dm_struct                        *pDM_Odm = &pHalData->odmpriv;
2381         s8      offset = 0;
2382
2383         if (pDM_Odm->rf_calibrate_info.txpowertrack_control  == _FALSE)
2384                 return offset;
2385
2386         if ((Rate == MGN_1M) || (Rate == MGN_2M) || (Rate == MGN_5_5M) || (Rate == MGN_11M)) {
2387                 offset = pDM_Odm->rf_calibrate_info.remnant_cck_swing_idx;
2388                 /*RTW_INFO("+Remnant_CCKSwingIdx = 0x%x\n", RFPath, Rate, pRFCalibrateInfo->Remnant_CCKSwingIdx);*/
2389         } else {
2390                 offset = pDM_Odm->rf_calibrate_info.remnant_ofdm_swing_idx[RFPath];
2391                 /*RTW_INFO("+Remanant_OFDMSwingIdx[RFPath %u][Rate 0x%x] = 0x%x\n", RFPath, Rate, pRFCalibrateInfo->Remnant_OFDMSwingIdx[RFPath]);      */
2392
2393         }
2394
2395         return offset;
2396 }
2397
2398 /*The same as MRateToHwRate in hal_com.c*/
2399 u8
2400 PHY_GetRateIndexOfTxPowerByRate(
2401         IN      u8              Rate
2402 )
2403 {
2404         u8      index = 0;
2405         switch (Rate) {
2406         case MGN_1M:
2407                 index = 0;
2408                 break;
2409         case MGN_2M:
2410                 index = 1;
2411                 break;
2412         case MGN_5_5M:
2413                 index = 2;
2414                 break;
2415         case MGN_11M:
2416                 index = 3;
2417                 break;
2418         case MGN_6M:
2419                 index = 4;
2420                 break;
2421         case MGN_9M:
2422                 index = 5;
2423                 break;
2424         case MGN_12M:
2425                 index = 6;
2426                 break;
2427         case MGN_18M:
2428                 index = 7;
2429                 break;
2430         case MGN_24M:
2431                 index = 8;
2432                 break;
2433         case MGN_36M:
2434                 index = 9;
2435                 break;
2436         case MGN_48M:
2437                 index = 10;
2438                 break;
2439         case MGN_54M:
2440                 index = 11;
2441                 break;
2442         case MGN_MCS0:
2443                 index = 12;
2444                 break;
2445         case MGN_MCS1:
2446                 index = 13;
2447                 break;
2448         case MGN_MCS2:
2449                 index = 14;
2450                 break;
2451         case MGN_MCS3:
2452                 index = 15;
2453                 break;
2454         case MGN_MCS4:
2455                 index = 16;
2456                 break;
2457         case MGN_MCS5:
2458                 index = 17;
2459                 break;
2460         case MGN_MCS6:
2461                 index = 18;
2462                 break;
2463         case MGN_MCS7:
2464                 index = 19;
2465                 break;
2466         case MGN_MCS8:
2467                 index = 20;
2468                 break;
2469         case MGN_MCS9:
2470                 index = 21;
2471                 break;
2472         case MGN_MCS10:
2473                 index = 22;
2474                 break;
2475         case MGN_MCS11:
2476                 index = 23;
2477                 break;
2478         case MGN_MCS12:
2479                 index = 24;
2480                 break;
2481         case MGN_MCS13:
2482                 index = 25;
2483                 break;
2484         case MGN_MCS14:
2485                 index = 26;
2486                 break;
2487         case MGN_MCS15:
2488                 index = 27;
2489                 break;
2490         case MGN_MCS16:
2491                 index = 28;
2492                 break;
2493         case MGN_MCS17:
2494                 index = 29;
2495                 break;
2496         case MGN_MCS18:
2497                 index = 30;
2498                 break;
2499         case MGN_MCS19:
2500                 index = 31;
2501                 break;
2502         case MGN_MCS20:
2503                 index = 32;
2504                 break;
2505         case MGN_MCS21:
2506                 index = 33;
2507                 break;
2508         case MGN_MCS22:
2509                 index = 34;
2510                 break;
2511         case MGN_MCS23:
2512                 index = 35;
2513                 break;
2514         case MGN_MCS24:
2515                 index = 36;
2516                 break;
2517         case MGN_MCS25:
2518                 index = 37;
2519                 break;
2520         case MGN_MCS26:
2521                 index = 38;
2522                 break;
2523         case MGN_MCS27:
2524                 index = 39;
2525                 break;
2526         case MGN_MCS28:
2527                 index = 40;
2528                 break;
2529         case MGN_MCS29:
2530                 index = 41;
2531                 break;
2532         case MGN_MCS30:
2533                 index = 42;
2534                 break;
2535         case MGN_MCS31:
2536                 index = 43;
2537                 break;
2538         case MGN_VHT1SS_MCS0:
2539                 index = 44;
2540                 break;
2541         case MGN_VHT1SS_MCS1:
2542                 index = 45;
2543                 break;
2544         case MGN_VHT1SS_MCS2:
2545                 index = 46;
2546                 break;
2547         case MGN_VHT1SS_MCS3:
2548                 index = 47;
2549                 break;
2550         case MGN_VHT1SS_MCS4:
2551                 index = 48;
2552                 break;
2553         case MGN_VHT1SS_MCS5:
2554                 index = 49;
2555                 break;
2556         case MGN_VHT1SS_MCS6:
2557                 index = 50;
2558                 break;
2559         case MGN_VHT1SS_MCS7:
2560                 index = 51;
2561                 break;
2562         case MGN_VHT1SS_MCS8:
2563                 index = 52;
2564                 break;
2565         case MGN_VHT1SS_MCS9:
2566                 index = 53;
2567                 break;
2568         case MGN_VHT2SS_MCS0:
2569                 index = 54;
2570                 break;
2571         case MGN_VHT2SS_MCS1:
2572                 index = 55;
2573                 break;
2574         case MGN_VHT2SS_MCS2:
2575                 index = 56;
2576                 break;
2577         case MGN_VHT2SS_MCS3:
2578                 index = 57;
2579                 break;
2580         case MGN_VHT2SS_MCS4:
2581                 index = 58;
2582                 break;
2583         case MGN_VHT2SS_MCS5:
2584                 index = 59;
2585                 break;
2586         case MGN_VHT2SS_MCS6:
2587                 index = 60;
2588                 break;
2589         case MGN_VHT2SS_MCS7:
2590                 index = 61;
2591                 break;
2592         case MGN_VHT2SS_MCS8:
2593                 index = 62;
2594                 break;
2595         case MGN_VHT2SS_MCS9:
2596                 index = 63;
2597                 break;
2598         case MGN_VHT3SS_MCS0:
2599                 index = 64;
2600                 break;
2601         case MGN_VHT3SS_MCS1:
2602                 index = 65;
2603                 break;
2604         case MGN_VHT3SS_MCS2:
2605                 index = 66;
2606                 break;
2607         case MGN_VHT3SS_MCS3:
2608                 index = 67;
2609                 break;
2610         case MGN_VHT3SS_MCS4:
2611                 index = 68;
2612                 break;
2613         case MGN_VHT3SS_MCS5:
2614                 index = 69;
2615                 break;
2616         case MGN_VHT3SS_MCS6:
2617                 index = 70;
2618                 break;
2619         case MGN_VHT3SS_MCS7:
2620                 index = 71;
2621                 break;
2622         case MGN_VHT3SS_MCS8:
2623                 index = 72;
2624                 break;
2625         case MGN_VHT3SS_MCS9:
2626                 index = 73;
2627                 break;
2628         case MGN_VHT4SS_MCS0:
2629                 index = 74;
2630                 break;
2631         case MGN_VHT4SS_MCS1:
2632                 index = 75;
2633                 break;
2634         case MGN_VHT4SS_MCS2:
2635                 index = 76;
2636                 break;
2637         case MGN_VHT4SS_MCS3:
2638                 index = 77;
2639                 break;
2640         case MGN_VHT4SS_MCS4:
2641                 index = 78;
2642                 break;
2643         case MGN_VHT4SS_MCS5:
2644                 index = 79;
2645                 break;
2646         case MGN_VHT4SS_MCS6:
2647                 index = 80;
2648                 break;
2649         case MGN_VHT4SS_MCS7:
2650                 index = 81;
2651                 break;
2652         case MGN_VHT4SS_MCS8:
2653                 index = 82;
2654                 break;
2655         case MGN_VHT4SS_MCS9:
2656                 index = 83;
2657                 break;
2658         default:
2659                 RTW_INFO("Invalid rate 0x%x in %s\n", Rate, __FUNCTION__);
2660                 break;
2661         };
2662
2663         return index;
2664 }
2665
2666 s8
2667 _PHY_GetTxPowerByRate(
2668         IN      PADAPTER        pAdapter,
2669         IN      u8                      Band,
2670         IN      enum rf_path    RFPath,
2671         IN      u8                      Rate
2672 )
2673 {
2674         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
2675         s8 value = 0;
2676         u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate);
2677
2678         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
2679                 RTW_INFO("Invalid band %d in %s\n", Band, __func__);
2680                 goto exit;
2681         }
2682         if (RFPath > RF_PATH_D) {
2683                 RTW_INFO("Invalid RfPath %d in %s\n", RFPath, __func__);
2684                 goto exit;
2685         }
2686         if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) {
2687                 RTW_INFO("Invalid RateIndex %d in %s\n", rateIndex, __func__);
2688                 goto exit;
2689         }
2690
2691         value = pHalData->TxPwrByRateOffset[Band][RFPath][rateIndex];
2692
2693 exit:
2694         return value;
2695 }
2696
2697
2698 s8
2699 PHY_GetTxPowerByRate(
2700         IN      PADAPTER        pAdapter,
2701         IN      u8                      Band,
2702         IN      enum rf_path    RFPath,
2703         IN      u8                      Rate
2704 )
2705 {
2706         if (!phy_is_tx_power_by_rate_needed(pAdapter))
2707                 return 0;
2708
2709         return _PHY_GetTxPowerByRate(pAdapter, Band, RFPath, Rate);
2710 }
2711
2712 VOID
2713 PHY_SetTxPowerByRate(
2714         IN      PADAPTER        pAdapter,
2715         IN      u8                      Band,
2716         IN      enum rf_path    RFPath,
2717         IN      u8                      Rate,
2718         IN      s8                      Value
2719 )
2720 {
2721         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
2722         u8      rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate);
2723
2724         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
2725                 RTW_INFO("Invalid band %d in %s\n", Band, __FUNCTION__);
2726                 return;
2727         }
2728         if (RFPath > RF_PATH_D) {
2729                 RTW_INFO("Invalid RfPath %d in %s\n", RFPath, __FUNCTION__);
2730                 return;
2731         }
2732         if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) {
2733                 RTW_INFO("Invalid RateIndex %d in %s\n", rateIndex, __FUNCTION__);
2734                 return;
2735         }
2736
2737         pHalData->TxPwrByRateOffset[Band][RFPath][rateIndex] = Value;
2738 }
2739
2740 u8 phy_check_under_survey_ch(_adapter *adapter)
2741 {
2742         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
2743         _adapter *iface;
2744         struct mlme_ext_priv *mlmeext;
2745         u8 ret = _FALSE;
2746         int i;
2747
2748         for (i = 0; i < dvobj->iface_nums; i++) {
2749                 iface = dvobj->padapters[i];
2750                 if (!iface)
2751                         continue;
2752                 mlmeext = &iface->mlmeextpriv;
2753
2754                 /* check scan state */
2755                 if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE
2756                         && mlmeext_scan_state(mlmeext) != SCAN_COMPLETE
2757                                 && mlmeext_scan_state(mlmeext) != SCAN_BACKING_OP) {
2758                         ret = _TRUE;
2759                 } else if (mlmeext_scan_state(mlmeext) == SCAN_BACKING_OP
2760                         && !mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_TX_RESUME)) {
2761                         ret = _TRUE;
2762                 }
2763         }
2764
2765         return ret;
2766 }
2767
2768 VOID
2769 phy_set_tx_power_level_by_path(
2770         IN      PADAPTER        Adapter,
2771         IN      u8                      channel,
2772         IN      u8                      path
2773 )
2774 {
2775         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
2776         BOOLEAN bIsIn24G = (pHalData->current_band_type == BAND_ON_2_4G);
2777         u8 under_survey_ch = phy_check_under_survey_ch(Adapter);
2778
2779
2780         /* if ( pMgntInfo->RegNByteAccess == 0 ) */
2781         {
2782                 if (bIsIn24G)
2783                         phy_set_tx_power_index_by_rate_section(Adapter, path, channel, CCK);
2784
2785                 phy_set_tx_power_index_by_rate_section(Adapter, path, channel, OFDM);
2786
2787                 if (!under_survey_ch) {
2788                         phy_set_tx_power_index_by_rate_section(Adapter, path, channel, HT_MCS0_MCS7);
2789
2790                         if (IS_HARDWARE_TYPE_JAGUAR(Adapter) || IS_HARDWARE_TYPE_8814A(Adapter))
2791                                 phy_set_tx_power_index_by_rate_section(Adapter, path, channel, VHT_1SSMCS0_1SSMCS9);
2792
2793                         if (pHalData->NumTotalRFPath >= 2) {
2794                                 phy_set_tx_power_index_by_rate_section(Adapter, path, channel, HT_MCS8_MCS15);
2795
2796                                 if (IS_HARDWARE_TYPE_JAGUAR(Adapter) || IS_HARDWARE_TYPE_8814A(Adapter))
2797                                         phy_set_tx_power_index_by_rate_section(Adapter, path, channel, VHT_2SSMCS0_2SSMCS9);
2798
2799                                 if (IS_HARDWARE_TYPE_8814A(Adapter)) {
2800                                         phy_set_tx_power_index_by_rate_section(Adapter, path, channel, HT_MCS16_MCS23);
2801                                         phy_set_tx_power_index_by_rate_section(Adapter, path, channel, VHT_3SSMCS0_3SSMCS9);
2802                                 }
2803                         }
2804                 }
2805         }
2806 }
2807
2808 #ifndef DBG_TX_POWER_IDX
2809 #define DBG_TX_POWER_IDX 0
2810 #endif
2811
2812 VOID
2813 PHY_SetTxPowerIndexByRateArray(
2814         IN      PADAPTER                        pAdapter,
2815         IN      enum rf_path                    RFPath,
2816         IN      enum channel_width      BandWidth,
2817         IN      u8                                      Channel,
2818         IN      u8                                      *Rates,
2819         IN      u8                                      RateArraySize
2820 )
2821 {
2822         u32     powerIndex = 0;
2823         int     i = 0;
2824
2825         for (i = 0; i < RateArraySize; ++i) {
2826 #if DBG_TX_POWER_IDX
2827                 struct txpwr_idx_comp tic;
2828
2829                 powerIndex = rtw_hal_get_tx_power_index(pAdapter, RFPath, Rates[i], BandWidth, Channel, &tic);
2830                 RTW_INFO("TXPWR: [%c][%s]ch:%u, %s %uT, pwr_idx:%u = %u + (%d=%d:%d) + (%d) + (%d)\n"
2831                         , rf_path_char(RFPath), ch_width_str(BandWidth), Channel, MGN_RATE_STR(Rates[i]), tic.ntx_idx + 1
2832                         , powerIndex, tic.base, (tic.by_rate > tic.limit ? tic.limit : tic.by_rate), tic.by_rate, tic.limit, tic.tpt, tic.ebias);
2833 #else
2834                 powerIndex = phy_get_tx_power_index(pAdapter, RFPath, Rates[i], BandWidth, Channel);
2835 #endif
2836                 PHY_SetTxPowerIndex(pAdapter, powerIndex, RFPath, Rates[i]);
2837         }
2838 }
2839
2840 #ifdef CONFIG_TXPWR_LIMIT
2841 const char *const _txpwr_lmt_rs_str[] = {
2842         "CCK",
2843         "OFDM",
2844         "HT",
2845         "VHT",
2846         "UNKNOWN",
2847 };
2848
2849 static s8
2850 phy_GetChannelIndexOfTxPowerLimit(
2851         IN      u8                      Band,
2852         IN      u8                      Channel
2853 )
2854 {
2855         s8      channelIndex = -1;
2856         u8      i = 0;
2857
2858         if (Band == BAND_ON_2_4G)
2859                 channelIndex = Channel - 1;
2860         else if (Band == BAND_ON_5G) {
2861                 for (i = 0; i < CENTER_CH_5G_ALL_NUM; ++i) {
2862                         if (center_ch_5g_all[i] == Channel)
2863                                 channelIndex = i;
2864                 }
2865         } else
2866                 RTW_PRINT("Invalid Band %d in %s\n", Band, __func__);
2867
2868         if (channelIndex == -1)
2869                 RTW_PRINT("Invalid Channel %d of Band %d in %s\n", Channel, Band, __func__);
2870
2871         return channelIndex;
2872 }
2873
2874 static s8 phy_txpwr_ww_lmt_value(_adapter *adapter)
2875 {
2876         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
2877
2878         if (hal_spec->txgi_max == 63)
2879                 return -63;
2880         else if (hal_spec->txgi_max == 127)
2881                 return -128;
2882
2883         rtw_warn_on(1);
2884         return -128;
2885 }
2886
2887 /*
2888 * return txpwr limit absolute value
2889 * hsl_spec->txgi_max is returned when NO limit
2890 */
2891 s8 phy_get_txpwr_lmt_abs(
2892         IN      PADAPTER                        Adapter,
2893         IN      const char                      *regd_name,
2894         IN      BAND_TYPE                       Band,
2895         IN      enum channel_width              bw,
2896         u8 tlrs,
2897         u8 ntx_idx,
2898         u8 cch,
2899         u8 lock
2900 )
2901 {
2902         struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
2903         struct rf_ctl_t *rfctl = adapter_to_rfctl(Adapter);
2904         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(Adapter);
2905         struct hal_spec_t *hal_spec = GET_HAL_SPEC(Adapter);
2906         struct txpwr_lmt_ent *ent = NULL;
2907         _irqL irqL;
2908         _list *cur, *head;
2909         s8 ch_idx;
2910         u8 is_ww_regd = 0;
2911         s8 ww_lmt_val = phy_txpwr_ww_lmt_value(Adapter);
2912         s8 lmt = hal_spec->txgi_max;
2913
2914         if ((Adapter->registrypriv.RegEnableTxPowerLimit == 2 && hal_data->EEPROMRegulatory != 1) ||
2915                 Adapter->registrypriv.RegEnableTxPowerLimit == 0)
2916                 goto exit;
2917
2918         if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) {
2919                 RTW_ERR("%s invalid band:%u\n", __func__, Band);
2920                 rtw_warn_on(1);
2921                 goto exit;
2922         }
2923
2924         if (Band == BAND_ON_5G  && tlrs == TXPWR_LMT_RS_CCK) {
2925                 RTW_ERR("5G has no CCK\n");
2926                 goto exit;
2927         }
2928
2929         if (lock)
2930                 _enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
2931
2932         if (!regd_name) /* no regd_name specified, use currnet */
2933                 regd_name = rfctl->regd_name;
2934
2935         if (rfctl->txpwr_regd_num == 0
2936                 || strcmp(regd_name, regd_str(TXPWR_LMT_NONE)) == 0)
2937                 goto release_lock;
2938
2939         if (strcmp(regd_name, regd_str(TXPWR_LMT_WW)) == 0)
2940                 is_ww_regd = 1;
2941
2942         if (!is_ww_regd) {
2943                 ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_name);
2944                 if (!ent)
2945                         goto release_lock;
2946         }
2947
2948         ch_idx = phy_GetChannelIndexOfTxPowerLimit(Band, cch);
2949         if (ch_idx == -1)
2950                 goto release_lock;
2951
2952         if (Band == BAND_ON_2_4G) {
2953                 if (!is_ww_regd) {
2954                         lmt = ent->lmt_2g[bw][tlrs][ch_idx][ntx_idx];
2955                         if (lmt != ww_lmt_val)
2956                                 goto release_lock;
2957                 }
2958
2959                 /* search for min value for WW regd or WW limit */
2960                 lmt = hal_spec->txgi_max;
2961                 head = &rfctl->txpwr_lmt_list;
2962                 cur = get_next(head);
2963                 while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
2964                         ent = LIST_CONTAINOR(cur, struct txpwr_lmt_ent, list);
2965                         cur = get_next(cur);
2966                         if (ent->lmt_2g[bw][tlrs][ch_idx][ntx_idx] != ww_lmt_val)
2967                                 lmt = rtw_min(lmt, ent->lmt_2g[bw][tlrs][ch_idx][ntx_idx]);
2968                 }
2969         }
2970         #ifdef CONFIG_IEEE80211_BAND_5GHZ
2971         else if (Band == BAND_ON_5G) {
2972                 if (!is_ww_regd) {
2973                         lmt = ent->lmt_5g[bw][tlrs - 1][ch_idx][ntx_idx];
2974                         if (lmt != ww_lmt_val)
2975                                 goto release_lock;
2976                 }
2977
2978                 /* search for min value for WW regd or WW limit */
2979                 lmt = hal_spec->txgi_max;
2980                 head = &rfctl->txpwr_lmt_list;
2981                 cur = get_next(head);
2982                 while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
2983                         ent = LIST_CONTAINOR(cur, struct txpwr_lmt_ent, list);
2984                         cur = get_next(cur);
2985                         if (ent->lmt_5g[bw][tlrs - 1][ch_idx][ntx_idx] != ww_lmt_val)
2986                                 lmt = rtw_min(lmt, ent->lmt_5g[bw][tlrs - 1][ch_idx][ntx_idx]);
2987                 }
2988         }
2989         #endif
2990
2991 release_lock:
2992         if (lock)
2993                 _exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
2994
2995 exit:
2996         return lmt;
2997 }
2998
2999 /*
3000 * return txpwr limit diff value
3001 * hal_spec->txgi_max is returned when NO limit
3002 */
3003 inline s8 phy_get_txpwr_lmt(_adapter *adapter
3004         , const char *regd_name
3005         , BAND_TYPE band, enum channel_width bw
3006         , u8 rfpath, u8 rs, u8 ntx_idx, u8 cch, u8 lock
3007 )
3008 {
3009         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3010         u8 tlrs;
3011         s8 lmt = hal_spec->txgi_max;
3012
3013         if (IS_CCK_RATE_SECTION(rs))
3014                 tlrs = TXPWR_LMT_RS_CCK;
3015         else if (IS_OFDM_RATE_SECTION(rs))
3016                 tlrs = TXPWR_LMT_RS_OFDM;
3017         else if (IS_HT_RATE_SECTION(rs))
3018                 tlrs = TXPWR_LMT_RS_HT;
3019         else if (IS_VHT_RATE_SECTION(rs))
3020                 tlrs = TXPWR_LMT_RS_VHT;
3021         else {
3022                 RTW_ERR("%s invalid rs %u\n", __func__, rs);
3023                 rtw_warn_on(1);
3024                 goto exit;
3025         }
3026
3027         lmt = phy_get_txpwr_lmt_abs(adapter, regd_name, band, bw, tlrs, ntx_idx, cch, lock);
3028
3029         if (lmt != hal_spec->txgi_max) {
3030                 /* return diff value */
3031                 lmt = lmt - PHY_GetTxPowerByRateBase(adapter, band, rfpath, rs);
3032         }
3033
3034 exit:
3035         return lmt;
3036 }
3037
3038 /*
3039 * May search for secondary channels for min limit
3040 * return txpwr limit diff value
3041 */
3042 s8
3043 PHY_GetTxPowerLimit(_adapter *adapter
3044         , const char *regd_name
3045         , BAND_TYPE band, enum channel_width bw
3046         , u8 rfpath, u8 rate, u8 ntx_idx, u8 cch)
3047 {
3048         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3049         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3050         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3051         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3052         BOOLEAN no_sc = _FALSE;
3053         s8 tlrs = -1, rs = -1;
3054         s8 lmt = hal_spec->txgi_max;
3055         u8 tmp_cch = 0;
3056         u8 tmp_bw;
3057         u8 bw_bmp = 0;
3058         s8 min_lmt = hal_spec->txgi_max;
3059         u8 final_bw = bw, final_cch = cch;
3060         _irqL irqL;
3061
3062 #ifdef CONFIG_MP_INCLUDED
3063         /* MP mode channel don't use secondary channel */
3064         if (rtw_mp_mode_check(adapter) == _TRUE)
3065                 no_sc = _TRUE;
3066 #endif
3067         if (IS_CCK_RATE(rate)) {
3068                 tlrs = TXPWR_LMT_RS_CCK;
3069                 rs = CCK;
3070         } else if (IS_OFDM_RATE(rate)) {
3071                 tlrs = TXPWR_LMT_RS_OFDM;
3072                 rs = OFDM;
3073         } else if (IS_HT_RATE(rate)) {
3074                 tlrs = TXPWR_LMT_RS_HT;
3075                 rs = HT_1SS + (IS_HT1SS_RATE(rate) ? 0 : IS_HT2SS_RATE(rate) ? 1 : IS_HT3SS_RATE(rate) ? 2 : IS_HT4SS_RATE(rate) ? 3 : 0);
3076         } else if (IS_VHT_RATE(rate)) {
3077                 tlrs = TXPWR_LMT_RS_VHT;
3078                 rs = VHT_1SS + (IS_VHT1SS_RATE(rate) ? 0 : IS_VHT2SS_RATE(rate) ? 1 : IS_VHT3SS_RATE(rate) ? 2 : IS_VHT4SS_RATE(rate) ? 3 : 0);
3079         } else {
3080                 RTW_ERR("%s invalid rate 0x%x\n", __func__, rate);
3081                 rtw_warn_on(1);
3082                 goto exit;
3083         }
3084
3085         if (no_sc == _TRUE) {
3086                 /* use the input center channel and bandwidth directly */
3087                 tmp_cch = cch;
3088                 bw_bmp = ch_width_to_bw_cap(bw);
3089         } else {
3090                 /*
3091                 * find the possible tx bandwidth bmp for this rate, and then will get center channel for each bandwidth
3092                 * if no possible tx bandwidth bmp, select valid bandwidth up to current RF bandwidth into bmp
3093                 */
3094                 if (tlrs == TXPWR_LMT_RS_CCK || tlrs == TXPWR_LMT_RS_OFDM)
3095                         bw_bmp = BW_CAP_20M; /* CCK, OFDM only BW 20M */
3096                 else if (tlrs == TXPWR_LMT_RS_HT) {
3097                         bw_bmp = rtw_get_tx_bw_bmp_of_ht_rate(dvobj, rate, bw);
3098                         if (bw_bmp == 0)
3099                                 bw_bmp = ch_width_to_bw_cap(bw > CHANNEL_WIDTH_40 ? CHANNEL_WIDTH_40 : bw);
3100                 } else if (tlrs == TXPWR_LMT_RS_VHT) {
3101                         bw_bmp = rtw_get_tx_bw_bmp_of_vht_rate(dvobj, rate, bw);
3102                         if (bw_bmp == 0)
3103                                 bw_bmp = ch_width_to_bw_cap(bw > CHANNEL_WIDTH_160 ? CHANNEL_WIDTH_160 : bw);
3104                 } else
3105                         rtw_warn_on(1);
3106         }
3107
3108         if (bw_bmp == 0)
3109                 goto exit;
3110
3111         _enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
3112
3113         /* loop for each possible tx bandwidth to find minimum limit */
3114         for (tmp_bw = CHANNEL_WIDTH_20; tmp_bw <= bw; tmp_bw++) {
3115                 if (!(ch_width_to_bw_cap(tmp_bw) & bw_bmp))
3116                         continue;
3117
3118                 if (no_sc == _FALSE) {
3119                         if (tmp_bw == CHANNEL_WIDTH_20)
3120                                 tmp_cch = hal_data->cch_20;
3121                         else if (tmp_bw == CHANNEL_WIDTH_40)
3122                                 tmp_cch = hal_data->cch_40;
3123                         else if (tmp_bw == CHANNEL_WIDTH_80)
3124                                 tmp_cch = hal_data->cch_80;
3125                         else {
3126                                 tmp_cch = 0;
3127                                 rtw_warn_on(1);
3128                         }
3129                 }
3130
3131                 lmt = phy_get_txpwr_lmt_abs(adapter, regd_name, band, tmp_bw, tlrs, ntx_idx, tmp_cch, 0);
3132
3133                 if (min_lmt >= lmt) {
3134                         min_lmt = lmt;
3135                         final_cch = tmp_cch;
3136                         final_bw = tmp_bw;
3137                 }
3138
3139         }
3140
3141         _exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
3142
3143         if (min_lmt != hal_spec->txgi_max) {
3144                 /* return diff value */
3145                 min_lmt = min_lmt - PHY_GetTxPowerByRateBase(adapter, band, rfpath, rs);
3146         }
3147
3148 exit:
3149
3150         if (0) {
3151                 if (final_bw != bw && (IS_HT_RATE(rate) || IS_VHT_RATE(rate)))
3152                         RTW_INFO("%s min_lmt: %s ch%u -> %s ch%u\n"
3153                                 , MGN_RATE_STR(rate)
3154                                 , ch_width_str(bw), cch
3155                                 , ch_width_str(final_bw), final_cch);
3156         }
3157
3158         return min_lmt;
3159 }
3160
3161 static void phy_txpwr_lmt_cck_ofdm_mt_chk(_adapter *adapter)
3162 {
3163         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3164         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3165         struct txpwr_lmt_ent *ent;
3166         _list *cur, *head;
3167         u8 channel, tlrs, ntx_idx;
3168
3169         rfctl->txpwr_lmt_2g_cck_ofdm_state = 0;
3170 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3171         rfctl->txpwr_lmt_5g_cck_ofdm_state = 0;
3172 #endif
3173
3174         head = &rfctl->txpwr_lmt_list;
3175         cur = get_next(head);
3176
3177         while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
3178                 ent = LIST_CONTAINOR(cur, struct txpwr_lmt_ent, list);
3179                 cur = get_next(cur);
3180
3181                 /* check 2G CCK, OFDM state*/
3182                 for (tlrs = TXPWR_LMT_RS_CCK; tlrs <= TXPWR_LMT_RS_OFDM; tlrs++) {
3183                         for (ntx_idx = RF_1TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3184                                 for (channel = 0; channel < CENTER_CH_2G_NUM; ++channel) {
3185                                         if (ent->lmt_2g[CHANNEL_WIDTH_20][tlrs][channel][ntx_idx] != hal_spec->txgi_max) {
3186                                                 if (tlrs == TXPWR_LMT_RS_CCK)
3187                                                         rfctl->txpwr_lmt_2g_cck_ofdm_state |= TXPWR_LMT_HAS_CCK_1T << ntx_idx;
3188                                                 else
3189                                                         rfctl->txpwr_lmt_2g_cck_ofdm_state |= TXPWR_LMT_HAS_OFDM_1T << ntx_idx;
3190                                                 break;
3191                                         }
3192                                 }
3193                         }
3194                 }
3195
3196                 /* if 2G OFDM multi-TX is not defined, reference HT20 */
3197                 for (channel = 0; channel < CENTER_CH_2G_NUM; ++channel) {
3198                         for (ntx_idx = RF_2TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3199                                 if (rfctl->txpwr_lmt_2g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx))
3200                                         continue;
3201                                 ent->lmt_2g[CHANNEL_WIDTH_20][TXPWR_LMT_RS_OFDM][channel][ntx_idx] =
3202                                         ent->lmt_2g[CHANNEL_WIDTH_20][TXPWR_LMT_RS_HT][channel][ntx_idx];
3203                         }
3204                 }
3205
3206 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3207                 /* check 5G OFDM state*/
3208                 for (ntx_idx = RF_1TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3209                         for (channel = 0; channel < CENTER_CH_5G_ALL_NUM; ++channel) {
3210                                 if (ent->lmt_5g[CHANNEL_WIDTH_20][TXPWR_LMT_RS_OFDM - 1][channel][ntx_idx] != hal_spec->txgi_max) {
3211                                         rfctl->txpwr_lmt_5g_cck_ofdm_state |= TXPWR_LMT_HAS_OFDM_1T << ntx_idx;
3212                                         break;
3213                                 }
3214                         }
3215                 }
3216
3217                 for (channel = 0; channel < CENTER_CH_5G_ALL_NUM; ++channel) {
3218                         for (ntx_idx = RF_2TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3219                                 if (rfctl->txpwr_lmt_5g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx))
3220                                         continue;
3221                                 /* if 5G OFDM multi-TX is not defined, reference HT20 */
3222                                 ent->lmt_5g[CHANNEL_WIDTH_20][TXPWR_LMT_RS_OFDM - 1][channel][ntx_idx] =
3223                                         ent->lmt_5g[CHANNEL_WIDTH_20][TXPWR_LMT_RS_HT - 1][channel][ntx_idx];
3224                         }
3225                 }
3226 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
3227         }
3228 }
3229
3230 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3231 static void phy_txpwr_lmt_cross_ref_ht_vht(_adapter *adapter)
3232 {
3233         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3234         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3235         struct txpwr_lmt_ent *ent;
3236         _list *cur, *head;
3237         u8 bw, channel, tlrs, ref_tlrs, ntx_idx;
3238         int ht_ref_vht_5g_20_40 = 0;
3239         int vht_ref_ht_5g_20_40 = 0;
3240         int ht_has_ref_5g_20_40 = 0;
3241         int vht_has_ref_5g_20_40 = 0;
3242
3243         rfctl->txpwr_lmt_5g_20_40_ref = 0;
3244
3245         head = &rfctl->txpwr_lmt_list;
3246         cur = get_next(head);
3247
3248         while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
3249                 ent = LIST_CONTAINOR(cur, struct txpwr_lmt_ent, list);
3250                 cur = get_next(cur);
3251
3252                 for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; ++bw) {
3253
3254                         for (channel = 0; channel < CENTER_CH_5G_ALL_NUM; ++channel) {
3255
3256                                 for (tlrs = TXPWR_LMT_RS_HT; tlrs < TXPWR_LMT_RS_NUM; ++tlrs) {
3257
3258                                         /* 5G 20M 40M VHT and HT can cross reference */
3259                                         if (bw == CHANNEL_WIDTH_20 || bw == CHANNEL_WIDTH_40) {
3260                                                 if (tlrs == TXPWR_LMT_RS_HT)
3261                                                         ref_tlrs = TXPWR_LMT_RS_VHT;
3262                                                 else if (tlrs == TXPWR_LMT_RS_VHT)
3263                                                         ref_tlrs = TXPWR_LMT_RS_HT;
3264                                                 else
3265                                                         continue;
3266
3267                                                 for (ntx_idx = RF_1TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3268
3269                                                         if (ent->lmt_5g[bw][ref_tlrs - 1][channel][ntx_idx] == hal_spec->txgi_max)
3270                                                                 continue;
3271
3272                                                         if (tlrs == TXPWR_LMT_RS_HT)
3273                                                                 ht_has_ref_5g_20_40++;
3274                                                         else if (tlrs == TXPWR_LMT_RS_VHT)
3275                                                                 vht_has_ref_5g_20_40++;
3276                                                         else
3277                                                                 continue;
3278
3279                                                         if (ent->lmt_5g[bw][tlrs - 1][channel][ntx_idx] != hal_spec->txgi_max)
3280                                                                 continue;
3281
3282                                                         if (tlrs == TXPWR_LMT_RS_HT && ref_tlrs == TXPWR_LMT_RS_VHT)
3283                                                                 ht_ref_vht_5g_20_40++;
3284                                                         else if (tlrs == TXPWR_LMT_RS_VHT && ref_tlrs == TXPWR_LMT_RS_HT)
3285                                                                 vht_ref_ht_5g_20_40++;
3286
3287                                                         if (0)
3288                                                                 RTW_INFO("reg:%s, bw:%u, ch:%u, %s-%uT ref %s-%uT\n"
3289                                                                         , ent->regd_name, bw, channel
3290                                                                         , txpwr_lmt_rs_str(tlrs), ntx_idx + 1
3291                                                                         , txpwr_lmt_rs_str(ref_tlrs), ntx_idx + 1);
3292
3293                                                         ent->lmt_5g[bw][tlrs - 1][channel][ntx_idx] =
3294                                                                 ent->lmt_5g[bw][ref_tlrs - 1][channel][ntx_idx];
3295                                                 }
3296                                         }
3297
3298                                 }
3299                         }
3300                 }
3301         }
3302
3303         if (0) {
3304                 RTW_INFO("ht_ref_vht_5g_20_40:%d, ht_has_ref_5g_20_40:%d\n", ht_ref_vht_5g_20_40, ht_has_ref_5g_20_40);
3305                 RTW_INFO("vht_ref_ht_5g_20_40:%d, vht_has_ref_5g_20_40:%d\n", vht_ref_ht_5g_20_40, vht_has_ref_5g_20_40);
3306         }
3307
3308         /* 5G 20M&40M HT all come from VHT*/
3309         if (ht_ref_vht_5g_20_40 && ht_has_ref_5g_20_40 == ht_ref_vht_5g_20_40)
3310                 rfctl->txpwr_lmt_5g_20_40_ref |= TXPWR_LMT_REF_HT_FROM_VHT;
3311
3312         /* 5G 20M&40M VHT all come from HT*/
3313         if (vht_ref_ht_5g_20_40 && vht_has_ref_5g_20_40 == vht_ref_ht_5g_20_40)
3314                 rfctl->txpwr_lmt_5g_20_40_ref |= TXPWR_LMT_REF_VHT_FROM_HT;
3315 }
3316 #endif /* CONFIG_IEEE80211_BAND_5GHZ */
3317
3318 #ifndef DBG_TXPWR_LMT_BAND_CHK
3319 #define DBG_TXPWR_LMT_BAND_CHK 0
3320 #endif
3321
3322 #if DBG_TXPWR_LMT_BAND_CHK
3323 /* check if larger bandwidth limit is less than smaller bandwidth for HT & VHT rate */
3324 void phy_txpwr_limit_bandwidth_chk(_adapter *adapter)
3325 {
3326         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3327         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3328         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3329         u8 band, bw, path, tlrs, ntx_idx, cch, offset, scch;
3330         u8 ch_num, n, i;
3331
3332         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
3333                 if (!hal_is_band_support(adapter, band))
3334                         continue;
3335
3336                 for (bw = CHANNEL_WIDTH_40; bw <= CHANNEL_WIDTH_80; bw++) {
3337                         if (bw >= CHANNEL_WIDTH_160)
3338                                 continue;
3339                         if (band == BAND_ON_2_4G && bw >= CHANNEL_WIDTH_80)
3340                                 continue;
3341
3342                         if (band == BAND_ON_2_4G)
3343                                 ch_num = center_chs_2g_num(bw);
3344                         else
3345                                 ch_num = center_chs_5g_num(bw);
3346
3347                         if (ch_num == 0) {
3348                                 rtw_warn_on(1);
3349                                 break;
3350                         }
3351
3352                         for (tlrs = TXPWR_LMT_RS_HT; tlrs < TXPWR_LMT_RS_NUM; tlrs++) {
3353
3354                                 if (band == BAND_ON_2_4G && tlrs == TXPWR_LMT_RS_VHT)
3355                                         continue;
3356                                 if (band == BAND_ON_5G && tlrs == TXPWR_LMT_RS_CCK)
3357                                         continue;
3358                                 if (bw > CHANNEL_WIDTH_20 && (tlrs == TXPWR_LMT_RS_CCK || tlrs == TXPWR_LMT_RS_OFDM))
3359                                         continue;
3360                                 if (bw > CHANNEL_WIDTH_40 && tlrs == TXPWR_LMT_RS_HT)
3361                                         continue;
3362                                 if (tlrs == TXPWR_LMT_RS_VHT && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
3363                                         continue;
3364
3365                                 for (ntx_idx = RF_1TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
3366                                         struct txpwr_lmt_ent *ent;
3367                                         _list *cur, *head;
3368
3369                                         if (ntx_idx >= hal_spec->tx_nss_num)
3370                                                 continue;
3371
3372                                         /* bypass CCK multi-TX is not defined */
3373                                         if (tlrs == TXPWR_LMT_RS_CCK && ntx_idx > RF_1TX) {
3374                                                 if (band == BAND_ON_2_4G
3375                                                         && !(rfctl->txpwr_lmt_2g_cck_ofdm_state & (TXPWR_LMT_HAS_CCK_1T << ntx_idx)))
3376                                                         continue;
3377                                         }
3378
3379                                         /* bypass OFDM multi-TX is not defined */
3380                                         if (tlrs == TXPWR_LMT_RS_OFDM && ntx_idx > RF_1TX) {
3381                                                 if (band == BAND_ON_2_4G
3382                                                         && !(rfctl->txpwr_lmt_2g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx)))
3383                                                         continue;
3384                                                 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3385                                                 if (band == BAND_ON_5G
3386                                                         && !(rfctl->txpwr_lmt_5g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx)))
3387                                                         continue;
3388                                                 #endif
3389                                         }
3390
3391                                         /* bypass 5G 20M, 40M pure reference */
3392                                         #ifdef CONFIG_IEEE80211_BAND_5GHZ
3393                                         if (band == BAND_ON_5G && (bw == CHANNEL_WIDTH_20 || bw == CHANNEL_WIDTH_40)) {
3394                                                 if (rfctl->txpwr_lmt_5g_20_40_ref == TXPWR_LMT_REF_HT_FROM_VHT) {
3395                                                         if (tlrs == TXPWR_LMT_RS_HT)
3396                                                                 continue;
3397                                                 } else if (rfctl->txpwr_lmt_5g_20_40_ref == TXPWR_LMT_REF_VHT_FROM_HT) {
3398                                                         if (tlrs == TXPWR_LMT_RS_VHT && bw <= CHANNEL_WIDTH_40)
3399                                                                 continue;
3400                                                 }
3401                                         }
3402                                         #endif
3403
3404                                         for (n = 0; n < ch_num; n++) {
3405                                                 u8 cch_by_bw[3];
3406                                                 u8 offset_by_bw; /* bitmap, 0 for lower, 1 for upper */
3407                                                 u8 bw_pos;
3408                                                 s8 lmt[3];
3409
3410                                                 if (band == BAND_ON_2_4G)
3411                                                         cch = center_chs_2g(bw, n);
3412                                                 else
3413                                                         cch = center_chs_5g(bw, n);
3414
3415                                                 if (cch == 0) {
3416                                                         rtw_warn_on(1);
3417                                                         break;
3418                                                 }
3419
3420                                                 _rtw_memset(cch_by_bw, 0, 3);
3421                                                 cch_by_bw[bw] = cch;
3422                                                 offset_by_bw = 0x01;
3423
3424                                                 do {
3425                                                         for (bw_pos = bw; bw_pos >= CHANNEL_WIDTH_40; bw_pos--)
3426                                                                 cch_by_bw[bw_pos - 1] = rtw_get_scch_by_cch_offset(cch_by_bw[bw_pos], bw_pos, offset_by_bw & BIT(bw_pos) ? HAL_PRIME_CHNL_OFFSET_UPPER : HAL_PRIME_CHNL_OFFSET_LOWER);
3427
3428                                                         head = &rfctl->txpwr_lmt_list;
3429                                                         cur = get_next(head);
3430                                                         while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
3431                                                                 ent = LIST_CONTAINOR(cur, struct txpwr_lmt_ent, list);
3432                                                                 cur = get_next(cur);
3433
3434                                                                 for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--)
3435                                                                         lmt[bw_pos] = phy_get_txpwr_lmt_abs(adapter, ent->regd_name, band, bw_pos, tlrs, ntx_idx, cch_by_bw[bw_pos], 0);
3436
3437                                                                 for (bw_pos = bw; bw_pos > CHANNEL_WIDTH_20; bw_pos--)
3438                                                                         if (lmt[bw_pos] > lmt[bw_pos - 1])
3439                                                                                 break;
3440                                                                 if (bw_pos == CHANNEL_WIDTH_20)
3441                                                                         continue;
3442
3443                                                                 RTW_PRINT_SEL(RTW_DBGDUMP, "[%s][%s][%s][%uT][%-4s] cch:"
3444                                                                         , band_str(band)
3445                                                                         , ch_width_str(bw)
3446                                                                         , txpwr_lmt_rs_str(tlrs)
3447                                                                         , ntx_idx + 1
3448                                                                         , ent->regd_name
3449                                                                 );
3450                                                                 for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--)
3451                                                                         _RTW_PRINT_SEL(RTW_DBGDUMP, "%03u ", cch_by_bw[bw_pos]);
3452                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "limit:");
3453                                                                 for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--) {
3454                                                                         if (lmt[bw_pos] == hal_spec->txgi_max)
3455                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "N/A ");
3456                                                                         else if (lmt[bw_pos] > -hal_spec->txgi_pdbm && lmt[bw_pos] < 0) /* -1 < value < 0 */
3457                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "-0.%d", (rtw_abs(lmt[bw_pos]) % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
3458                                                                         else if (lmt[bw_pos] % hal_spec->txgi_pdbm)
3459                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "%2d.%d ", lmt[bw_pos] / hal_spec->txgi_pdbm, (rtw_abs(lmt[bw_pos]) % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
3460                                                                         else
3461                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "%2d ", lmt[bw_pos] / hal_spec->txgi_pdbm);
3462                                                                 }
3463                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "\n");
3464                                                         }
3465                                                         for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--)
3466                                                                 lmt[bw_pos] = phy_get_txpwr_lmt_abs(adapter, regd_str(TXPWR_LMT_WW), band, bw_pos, tlrs, ntx_idx, cch_by_bw[bw_pos], 0);
3467
3468                                                         for (bw_pos = bw; bw_pos > CHANNEL_WIDTH_20; bw_pos--)
3469                                                                 if (lmt[bw_pos] > lmt[bw_pos - 1])
3470                                                                         break;
3471                                                         if (bw_pos != CHANNEL_WIDTH_20) {
3472                                                                 RTW_PRINT_SEL(RTW_DBGDUMP, "[%s][%s][%s][%uT][%-4s] cch:"
3473                                                                         , band_str(band)
3474                                                                         , ch_width_str(bw)
3475                                                                         , txpwr_lmt_rs_str(tlrs)
3476                                                                         , ntx_idx + 1
3477                                                                         , regd_str(TXPWR_LMT_WW)
3478                                                                 );
3479                                                                 for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--)
3480                                                                         _RTW_PRINT_SEL(RTW_DBGDUMP, "%03u ", cch_by_bw[bw_pos]);
3481                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "limit:");
3482                                                                 for (bw_pos = bw; bw_pos < CHANNEL_WIDTH_160; bw_pos--) {
3483                                                                         if (lmt[bw_pos] == hal_spec->txgi_max)
3484                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "N/A ");
3485                                                                         else if (lmt[bw_pos] > -hal_spec->txgi_pdbm && lmt[bw_pos] < 0) /* -1 < value < 0 */
3486                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "-0.%d", (rtw_abs(lmt[bw_pos]) % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
3487                                                                         else if (lmt[bw_pos] % hal_spec->txgi_pdbm)
3488                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "%2d.%d ", lmt[bw_pos] / hal_spec->txgi_pdbm, (rtw_abs(lmt[bw_pos]) % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
3489                                                                         else
3490                                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "%2d ", lmt[bw_pos] / hal_spec->txgi_pdbm);
3491                                                                 }
3492                                                                 _RTW_PRINT_SEL(RTW_DBGDUMP, "\n");
3493                                                         }
3494
3495                                                         offset_by_bw += 2;
3496                                                         if (offset_by_bw & BIT(bw + 1))
3497                                                                 break;
3498                                                 } while (1); /* loop for all ch combinations */
3499                                         } /* loop for center channels */
3500                                 } /* loop fo each ntx_idx */
3501                         } /* loop for tlrs */
3502                 } /* loop for bandwidth */
3503         } /* loop for band */
3504 }
3505 #endif /* DBG_TXPWR_LMT_BAND_CHK */
3506
3507 static void phy_txpwr_lmt_post_hdl(_adapter *adapter)
3508 {
3509         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3510         _irqL irqL;
3511
3512         _enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
3513
3514 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3515         if (IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
3516                 phy_txpwr_lmt_cross_ref_ht_vht(adapter);
3517 #endif
3518         phy_txpwr_lmt_cck_ofdm_mt_chk(adapter);
3519
3520 #if DBG_TXPWR_LMT_BAND_CHK
3521         phy_txpwr_limit_bandwidth_chk(adapter);
3522 #endif
3523
3524         _exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
3525 }
3526
3527 BOOLEAN
3528 GetS1ByteIntegerFromStringInDecimal(
3529         IN              char    *str,
3530         IN OUT  s8              *val
3531 )
3532 {
3533         u8 negative = 0;
3534         u16 i = 0;
3535
3536         *val = 0;
3537
3538         while (str[i] != '\0') {
3539                 if (i == 0 && (str[i] == '+' || str[i] == '-')) {
3540                         if (str[i] == '-')
3541                                 negative = 1;
3542                 } else if (str[i] >= '0' && str[i] <= '9') {
3543                         *val *= 10;
3544                         *val += (str[i] - '0');
3545                 } else
3546                         return _FALSE;
3547                 ++i;
3548         }
3549
3550         if (negative)
3551                 *val = -*val;
3552
3553         return _TRUE;
3554 }
3555 #endif /* CONFIG_TXPWR_LIMIT */
3556
3557 /*
3558 * phy_set_tx_power_limit - Parsing TX power limit from phydm array, called by odm_ConfigBB_TXPWR_LMT_XXX in phydm
3559 */
3560 VOID
3561 phy_set_tx_power_limit(
3562         IN      struct dm_struct                *pDM_Odm,
3563         IN      u8                              *Regulation,
3564         IN      u8                              *Band,
3565         IN      u8                              *Bandwidth,
3566         IN      u8                              *RateSection,
3567         IN      u8                              *ntx,
3568         IN      u8                              *Channel,
3569         IN      u8                              *PowerLimit
3570 )
3571 {
3572 #ifdef CONFIG_TXPWR_LIMIT
3573         PADAPTER Adapter = pDM_Odm->adapter;
3574         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
3575         struct hal_spec_t *hal_spec = GET_HAL_SPEC(Adapter);
3576         u8 band = 0, bandwidth = 0, tlrs = 0, channel;
3577         u8 ntx_idx;
3578         s8 powerLimit = 0, prevPowerLimit, channelIndex;
3579         s8 ww_lmt_val = phy_txpwr_ww_lmt_value(Adapter);
3580
3581         if (0)
3582                 RTW_INFO("Index of power limit table [regulation %s][band %s][bw %s][rate section %s][ntx %s][chnl %s][val %s]\n"
3583                         , Regulation, Band, Bandwidth, RateSection, ntx, Channel, PowerLimit);
3584
3585         if (GetU1ByteIntegerFromStringInDecimal((char *)Channel, &channel) == _FALSE
3586                 || GetS1ByteIntegerFromStringInDecimal((char *)PowerLimit, &powerLimit) == _FALSE
3587         ) {
3588                 RTW_PRINT("Illegal index of power limit table [ch %s][val %s]\n", Channel, PowerLimit);
3589                 return;
3590         }
3591
3592         if (powerLimit != ww_lmt_val) {
3593                 if (powerLimit < -hal_spec->txgi_max || powerLimit > hal_spec->txgi_max)
3594                         RTW_PRINT("Illegal power limit value [ch %s][val %s]\n", Channel, PowerLimit);
3595
3596                 if (powerLimit > hal_spec->txgi_max)
3597                         powerLimit = hal_spec->txgi_max;
3598                 else if (powerLimit < -hal_spec->txgi_max)
3599                         powerLimit =  ww_lmt_val + 1;
3600         }
3601
3602         if (eqNByte(RateSection, (u8 *)("CCK"), 3))
3603                 tlrs = TXPWR_LMT_RS_CCK;
3604         else if (eqNByte(RateSection, (u8 *)("OFDM"), 4))
3605                 tlrs = TXPWR_LMT_RS_OFDM;
3606         else if (eqNByte(RateSection, (u8 *)("HT"), 2))
3607                 tlrs = TXPWR_LMT_RS_HT;
3608         else if (eqNByte(RateSection, (u8 *)("VHT"), 3))
3609                 tlrs = TXPWR_LMT_RS_VHT;
3610         else {
3611                 RTW_PRINT("Wrong rate section:%s\n", RateSection);
3612                 return;
3613         }
3614
3615         if (eqNByte(ntx, (u8 *)("1T"), 2))
3616                 ntx_idx = RF_1TX;
3617         else if (eqNByte(ntx, (u8 *)("2T"), 2))
3618                 ntx_idx = RF_2TX;
3619         else if (eqNByte(ntx, (u8 *)("3T"), 2))
3620                 ntx_idx = RF_3TX;
3621         else if (eqNByte(ntx, (u8 *)("4T"), 2))
3622                 ntx_idx = RF_4TX;
3623         else {
3624                 RTW_PRINT("Wrong tx num:%s\n", ntx);
3625                 return;
3626         }
3627
3628         if (eqNByte(Bandwidth, (u8 *)("20M"), 3))
3629                 bandwidth = CHANNEL_WIDTH_20;
3630         else if (eqNByte(Bandwidth, (u8 *)("40M"), 3))
3631                 bandwidth = CHANNEL_WIDTH_40;
3632         else if (eqNByte(Bandwidth, (u8 *)("80M"), 3))
3633                 bandwidth = CHANNEL_WIDTH_80;
3634         else if (eqNByte(Bandwidth, (u8 *)("160M"), 4))
3635                 bandwidth = CHANNEL_WIDTH_160;
3636         else {
3637                 RTW_PRINT("unknown bandwidth: %s\n", Bandwidth);
3638                 return;
3639         }
3640
3641         if (eqNByte(Band, (u8 *)("2.4G"), 4)) {
3642                 band = BAND_ON_2_4G;
3643                 channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_2_4G, channel);
3644
3645                 if (channelIndex == -1) {
3646                         RTW_PRINT("unsupported channel: %d at 2.4G\n", channel);
3647                         return;
3648                 }
3649
3650                 if (bandwidth >= MAX_2_4G_BANDWIDTH_NUM) {
3651                         RTW_PRINT("unsupported bandwidth: %s at 2.4G\n", Bandwidth);
3652                         return;
3653                 }
3654
3655                 rtw_txpwr_lmt_add(adapter_to_rfctl(Adapter), Regulation, band, bandwidth, tlrs, ntx_idx, channelIndex, powerLimit);
3656         }
3657 #ifdef CONFIG_IEEE80211_BAND_5GHZ
3658         else if (eqNByte(Band, (u8 *)("5G"), 2)) {
3659                 band = BAND_ON_5G;
3660                 channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_5G, channel);
3661
3662                 if (channelIndex == -1) {
3663                         RTW_PRINT("unsupported channel: %d at 5G\n", channel);
3664                         return;
3665                 }
3666
3667                 rtw_txpwr_lmt_add(adapter_to_rfctl(Adapter), Regulation, band, bandwidth, tlrs, ntx_idx, channelIndex, powerLimit);
3668         }
3669 #endif
3670         else {
3671                 RTW_PRINT("unknown/unsupported band:%s\n", Band);
3672                 return;
3673         }
3674 #endif
3675 }
3676
3677 u8
3678 phy_get_tx_power_index(
3679         IN      PADAPTER                        pAdapter,
3680         IN      enum rf_path                    RFPath,
3681         IN      u8                                      Rate,
3682         IN      enum channel_width      BandWidth,
3683         IN      u8                                      Channel
3684 )
3685 {
3686         return rtw_hal_get_tx_power_index(pAdapter, RFPath, Rate, BandWidth, Channel, NULL);
3687 }
3688
3689 VOID
3690 PHY_SetTxPowerIndex(
3691         IN      PADAPTER                pAdapter,
3692         IN      u32                             PowerIndex,
3693         IN      enum rf_path            RFPath,
3694         IN      u8                              Rate
3695 )
3696 {
3697         rtw_hal_set_tx_power_index(pAdapter, PowerIndex, RFPath, Rate);
3698 }
3699
3700 void dump_tx_power_idx_title(void *sel, _adapter *adapter)
3701 {
3702         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3703         u8 bw = hal_data->current_channel_bw;
3704
3705         RTW_PRINT_SEL(sel, "%s", ch_width_str(bw));
3706         if (bw >= CHANNEL_WIDTH_80)
3707                 _RTW_PRINT_SEL(sel, ", cch80:%u", hal_data->cch_80);
3708         if (bw >= CHANNEL_WIDTH_40)
3709                 _RTW_PRINT_SEL(sel, ", cch40:%u", hal_data->cch_40);
3710         _RTW_PRINT_SEL(sel, ", cch20:%u\n", hal_data->cch_20);
3711
3712         RTW_PRINT_SEL(sel, "%-4s %-9s %2s %-3s %-4s %-3s %-4s %-4s %-3s %-5s\n"
3713                 , "path", "rate", "", "pwr", "base", "", "(byr", "lmt)", "tpt", "ebias");
3714 }
3715
3716 void dump_tx_power_idx_by_path_rs(void *sel, _adapter *adapter, u8 rfpath, u8 rs)
3717 {
3718         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3719         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3720         u8 power_idx;
3721         struct txpwr_idx_comp tic;
3722         u8 tx_num, i;
3723         u8 band = hal_data->current_band_type;
3724         u8 cch = hal_data->current_channel;
3725         u8 bw = hal_data->current_channel_bw;
3726
3727         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, rfpath))
3728                 return;
3729
3730         if (rs >= RATE_SECTION_NUM)
3731                 return;
3732
3733         tx_num = rate_section_to_tx_num(rs);
3734         if (tx_num >= hal_spec->tx_nss_num || tx_num >= hal_spec->max_tx_cnt)
3735                 return;
3736
3737         if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
3738                 return;
3739
3740         if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
3741                 return;
3742
3743         for (i = 0; i < rates_by_sections[rs].rate_num; i++) {
3744                 power_idx = rtw_hal_get_tx_power_index(adapter, rfpath, rates_by_sections[rs].rates[i], bw, cch, &tic);
3745
3746                 RTW_PRINT_SEL(sel, "%4c %9s %uT %3u %4u %3d (%3d %3d) %3d %5d\n"
3747                         , rf_path_char(rfpath), MGN_RATE_STR(rates_by_sections[rs].rates[i]), tic.ntx_idx + 1
3748                         , power_idx, tic.base, (tic.by_rate > tic.limit ? tic.limit : tic.by_rate), tic.by_rate, tic.limit, tic.tpt, tic.ebias);
3749         }
3750 }
3751
3752 void dump_tx_power_idx(void *sel, _adapter *adapter)
3753 {
3754         u8 rfpath, rs;
3755
3756         dump_tx_power_idx_title(sel, adapter);
3757         for (rfpath = RF_PATH_A; rfpath < RF_PATH_MAX; rfpath++)
3758                 for (rs = CCK; rs < RATE_SECTION_NUM; rs++)
3759                         dump_tx_power_idx_by_path_rs(sel, adapter, rfpath, rs);
3760 }
3761
3762 bool phy_is_tx_power_limit_needed(_adapter *adapter)
3763 {
3764         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3765         struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
3766
3767 #ifdef CONFIG_TXPWR_LIMIT
3768         if (regsty->RegEnableTxPowerLimit == 1
3769                 || (regsty->RegEnableTxPowerLimit == 2 && hal_data->EEPROMRegulatory == 1))
3770                 return _TRUE;
3771 #endif
3772
3773         return _FALSE;
3774 }
3775
3776 bool phy_is_tx_power_by_rate_needed(_adapter *adapter)
3777 {
3778         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3779         struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
3780
3781         if (regsty->RegEnableTxPowerByRate == 1
3782                 || (regsty->RegEnableTxPowerByRate == 2 && hal_data->EEPROMRegulatory != 2))
3783                 return _TRUE;
3784         return _FALSE;
3785 }
3786
3787 int phy_load_tx_power_by_rate(_adapter *adapter, u8 chk_file)
3788 {
3789         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3790         struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
3791         int ret = _FAIL;
3792
3793         hal_data->txpwr_by_rate_loaded = 0;
3794         PHY_InitTxPowerByRate(adapter);
3795
3796         /* tx power limit is based on tx power by rate */
3797         hal_data->txpwr_limit_loaded = 0;
3798
3799 #ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
3800         if (chk_file
3801                 && phy_ConfigBBWithPgParaFile(adapter, PHY_FILE_PHY_REG_PG) == _SUCCESS
3802         ) {
3803                 hal_data->txpwr_by_rate_from_file = 1;
3804                 goto post_hdl;
3805         }
3806 #endif
3807
3808 #ifdef CONFIG_EMBEDDED_FWIMG
3809         if (HAL_STATUS_SUCCESS == odm_config_bb_with_header_file(&hal_data->odmpriv, CONFIG_BB_PHY_REG_PG)) {
3810                 RTW_INFO("default power by rate loaded\n");
3811                 hal_data->txpwr_by_rate_from_file = 0;
3812                 goto post_hdl;
3813         }
3814 #endif
3815
3816         RTW_ERR("%s():Read Tx power by rate fail\n", __func__);
3817         goto exit;
3818
3819 post_hdl:
3820         if (hal_data->odmpriv.phy_reg_pg_value_type != PHY_REG_PG_EXACT_VALUE) {
3821                 rtw_warn_on(1);
3822                 goto exit;
3823         }
3824
3825         PHY_TxPowerByRateConfiguration(adapter);
3826         hal_data->txpwr_by_rate_loaded = 1;
3827
3828         ret = _SUCCESS;
3829
3830 exit:
3831         return ret;
3832 }
3833
3834 #ifdef CONFIG_TXPWR_LIMIT
3835 int phy_load_tx_power_limit(_adapter *adapter, u8 chk_file)
3836 {
3837         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3838         struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
3839         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3840         int ret = _FAIL;
3841
3842         hal_data->txpwr_limit_loaded = 0;
3843         rtw_regd_exc_list_free(rfctl);
3844         rtw_txpwr_lmt_list_free(rfctl);
3845
3846         if (!hal_data->txpwr_by_rate_loaded && regsty->target_tx_pwr_valid != _TRUE) {
3847                 RTW_ERR("%s():Read Tx power limit before target tx power is specify\n", __func__);
3848                 goto exit;
3849         }
3850
3851 #ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
3852         if (chk_file
3853                 && PHY_ConfigRFWithPowerLimitTableParaFile(adapter, PHY_FILE_TXPWR_LMT) == _SUCCESS
3854         ) {
3855                 hal_data->txpwr_limit_from_file = 1;
3856                 goto post_hdl;
3857         }
3858 #endif
3859
3860 #ifdef CONFIG_EMBEDDED_FWIMG
3861         if (odm_config_rf_with_header_file(&hal_data->odmpriv, CONFIG_RF_TXPWR_LMT, RF_PATH_A) == HAL_STATUS_SUCCESS) {
3862                 RTW_INFO("default power limit loaded\n");
3863                 hal_data->txpwr_limit_from_file = 0;
3864                 goto post_hdl;
3865         }
3866 #endif
3867
3868         RTW_ERR("%s():Read Tx power limit fail\n", __func__);
3869         goto exit;
3870
3871 post_hdl:
3872         phy_txpwr_lmt_post_hdl(adapter);
3873         rtw_txpwr_init_regd(rfctl);
3874         hal_data->txpwr_limit_loaded = 1;
3875         ret = _SUCCESS;
3876
3877 exit:
3878         return ret;
3879 }
3880 #endif /* CONFIG_TXPWR_LIMIT */
3881
3882 void phy_load_tx_power_ext_info(_adapter *adapter, u8 chk_file)
3883 {
3884         struct registry_priv *regsty = adapter_to_regsty(adapter);
3885
3886         /* check registy target tx power */
3887         regsty->target_tx_pwr_valid = rtw_regsty_chk_target_tx_power_valid(adapter);
3888
3889         /* power by rate and limit */
3890         if (phy_is_tx_power_by_rate_needed(adapter)
3891                 || (phy_is_tx_power_limit_needed(adapter) && regsty->target_tx_pwr_valid != _TRUE)
3892         )
3893                 phy_load_tx_power_by_rate(adapter, chk_file);
3894
3895 #ifdef CONFIG_TXPWR_LIMIT
3896         if (phy_is_tx_power_limit_needed(adapter))
3897                 phy_load_tx_power_limit(adapter, chk_file);
3898 #endif
3899 }
3900
3901 inline void phy_reload_tx_power_ext_info(_adapter *adapter)
3902 {
3903         phy_load_tx_power_ext_info(adapter, 1);
3904 }
3905
3906 inline void phy_reload_default_tx_power_ext_info(_adapter *adapter)
3907 {
3908         phy_load_tx_power_ext_info(adapter, 0);
3909 }
3910
3911 void dump_tx_power_ext_info(void *sel, _adapter *adapter)
3912 {
3913         struct registry_priv *regsty = adapter_to_regsty(adapter);
3914         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3915
3916         if (regsty->target_tx_pwr_valid == _TRUE)
3917                 RTW_PRINT_SEL(sel, "target_tx_power: from registry\n");
3918         else if (phy_is_tx_power_by_rate_needed(adapter))
3919                 RTW_PRINT_SEL(sel, "target_tx_power: from power by rate\n");
3920         else
3921                 RTW_PRINT_SEL(sel, "target_tx_power: unavailable\n");
3922
3923         RTW_PRINT_SEL(sel, "tx_power_by_rate: %s, %s, %s\n"
3924                 , phy_is_tx_power_by_rate_needed(adapter) ? "enabled" : "disabled"
3925                 , hal_data->txpwr_by_rate_loaded ? "loaded" : "unloaded"
3926                 , hal_data->txpwr_by_rate_from_file ? "file" : "default"
3927         );
3928
3929         RTW_PRINT_SEL(sel, "tx_power_limit: %s, %s, %s\n"
3930                 , phy_is_tx_power_limit_needed(adapter) ? "enabled" : "disabled"
3931                 , hal_data->txpwr_limit_loaded ? "loaded" : "unloaded"
3932                 , hal_data->txpwr_limit_from_file ? "file" : "default"
3933         );
3934 }
3935
3936 void dump_target_tx_power(void *sel, _adapter *adapter)
3937 {
3938         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3939         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3940         struct registry_priv *regsty = adapter_to_regsty(adapter);
3941         int path, tx_num, band, rs;
3942         u8 target;
3943
3944         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
3945                 if (!hal_is_band_support(adapter, band))
3946                         continue;
3947
3948                 for (path = 0; path < RF_PATH_MAX; path++) {
3949                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
3950                                 break;
3951
3952                         RTW_PRINT_SEL(sel, "[%s][%c]%s\n", band_str(band), rf_path_char(path)
3953                                 , (regsty->target_tx_pwr_valid == _FALSE && hal_data->txpwr_by_rate_undefined_band_path[band][path]) ? "(dup)" : "");
3954
3955                         for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
3956                                 tx_num = rate_section_to_tx_num(rs);
3957                                 if (tx_num >= hal_spec->tx_nss_num)
3958                                         continue;
3959
3960                                 if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
3961                                         continue;
3962
3963                                 if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
3964                                         continue;
3965
3966                                 target = PHY_GetTxPowerByRateBase(adapter, band, path, rs);
3967
3968                                 if (target % hal_spec->txgi_pdbm) {
3969                                         _RTW_PRINT_SEL(sel, "%7s: %2d.%d\n", rate_section_str(rs)
3970                                                 , target / hal_spec->txgi_pdbm, (target % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
3971                                 } else {
3972                                         _RTW_PRINT_SEL(sel, "%7s: %5d\n", rate_section_str(rs)
3973                                                 , target / hal_spec->txgi_pdbm);
3974                                 }
3975                         }
3976                 }
3977         }
3978
3979 exit:
3980         return;
3981 }
3982
3983 void dump_tx_power_by_rate(void *sel, _adapter *adapter)
3984 {
3985         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3986         HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
3987         int path, tx_num, band, n, rs;
3988         u8 rate_num, max_rate_num, base;
3989         s8 by_rate_offset;
3990
3991         for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
3992                 if (!hal_is_band_support(adapter, band))
3993                         continue;
3994
3995                 for (path = 0; path < RF_PATH_MAX; path++) {
3996                         if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
3997                                 break;
3998
3999                         RTW_PRINT_SEL(sel, "[%s][%c]%s\n", band_str(band), rf_path_char(path)
4000                                 , hal_data->txpwr_by_rate_undefined_band_path[band][path] ? "(dup)" : "");
4001
4002                         for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
4003                                 tx_num = rate_section_to_tx_num(rs);
4004                                 if (tx_num >= hal_spec->tx_nss_num)
4005                                         continue;
4006
4007                                 if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
4008                                         continue;
4009
4010                                 if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
4011                                         continue;
4012
4013                                 if (IS_HARDWARE_TYPE_JAGUAR_AND_JAGUAR2(adapter))
4014                                         max_rate_num = 10;
4015                                 else
4016                                         max_rate_num = 8;
4017                                 rate_num = rate_section_rate_num(rs);
4018                                 base = PHY_GetTxPowerByRateBase(adapter, band, path, rs);
4019
4020                                 RTW_PRINT_SEL(sel, "%7s: ", rate_section_str(rs));
4021
4022                                 /* dump power by rate in db */
4023                                 for (n = rate_num - 1; n >= 0; n--) {
4024                                         by_rate_offset = PHY_GetTxPowerByRate(adapter, band, path, rates_by_sections[rs].rates[n]);
4025
4026                                         if ((base + by_rate_offset) % hal_spec->txgi_pdbm) {
4027                                                 _RTW_PRINT_SEL(sel, "%2d.%d ", (base + by_rate_offset) / hal_spec->txgi_pdbm
4028                                                         , ((base + by_rate_offset) % hal_spec->txgi_pdbm) * 100 / hal_spec->txgi_pdbm);
4029                                         } else
4030                                                 _RTW_PRINT_SEL(sel, "%5d ", (base + by_rate_offset) / hal_spec->txgi_pdbm);
4031                                 }
4032                                 for (n = 0; n < max_rate_num - rate_num; n++)
4033                                         _RTW_PRINT_SEL(sel, "%5s ", "");
4034
4035                                 _RTW_PRINT_SEL(sel, "|");
4036
4037                                 /* dump power by rate in offset */
4038                                 for (n = rate_num - 1; n >= 0; n--) {
4039                                         by_rate_offset = PHY_GetTxPowerByRate(adapter, band, path, rates_by_sections[rs].rates[n]);
4040                                         _RTW_PRINT_SEL(sel, "%3d ", by_rate_offset);
4041                                 }
4042                                 RTW_PRINT_SEL(sel, "\n");
4043
4044                         }
4045                 }
4046         }
4047 }
4048
4049 /*
4050  * phy file path is stored in global char array rtw_phy_para_file_path
4051  * need to care about racing
4052  */
4053 int rtw_get_phy_file_path(_adapter *adapter, const char *file_name)
4054 {
4055 #ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
4056         struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
4057         int len = 0;
4058
4059         if (file_name) {
4060                 len += snprintf(rtw_phy_para_file_path, PATH_LENGTH_MAX, "%s", rtw_phy_file_path);
4061                 #if defined(CONFIG_MULTIDRV) || defined(REALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER)
4062                 len += snprintf(rtw_phy_para_file_path + len, PATH_LENGTH_MAX - len, "%s/", hal_spec->ic_name);
4063                 #endif
4064                 len += snprintf(rtw_phy_para_file_path + len, PATH_LENGTH_MAX - len, "%s", file_name);
4065
4066                 return _TRUE;
4067         }
4068 #endif
4069         return _FALSE;
4070 }
4071
4072 #ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
4073 int
4074 phy_ConfigMACWithParaFile(
4075         IN      PADAPTER        Adapter,
4076         IN      char            *pFileName
4077 )
4078 {
4079         PHAL_DATA_TYPE  pHalData = GET_HAL_DATA(Adapter);
4080         int     rlen = 0, rtStatus = _FAIL;
4081         char    *szLine, *ptmp;
4082         u32     u4bRegOffset, u4bRegValue, u4bMove;
4083
4084         if (!(Adapter->registrypriv.load_phy_file & LOAD_MAC_PARA_FILE))
4085                 return rtStatus;
4086
4087         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4088
4089         if ((pHalData->mac_reg_len == 0) && (pHalData->mac_reg == NULL)) {
4090                 rtw_get_phy_file_path(Adapter, pFileName);
4091                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4092                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4093                         if (rlen > 0) {
4094                                 rtStatus = _SUCCESS;
4095                                 pHalData->mac_reg = rtw_zvmalloc(rlen);
4096                                 if (pHalData->mac_reg) {
4097                                         _rtw_memcpy(pHalData->mac_reg, pHalData->para_file_buf, rlen);
4098                                         pHalData->mac_reg_len = rlen;
4099                                 } else
4100                                         RTW_INFO("%s mac_reg alloc fail !\n", __FUNCTION__);
4101                         }
4102                 }
4103         } else {
4104                 if ((pHalData->mac_reg_len != 0) && (pHalData->mac_reg != NULL)) {
4105                         _rtw_memcpy(pHalData->para_file_buf, pHalData->mac_reg, pHalData->mac_reg_len);
4106                         rtStatus = _SUCCESS;
4107                 } else
4108                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4109         }
4110
4111         if (rtStatus == _SUCCESS) {
4112                 ptmp = pHalData->para_file_buf;
4113                 for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4114                         if (!IsCommentString(szLine)) {
4115                                 /* Get 1st hex value as register offset */
4116                                 if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
4117                                         if (u4bRegOffset == 0xffff) {
4118                                                 /* Ending. */
4119                                                 break;
4120                                         }
4121
4122                                         /* Get 2nd hex value as register value. */
4123                                         szLine += u4bMove;
4124                                         if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove))
4125                                                 rtw_write8(Adapter, u4bRegOffset, (u8)u4bRegValue);
4126                                 }
4127                         }
4128                 }
4129         } else
4130                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4131
4132         return rtStatus;
4133 }
4134
4135 int
4136 phy_ConfigBBWithParaFile(
4137         IN      PADAPTER        Adapter,
4138         IN      char            *pFileName,
4139         IN      u32                     ConfigType
4140 )
4141 {
4142         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4143         int     rlen = 0, rtStatus = _FAIL;
4144         char    *szLine, *ptmp;
4145         u32     u4bRegOffset, u4bRegValue, u4bMove;
4146         char    *pBuf = NULL;
4147         u32     *pBufLen = NULL;
4148
4149         if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PARA_FILE))
4150                 return rtStatus;
4151
4152         switch (ConfigType) {
4153         case CONFIG_BB_PHY_REG:
4154                 pBuf = pHalData->bb_phy_reg;
4155                 pBufLen = &pHalData->bb_phy_reg_len;
4156                 break;
4157         case CONFIG_BB_AGC_TAB:
4158                 pBuf = pHalData->bb_agc_tab;
4159                 pBufLen = &pHalData->bb_agc_tab_len;
4160                 break;
4161         default:
4162                 RTW_INFO("Unknown ConfigType!! %d\r\n", ConfigType);
4163                 break;
4164         }
4165
4166         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4167
4168         if ((pBufLen != NULL) && (*pBufLen == 0) && (pBuf == NULL)) {
4169                 rtw_get_phy_file_path(Adapter, pFileName);
4170                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4171                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4172                         if (rlen > 0) {
4173                                 rtStatus = _SUCCESS;
4174                                 pBuf = rtw_zvmalloc(rlen);
4175                                 if (pBuf) {
4176                                         _rtw_memcpy(pBuf, pHalData->para_file_buf, rlen);
4177                                         *pBufLen = rlen;
4178
4179                                         switch (ConfigType) {
4180                                         case CONFIG_BB_PHY_REG:
4181                                                 pHalData->bb_phy_reg = pBuf;
4182                                                 break;
4183                                         case CONFIG_BB_AGC_TAB:
4184                                                 pHalData->bb_agc_tab = pBuf;
4185                                                 break;
4186                                         }
4187                                 } else
4188                                         RTW_INFO("%s(): ConfigType %d  alloc fail !\n", __FUNCTION__, ConfigType);
4189                         }
4190                 }
4191         } else {
4192                 if ((pBufLen != NULL) && (*pBufLen != 0) && (pBuf != NULL)) {
4193                         _rtw_memcpy(pHalData->para_file_buf, pBuf, *pBufLen);
4194                         rtStatus = _SUCCESS;
4195                 } else
4196                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4197         }
4198
4199         if (rtStatus == _SUCCESS) {
4200                 ptmp = pHalData->para_file_buf;
4201                 for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4202                         if (!IsCommentString(szLine)) {
4203                                 /* Get 1st hex value as register offset. */
4204                                 if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
4205                                         if (u4bRegOffset == 0xffff) {
4206                                                 /* Ending. */
4207                                                 break;
4208                                         } else if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) {
4209 #ifdef CONFIG_LONG_DELAY_ISSUE
4210                                                 rtw_msleep_os(50);
4211 #else
4212                                                 rtw_mdelay_os(50);
4213 #endif
4214                                         } else if (u4bRegOffset == 0xfd)
4215                                                 rtw_mdelay_os(5);
4216                                         else if (u4bRegOffset == 0xfc)
4217                                                 rtw_mdelay_os(1);
4218                                         else if (u4bRegOffset == 0xfb)
4219                                                 rtw_udelay_os(50);
4220                                         else if (u4bRegOffset == 0xfa)
4221                                                 rtw_udelay_os(5);
4222                                         else if (u4bRegOffset == 0xf9)
4223                                                 rtw_udelay_os(1);
4224
4225                                         /* Get 2nd hex value as register value. */
4226                                         szLine += u4bMove;
4227                                         if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
4228                                                 /* RTW_INFO("[BB-ADDR]%03lX=%08lX\n", u4bRegOffset, u4bRegValue); */
4229                                                 phy_set_bb_reg(Adapter, u4bRegOffset, bMaskDWord, u4bRegValue);
4230
4231                                                 if (u4bRegOffset == 0xa24)
4232                                                         pHalData->odmpriv.rf_calibrate_info.rega24 = u4bRegValue;
4233
4234                                                 /* Add 1us delay between BB/RF register setting. */
4235                                                 rtw_udelay_os(1);
4236                                         }
4237                                 }
4238                         }
4239                 }
4240         } else
4241                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4242
4243         return rtStatus;
4244 }
4245
4246 VOID
4247 phy_DecryptBBPgParaFile(
4248         PADAPTER                Adapter,
4249         char                    *buffer
4250 )
4251 {
4252         u32     i = 0, j = 0;
4253         u8      map[95] = {0};
4254         u8      currentChar;
4255         char    *BufOfLines, *ptmp;
4256
4257         /* RTW_INFO("=====>phy_DecryptBBPgParaFile()\n"); */
4258         /* 32 the ascii code of the first visable char, 126 the last one */
4259         for (i = 0; i < 95; ++i)
4260                 map[i] = (u8)(94 - i);
4261
4262         ptmp = buffer;
4263         i = 0;
4264         for (BufOfLines = GetLineFromBuffer(ptmp); BufOfLines != NULL; BufOfLines = GetLineFromBuffer(ptmp)) {
4265                 /* RTW_INFO("Encrypted Line: %s\n", BufOfLines); */
4266
4267                 for (j = 0; j < strlen(BufOfLines); ++j) {
4268                         currentChar = BufOfLines[j];
4269
4270                         if (currentChar == '\0')
4271                                 break;
4272
4273                         currentChar -= (u8)((((i + j) * 3) % 128));
4274
4275                         BufOfLines[j] = map[currentChar - 32] + 32;
4276                 }
4277                 /* RTW_INFO("Decrypted Line: %s\n", BufOfLines ); */
4278                 if (strlen(BufOfLines) != 0)
4279                         i++;
4280                 BufOfLines[strlen(BufOfLines)] = '\n';
4281         }
4282 }
4283
4284 #ifndef DBG_TXPWR_BY_RATE_FILE_PARSE
4285 #define DBG_TXPWR_BY_RATE_FILE_PARSE 0
4286 #endif
4287
4288 int
4289 phy_ParseBBPgParaFile(
4290         PADAPTER                Adapter,
4291         char                    *buffer
4292 )
4293 {
4294         int     rtStatus = _FAIL;
4295         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4296         struct hal_spec_t *hal_spec = GET_HAL_SPEC(Adapter);
4297         char    *szLine, *ptmp;
4298         u32     u4bRegOffset, u4bRegMask, u4bRegValue;
4299         u32     u4bMove;
4300         BOOLEAN firstLine = _TRUE;
4301         u8      tx_num = 0;
4302         u8      band = 0, rf_path = 0;
4303
4304         if (Adapter->registrypriv.RegDecryptCustomFile == 1)
4305                 phy_DecryptBBPgParaFile(Adapter, buffer);
4306
4307         ptmp = buffer;
4308         for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4309                 if (isAllSpaceOrTab(szLine, sizeof(*szLine)))
4310                         continue;
4311
4312                 if (!IsCommentString(szLine)) {
4313                         /* Get header info (relative value or exact value) */
4314                         if (firstLine) {
4315                                 if (eqNByte(szLine, (u8 *)("#[v1]"), 5))
4316                                         pHalData->odmpriv.phy_reg_pg_version = szLine[3] - '0';
4317                                 else {
4318                                         RTW_ERR("The format in PHY_REG_PG are invalid %s\n", szLine);
4319                                         goto exit;
4320                                 }
4321
4322                                 if (eqNByte(szLine + 5, (u8 *)("[Exact]#"), 8)) {
4323                                         pHalData->odmpriv.phy_reg_pg_value_type = PHY_REG_PG_EXACT_VALUE;
4324                                         firstLine = _FALSE;
4325                                         continue;
4326                                 } else {
4327                                         RTW_ERR("The values in PHY_REG_PG are invalid %s\n", szLine);
4328                                         goto exit;
4329                                 }
4330                         }
4331
4332                         if (pHalData->odmpriv.phy_reg_pg_version > 0) {
4333                                 u32     index = 0, cnt = 0;
4334
4335                                 if (eqNByte(szLine, "0xffff", 6))
4336                                         break;
4337
4338                                 if (!eqNByte("#[END]#", szLine, 7)) {
4339                                         /* load the table label info */
4340                                         if (szLine[0] == '#') {
4341                                                 index = 0;
4342                                                 if (eqNByte(szLine, "#[2.4G]" , 7)) {
4343                                                         band = BAND_ON_2_4G;
4344                                                         index += 8;
4345                                                 } else if (eqNByte(szLine, "#[5G]", 5)) {
4346                                                         band = BAND_ON_5G;
4347                                                         index += 6;
4348                                                 } else {
4349                                                         RTW_ERR("Invalid band %s in PHY_REG_PG.txt\n", szLine);
4350                                                         goto exit;
4351                                                 }
4352
4353                                                 rf_path = szLine[index] - 'A';
4354                                                 if (DBG_TXPWR_BY_RATE_FILE_PARSE)
4355                                                         RTW_INFO(" Table label Band %d, RfPath %d\n", band, rf_path );
4356                                         } else { /* load rows of tables */
4357                                                 if (szLine[1] == '1')
4358                                                         tx_num = RF_1TX;
4359                                                 else if (szLine[1] == '2')
4360                                                         tx_num = RF_2TX;
4361                                                 else if (szLine[1] == '3')
4362                                                         tx_num = RF_3TX;
4363                                                 else if (szLine[1] == '4')
4364                                                         tx_num = RF_4TX;
4365                                                 else {
4366                                                         RTW_ERR("Invalid row in PHY_REG_PG.txt '%c'(%d)\n", szLine[1], szLine[1]);
4367                                                         goto exit;
4368                                                 }
4369
4370                                                 while (szLine[index] != ']')
4371                                                         ++index;
4372                                                 ++index;/* skip ] */
4373
4374                                                 /* Get 2nd hex value as register offset. */
4375                                                 szLine += index;
4376                                                 if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove))
4377                                                         szLine += u4bMove;
4378                                                 else
4379                                                         goto exit;
4380
4381                                                 /* Get 2nd hex value as register mask. */
4382                                                 if (GetHexValueFromString(szLine, &u4bRegMask, &u4bMove))
4383                                                         szLine += u4bMove;
4384                                                 else
4385                                                         goto exit;
4386
4387                                                 if (pHalData->odmpriv.phy_reg_pg_value_type == PHY_REG_PG_EXACT_VALUE) {
4388                                                         u32     combineValue = 0;
4389                                                         u8      integer = 0, fraction = 0;
4390
4391                                                         if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
4392                                                                 szLine += u4bMove;
4393                                                         else
4394                                                                 goto exit;
4395
4396                                                         integer *= hal_spec->txgi_pdbm;
4397                                                         integer += ((u16)fraction * (u16)hal_spec->txgi_pdbm) / 100;
4398                                                         if (hal_spec->txgi_pdbm == 2)
4399                                                                 combineValue |= (((integer / 10) << 4) + (integer % 10));
4400                                                         else
4401                                                                 combineValue |= integer;
4402
4403                                                         if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
4404                                                                 szLine += u4bMove;
4405                                                         else
4406                                                                 goto exit;
4407
4408                                                         integer *= hal_spec->txgi_pdbm;
4409                                                         integer += ((u16)fraction * (u16)hal_spec->txgi_pdbm) / 100;
4410                                                         combineValue <<= 8;
4411                                                         if (hal_spec->txgi_pdbm == 2)
4412                                                                 combineValue |= (((integer / 10) << 4) + (integer % 10));
4413                                                         else
4414                                                                 combineValue |= integer;
4415
4416                                                         if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
4417                                                                 szLine += u4bMove;
4418                                                         else
4419                                                                 goto exit;
4420
4421                                                         integer *= hal_spec->txgi_pdbm;
4422                                                         integer += ((u16)fraction * (u16)hal_spec->txgi_pdbm) / 100;
4423                                                         combineValue <<= 8;
4424                                                         if (hal_spec->txgi_pdbm == 2)
4425                                                                 combineValue |= (((integer / 10) << 4) + (integer % 10));
4426                                                         else
4427                                                                 combineValue |= integer;
4428
4429                                                         if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove))
4430                                                                 szLine += u4bMove;
4431                                                         else
4432                                                                 goto exit;
4433
4434                                                         integer *= hal_spec->txgi_pdbm;
4435                                                         integer += ((u16)fraction * (u16)hal_spec->txgi_pdbm) / 100;
4436                                                         combineValue <<= 8;
4437                                                         if (hal_spec->txgi_pdbm == 2)
4438                                                                 combineValue |= (((integer / 10) << 4) + (integer % 10));
4439                                                         else
4440                                                                 combineValue |= integer;
4441
4442                                                         phy_store_tx_power_by_rate(Adapter, band, rf_path, tx_num, u4bRegOffset, u4bRegMask, combineValue);
4443
4444                                                         if (DBG_TXPWR_BY_RATE_FILE_PARSE)
4445                                                                 RTW_INFO("addr:0x%3x mask:0x%08x %dTx = 0x%08x\n", u4bRegOffset, u4bRegMask, tx_num, combineValue);
4446                                                 }
4447                                         }
4448                                 }
4449                         }
4450                 }
4451         }
4452
4453         rtStatus = _SUCCESS;
4454
4455 exit:
4456         RTW_INFO("%s return %d\n", __func__, rtStatus);
4457         return rtStatus;
4458 }
4459
4460 int
4461 phy_ConfigBBWithPgParaFile(
4462         IN      PADAPTER        Adapter,
4463         IN      const char      *pFileName)
4464 {
4465         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4466         int     rlen = 0, rtStatus = _FAIL;
4467
4468         if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PG_PARA_FILE))
4469                 return rtStatus;
4470
4471         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4472
4473         if (pHalData->bb_phy_reg_pg == NULL) {
4474                 rtw_get_phy_file_path(Adapter, pFileName);
4475                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4476                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4477                         if (rlen > 0) {
4478                                 rtStatus = _SUCCESS;
4479                                 pHalData->bb_phy_reg_pg = rtw_zvmalloc(rlen);
4480                                 if (pHalData->bb_phy_reg_pg) {
4481                                         _rtw_memcpy(pHalData->bb_phy_reg_pg, pHalData->para_file_buf, rlen);
4482                                         pHalData->bb_phy_reg_pg_len = rlen;
4483                                 } else
4484                                         RTW_INFO("%s bb_phy_reg_pg alloc fail !\n", __FUNCTION__);
4485                         }
4486                 }
4487         } else {
4488                 if ((pHalData->bb_phy_reg_pg_len != 0) && (pHalData->bb_phy_reg_pg != NULL)) {
4489                         _rtw_memcpy(pHalData->para_file_buf, pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len);
4490                         rtStatus = _SUCCESS;
4491                 } else
4492                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4493         }
4494
4495         if (rtStatus == _SUCCESS) {
4496                 /* RTW_INFO("phy_ConfigBBWithPgParaFile(): read %s ok\n", pFileName); */
4497                 rtStatus = phy_ParseBBPgParaFile(Adapter, pHalData->para_file_buf);
4498         } else
4499                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4500
4501         return rtStatus;
4502 }
4503
4504 #if (MP_DRIVER == 1)
4505
4506 int
4507 phy_ConfigBBWithMpParaFile(
4508         IN      PADAPTER        Adapter,
4509         IN      char            *pFileName
4510 )
4511 {
4512         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4513         int     rlen = 0, rtStatus = _FAIL;
4514         char    *szLine, *ptmp;
4515         u32     u4bRegOffset, u4bRegValue, u4bMove;
4516
4517         if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_MP_PARA_FILE))
4518                 return rtStatus;
4519
4520         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4521
4522         if ((pHalData->bb_phy_reg_mp_len == 0) && (pHalData->bb_phy_reg_mp == NULL)) {
4523                 rtw_get_phy_file_path(Adapter, pFileName);
4524                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4525                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4526                         if (rlen > 0) {
4527                                 rtStatus = _SUCCESS;
4528                                 pHalData->bb_phy_reg_mp = rtw_zvmalloc(rlen);
4529                                 if (pHalData->bb_phy_reg_mp) {
4530                                         _rtw_memcpy(pHalData->bb_phy_reg_mp, pHalData->para_file_buf, rlen);
4531                                         pHalData->bb_phy_reg_mp_len = rlen;
4532                                 } else
4533                                         RTW_INFO("%s bb_phy_reg_mp alloc fail !\n", __FUNCTION__);
4534                         }
4535                 }
4536         } else {
4537                 if ((pHalData->bb_phy_reg_mp_len != 0) && (pHalData->bb_phy_reg_mp != NULL)) {
4538                         _rtw_memcpy(pHalData->para_file_buf, pHalData->bb_phy_reg_mp, pHalData->bb_phy_reg_mp_len);
4539                         rtStatus = _SUCCESS;
4540                 } else
4541                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4542         }
4543
4544         if (rtStatus == _SUCCESS) {
4545                 /* RTW_INFO("phy_ConfigBBWithMpParaFile(): read %s ok\n", pFileName); */
4546
4547                 ptmp = pHalData->para_file_buf;
4548                 for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4549                         if (!IsCommentString(szLine)) {
4550                                 /* Get 1st hex value as register offset. */
4551                                 if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
4552                                         if (u4bRegOffset == 0xffff) {
4553                                                 /* Ending. */
4554                                                 break;
4555                                         } else if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) {
4556 #ifdef CONFIG_LONG_DELAY_ISSUE
4557                                                 rtw_msleep_os(50);
4558 #else
4559                                                 rtw_mdelay_os(50);
4560 #endif
4561                                         } else if (u4bRegOffset == 0xfd)
4562                                                 rtw_mdelay_os(5);
4563                                         else if (u4bRegOffset == 0xfc)
4564                                                 rtw_mdelay_os(1);
4565                                         else if (u4bRegOffset == 0xfb)
4566                                                 rtw_udelay_os(50);
4567                                         else if (u4bRegOffset == 0xfa)
4568                                                 rtw_udelay_os(5);
4569                                         else if (u4bRegOffset == 0xf9)
4570                                                 rtw_udelay_os(1);
4571
4572                                         /* Get 2nd hex value as register value. */
4573                                         szLine += u4bMove;
4574                                         if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
4575                                                 /* RTW_INFO("[ADDR]%03lX=%08lX\n", u4bRegOffset, u4bRegValue); */
4576                                                 phy_set_bb_reg(Adapter, u4bRegOffset, bMaskDWord, u4bRegValue);
4577
4578                                                 /* Add 1us delay between BB/RF register setting. */
4579                                                 rtw_udelay_os(1);
4580                                         }
4581                                 }
4582                         }
4583                 }
4584         } else
4585                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4586
4587         return rtStatus;
4588 }
4589
4590 #endif
4591
4592 int
4593 PHY_ConfigRFWithParaFile(
4594         IN      PADAPTER        Adapter,
4595         IN      char            *pFileName,
4596         IN      enum rf_path            eRFPath
4597 )
4598 {
4599         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4600         int     rlen = 0, rtStatus = _FAIL;
4601         char    *szLine, *ptmp;
4602         u32     u4bRegOffset, u4bRegValue, u4bMove;
4603         u16     i;
4604         char    *pBuf = NULL;
4605         u32     *pBufLen = NULL;
4606
4607         if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_PARA_FILE))
4608                 return rtStatus;
4609
4610         switch (eRFPath) {
4611         case RF_PATH_A:
4612                 pBuf = pHalData->rf_radio_a;
4613                 pBufLen = &pHalData->rf_radio_a_len;
4614                 break;
4615         case RF_PATH_B:
4616                 pBuf = pHalData->rf_radio_b;
4617                 pBufLen = &pHalData->rf_radio_b_len;
4618                 break;
4619         default:
4620                 RTW_INFO("Unknown RF path!! %d\r\n", eRFPath);
4621                 break;
4622         }
4623
4624         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4625
4626         if ((pBufLen != NULL) && (*pBufLen == 0) && (pBuf == NULL)) {
4627                 rtw_get_phy_file_path(Adapter, pFileName);
4628                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4629                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4630                         if (rlen > 0) {
4631                                 rtStatus = _SUCCESS;
4632                                 pBuf = rtw_zvmalloc(rlen);
4633                                 if (pBuf) {
4634                                         _rtw_memcpy(pBuf, pHalData->para_file_buf, rlen);
4635                                         *pBufLen = rlen;
4636
4637                                         switch (eRFPath) {
4638                                         case RF_PATH_A:
4639                                                 pHalData->rf_radio_a = pBuf;
4640                                                 break;
4641                                         case RF_PATH_B:
4642                                                 pHalData->rf_radio_b = pBuf;
4643                                                 break;
4644                                         default:
4645                                                 RTW_INFO("Unknown RF path!! %d\r\n", eRFPath);
4646                                                 break;
4647                                         }
4648                                 } else
4649                                         RTW_INFO("%s(): eRFPath=%d  alloc fail !\n", __FUNCTION__, eRFPath);
4650                         }
4651                 }
4652         } else {
4653                 if ((pBufLen != NULL) && (*pBufLen != 0) && (pBuf != NULL)) {
4654                         _rtw_memcpy(pHalData->para_file_buf, pBuf, *pBufLen);
4655                         rtStatus = _SUCCESS;
4656                 } else
4657                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4658         }
4659
4660         if (rtStatus == _SUCCESS) {
4661                 /* RTW_INFO("%s(): read %s successfully\n", __FUNCTION__, pFileName); */
4662
4663                 ptmp = pHalData->para_file_buf;
4664                 for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4665                         if (!IsCommentString(szLine)) {
4666                                 /* Get 1st hex value as register offset. */
4667                                 if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) {
4668                                         if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) {
4669                                                 /* Deay specific ms. Only RF configuration require delay.                                                                                                */
4670 #ifdef CONFIG_LONG_DELAY_ISSUE
4671                                                 rtw_msleep_os(50);
4672 #else
4673                                                 rtw_mdelay_os(50);
4674 #endif
4675                                         } else if (u4bRegOffset == 0xfd) {
4676                                                 /* delay_ms(5); */
4677                                                 for (i = 0; i < 100; i++)
4678                                                         rtw_udelay_os(MAX_STALL_TIME);
4679                                         } else if (u4bRegOffset == 0xfc) {
4680                                                 /* delay_ms(1); */
4681                                                 for (i = 0; i < 20; i++)
4682                                                         rtw_udelay_os(MAX_STALL_TIME);
4683                                         } else if (u4bRegOffset == 0xfb)
4684                                                 rtw_udelay_os(50);
4685                                         else if (u4bRegOffset == 0xfa)
4686                                                 rtw_udelay_os(5);
4687                                         else if (u4bRegOffset == 0xf9)
4688                                                 rtw_udelay_os(1);
4689                                         else if (u4bRegOffset == 0xffff)
4690                                                 break;
4691
4692                                         /* Get 2nd hex value as register value. */
4693                                         szLine += u4bMove;
4694                                         if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) {
4695                                                 phy_set_rf_reg(Adapter, eRFPath, u4bRegOffset, bRFRegOffsetMask, u4bRegValue);
4696
4697                                                 /* Temp add, for frequency lock, if no delay, that may cause */
4698                                                 /* frequency shift, ex: 2412MHz => 2417MHz */
4699                                                 /* If frequency shift, the following action may works. */
4700                                                 /* Fractional-N table in radio_a.txt */
4701                                                 /* 0x2a 0x00001          */ /* channel 1 */
4702                                                 /* 0x2b 0x00808         frequency divider. */
4703                                                 /* 0x2b 0x53333 */
4704                                                 /* 0x2c 0x0000c */
4705                                                 rtw_udelay_os(1);
4706                                         }
4707                                 }
4708                         }
4709                 }
4710         } else
4711                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4712
4713         return rtStatus;
4714 }
4715
4716 VOID
4717 initDeltaSwingIndexTables(
4718         PADAPTER        Adapter,
4719         char            *Band,
4720         char            *Path,
4721         char            *Sign,
4722         char            *Channel,
4723         char            *Rate,
4724         char            *Data
4725 )
4726 {
4727 #define STR_EQUAL_5G(_band, _path, _sign, _rate, _chnl) \
4728         ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\
4729          (strcmp(Rate, _rate) == 0) && (strcmp(Channel, _chnl) == 0)\
4730         )
4731 #define STR_EQUAL_2G(_band, _path, _sign, _rate) \
4732         ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\
4733          (strcmp(Rate, _rate) == 0)\
4734         )
4735
4736 #define STORE_SWING_TABLE(_array, _iteratedIdx) \
4737         do {    \
4738         for (token = strsep(&Data, delim); token != NULL; token = strsep(&Data, delim)) {\
4739                 sscanf(token, "%d", &idx);\
4740                 _array[_iteratedIdx++] = (u8)idx;\
4741         } } while (0)\
4742
4743         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
4744         struct dm_struct                *pDM_Odm = &pHalData->odmpriv;
4745         struct dm_rf_calibration_struct *pRFCalibrateInfo = &(pDM_Odm->rf_calibrate_info);
4746         u32     j = 0;
4747         char    *token;
4748         char    delim[] = ",";
4749         u32     idx = 0;
4750
4751         /* RTW_INFO("===>initDeltaSwingIndexTables(): Band: %s;\nPath: %s;\nSign: %s;\nChannel: %s;\nRate: %s;\n, Data: %s;\n",  */
4752         /*      Band, Path, Sign, Channel, Rate, Data); */
4753
4754         if (STR_EQUAL_2G("2G", "A", "+", "CCK"))
4755                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_p, j);
4756         else if (STR_EQUAL_2G("2G", "A", "-", "CCK"))
4757                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_n, j);
4758         else if (STR_EQUAL_2G("2G", "B", "+", "CCK"))
4759                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_p, j);
4760         else if (STR_EQUAL_2G("2G", "B", "-", "CCK"))
4761                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_n, j);
4762         else if (STR_EQUAL_2G("2G", "A", "+", "ALL"))
4763                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2ga_p, j);
4764         else if (STR_EQUAL_2G("2G", "A", "-", "ALL"))
4765                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2ga_n, j);
4766         else if (STR_EQUAL_2G("2G", "B", "+", "ALL"))
4767                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2gb_p, j);
4768         else if (STR_EQUAL_2G("2G", "B", "-", "ALL"))
4769                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2gb_n, j);
4770         else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "0"))
4771                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[0], j);
4772         else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "0"))
4773                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[0], j);
4774         else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "0"))
4775                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[0], j);
4776         else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "0"))
4777                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[0], j);
4778         else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "1"))
4779                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[1], j);
4780         else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "1"))
4781                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[1], j);
4782         else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "1"))
4783                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[1], j);
4784         else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "1"))
4785                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[1], j);
4786         else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "2"))
4787                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[2], j);
4788         else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "2"))
4789                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[2], j);
4790         else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "2"))
4791                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[2], j);
4792         else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "2"))
4793                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[2], j);
4794         else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "3"))
4795                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[3], j);
4796         else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "3"))
4797                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[3], j);
4798         else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "3"))
4799                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[3], j);
4800         else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "3"))
4801                 STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[3], j);
4802         else
4803                 RTW_INFO("===>initDeltaSwingIndexTables(): The input is invalid!!\n");
4804 }
4805
4806 int
4807 PHY_ConfigRFWithTxPwrTrackParaFile(
4808         IN      PADAPTER                Adapter,
4809         IN      char                    *pFileName
4810 )
4811 {
4812         HAL_DATA_TYPE           *pHalData = GET_HAL_DATA(Adapter);
4813         struct dm_struct                        *pDM_Odm = &pHalData->odmpriv;
4814         struct dm_rf_calibration_struct         *pRFCalibrateInfo = &(pDM_Odm->rf_calibrate_info);
4815         int     rlen = 0, rtStatus = _FAIL;
4816         char    *szLine, *ptmp;
4817         u32     i = 0, j = 0;
4818         char    c = 0;
4819
4820         if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_TRACK_PARA_FILE))
4821                 return rtStatus;
4822
4823         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
4824
4825         if ((pHalData->rf_tx_pwr_track_len == 0) && (pHalData->rf_tx_pwr_track == NULL)) {
4826                 rtw_get_phy_file_path(Adapter, pFileName);
4827                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
4828                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
4829                         if (rlen > 0) {
4830                                 rtStatus = _SUCCESS;
4831                                 pHalData->rf_tx_pwr_track = rtw_zvmalloc(rlen);
4832                                 if (pHalData->rf_tx_pwr_track) {
4833                                         _rtw_memcpy(pHalData->rf_tx_pwr_track, pHalData->para_file_buf, rlen);
4834                                         pHalData->rf_tx_pwr_track_len = rlen;
4835                                 } else
4836                                         RTW_INFO("%s rf_tx_pwr_track alloc fail !\n", __FUNCTION__);
4837                         }
4838                 }
4839         } else {
4840                 if ((pHalData->rf_tx_pwr_track_len != 0) && (pHalData->rf_tx_pwr_track != NULL)) {
4841                         _rtw_memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len);
4842                         rtStatus = _SUCCESS;
4843                 } else
4844                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
4845         }
4846
4847         if (rtStatus == _SUCCESS) {
4848                 /* RTW_INFO("%s(): read %s successfully\n", __FUNCTION__, pFileName); */
4849
4850                 ptmp = pHalData->para_file_buf;
4851                 for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
4852                         if (!IsCommentString(szLine)) {
4853                                 char    band[5] = "", path[5] = "", sign[5]  = "";
4854                                 char    chnl[5] = "", rate[10] = "";
4855                                 char    data[300] = ""; /* 100 is too small */
4856
4857                                 if (strlen(szLine) < 10 || szLine[0] != '[')
4858                                         continue;
4859
4860                                 strncpy(band, szLine + 1, 2);
4861                                 strncpy(path, szLine + 5, 1);
4862                                 strncpy(sign, szLine + 8, 1);
4863
4864                                 i = 10; /* szLine+10 */
4865                                 if (!ParseQualifiedString(szLine, &i, rate, '[', ']')) {
4866                                         /* RTW_INFO("Fail to parse rate!\n"); */
4867                                 }
4868                                 if (!ParseQualifiedString(szLine, &i, chnl, '[', ']')) {
4869                                         /* RTW_INFO("Fail to parse channel group!\n"); */
4870                                 }
4871                                 while (szLine[i] != '{' && i < strlen(szLine))
4872                                         i++;
4873                                 if (!ParseQualifiedString(szLine, &i, data, '{', '}')) {
4874                                         /* RTW_INFO("Fail to parse data!\n"); */
4875                                 }
4876
4877                                 initDeltaSwingIndexTables(Adapter, band, path, sign, chnl, rate, data);
4878                         }
4879                 }
4880         } else
4881                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
4882 #if 0
4883         for (i = 0; i < DELTA_SWINGIDX_SIZE; ++i) {
4884                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2ga_p[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2ga_p[i]);
4885                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2ga_n[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2ga_n[i]);
4886                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2gb_p[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2gb_p[i]);
4887                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2gb_n[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2gb_n[i]);
4888                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_p[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_p[i]);
4889                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_n[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_n[i]);
4890                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_p[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_p[i]);
4891                 RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_n[%d] = %d\n", i, pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_n[i]);
4892
4893                 for (j = 0; j < 3; ++j) {
4894                         RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_5ga_p[%d][%d] = %d\n", j, i, pRFCalibrateInfo->delta_swing_table_idx_5ga_p[j][i]);
4895                         RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_5ga_n[%d][%d] = %d\n", j, i, pRFCalibrateInfo->delta_swing_table_idx_5ga_n[j][i]);
4896                         RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_5gb_p[%d][%d] = %d\n", j, i, pRFCalibrateInfo->delta_swing_table_idx_5gb_p[j][i]);
4897                         RTW_INFO("pRFCalibrateInfo->delta_swing_table_idx_5gb_n[%d][%d] = %d\n", j, i, pRFCalibrateInfo->delta_swing_table_idx_5gb_n[j][i]);
4898                 }
4899         }
4900 #endif
4901         return rtStatus;
4902 }
4903
4904 #ifdef CONFIG_TXPWR_LIMIT
4905
4906 #ifndef DBG_TXPWR_LMT_FILE_PARSE
4907 #define DBG_TXPWR_LMT_FILE_PARSE 0
4908 #endif
4909
4910 #define PARSE_RET_NO_HDL        0
4911 #define PARSE_RET_SUCCESS       1
4912 #define PARSE_RET_FAIL          2
4913
4914 /*
4915 * @@Ver=2.0
4916 * or
4917 * @@DomainCode=0x28, Regulation=C6
4918 * or
4919 * @@CountryCode=GB, Regulation=C7
4920 */
4921 static u8 parse_reg_exc_config(_adapter *adapter, char *szLine)
4922 {
4923 #define VER_PREFIX "Ver="
4924 #define DOMAIN_PREFIX "DomainCode=0x"
4925 #define COUNTRY_PREFIX "CountryCode="
4926 #define REG_PREFIX "Regulation="
4927
4928         const u8 ver_prefix_len = strlen(VER_PREFIX);
4929         const u8 domain_prefix_len = strlen(DOMAIN_PREFIX);
4930         const u8 country_prefix_len = strlen(COUNTRY_PREFIX);
4931         const u8 reg_prefix_len = strlen(REG_PREFIX);
4932         u32 i, i_val_s, i_val_e;
4933         u32 j;
4934         u8 domain = 0xFF;
4935         char *country = NULL;
4936         u8 parse_reg = 0;
4937
4938         if (szLine[0] != '@' || szLine[1] != '@')
4939                 return PARSE_RET_NO_HDL;
4940
4941         i = 2;
4942         if (strncmp(szLine + i, VER_PREFIX, ver_prefix_len) == 0)
4943                 ; /* nothing to do */
4944         else if (strncmp(szLine + i, DOMAIN_PREFIX, domain_prefix_len) == 0) {
4945                 /* get string after domain prefix to ',' */
4946                 i += domain_prefix_len;
4947                 i_val_s = i;
4948                 while (szLine[i] != ',') {
4949                         if (szLine[i] == '\0')
4950                                 return PARSE_RET_FAIL;
4951                         i++;
4952                 }
4953                 i_val_e = i;
4954
4955                 /* check if all hex */
4956                 for (j = i_val_s; j < i_val_e; j++)
4957                         if (IsHexDigit(szLine[j]) == _FALSE)
4958                                 return PARSE_RET_FAIL;
4959
4960                 /* get value from hex string */
4961                 if (sscanf(szLine + i_val_s, "%hhx", &domain) != 1)
4962                         return PARSE_RET_FAIL;
4963
4964                 parse_reg = 1;
4965         } else if (strncmp(szLine + i, COUNTRY_PREFIX, country_prefix_len) == 0) {
4966                 /* get string after country prefix to ',' */
4967                 i += country_prefix_len;
4968                 i_val_s = i;
4969                 while (szLine[i] != ',') {
4970                         if (szLine[i] == '\0')
4971                                 return PARSE_RET_FAIL;
4972                         i++;
4973                 }
4974                 i_val_e = i;
4975
4976                 if (i_val_e - i_val_s != 2)
4977                         return PARSE_RET_FAIL;
4978
4979                 /* check if all alpha */
4980                 for (j = i_val_s; j < i_val_e; j++)
4981                         if (is_alpha(szLine[j]) == _FALSE)
4982                                 return PARSE_RET_FAIL;
4983
4984                 country = szLine + i_val_s;
4985
4986                 parse_reg = 1;
4987
4988         } else
4989                 return PARSE_RET_FAIL;
4990
4991         if (parse_reg) {
4992                 /* move to 'R' */
4993                 while (szLine[i] != 'R') {
4994                         if (szLine[i] == '\0')
4995                                 return PARSE_RET_FAIL;
4996                         i++;
4997                 }
4998
4999                 /* check if matching regulation prefix */
5000                 if (strncmp(szLine + i, REG_PREFIX, reg_prefix_len) != 0)
5001                         return PARSE_RET_FAIL;
5002
5003                 /* get string after regulation prefix ending with space */
5004                 i += reg_prefix_len;
5005                 i_val_s = i;
5006                 while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0')
5007                         i++;
5008
5009                 if (i == i_val_s)
5010                         return PARSE_RET_FAIL;
5011
5012                 rtw_regd_exc_add_with_nlen(adapter_to_rfctl(adapter), country, domain, szLine + i_val_s, i - i_val_s);
5013         }
5014
5015         return PARSE_RET_SUCCESS;
5016 }
5017
5018 static int
5019 phy_ParsePowerLimitTableFile(
5020         PADAPTER                Adapter,
5021         char                    *buffer
5022 )
5023 {
5024 #define LD_STAGE_EXC_MAPPING    0
5025 #define LD_STAGE_TAB_DEFINE             1
5026 #define LD_STAGE_TAB_START              2
5027 #define LD_STAGE_COLUMN_DEFINE  3
5028 #define LD_STAGE_CH_ROW                 4
5029
5030         int     rtStatus = _FAIL;
5031         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);
5032         struct hal_spec_t *hal_spec = GET_HAL_SPEC(Adapter);
5033         struct dm_struct        *pDM_Odm = &(pHalData->odmpriv);
5034         u8      loadingStage = LD_STAGE_EXC_MAPPING;
5035         u32     i = 0, forCnt = 0;
5036         char    *szLine, *ptmp;
5037         char band[10], bandwidth[10], rateSection[10], ntx[10], colNumBuf[10];
5038         char **regulation = NULL;
5039         u8      colNum = 0;
5040
5041         if (Adapter->registrypriv.RegDecryptCustomFile == 1)
5042                 phy_DecryptBBPgParaFile(Adapter, buffer);
5043
5044         ptmp = buffer;
5045         for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) {
5046                 if (isAllSpaceOrTab(szLine, sizeof(*szLine)))
5047                         continue;
5048                 if (IsCommentString(szLine))
5049                         continue;
5050
5051                 if (loadingStage == LD_STAGE_EXC_MAPPING) {
5052                         if (szLine[0] == '#' || szLine[1] == '#') {
5053                                 loadingStage = LD_STAGE_TAB_DEFINE;
5054                                 if (DBG_TXPWR_LMT_FILE_PARSE)
5055                                         dump_regd_exc_list(RTW_DBGDUMP, adapter_to_rfctl(Adapter));
5056                         } else {
5057                                 if (parse_reg_exc_config(Adapter, szLine) == PARSE_RET_FAIL) {
5058                                         RTW_ERR("Fail to parse regulation exception ruls!\n");
5059                                         goto exit;
5060                                 }
5061                                 continue;
5062                         }
5063                 }
5064
5065                 if (loadingStage == LD_STAGE_TAB_DEFINE) {
5066                         /* read "##     2.4G, 20M, 1T, CCK" */
5067                         if (szLine[0] != '#' || szLine[1] != '#')
5068                                 continue;
5069
5070                         /* skip the space */
5071                         i = 2;
5072                         while (szLine[i] == ' ' || szLine[i] == '\t')
5073                                 ++i;
5074
5075                         szLine[--i] = ' '; /* return the space in front of the regulation info */
5076
5077                         /* Parse the label of the table */
5078                         _rtw_memset((PVOID) band, 0, 10);
5079                         _rtw_memset((PVOID) bandwidth, 0, 10);
5080                         _rtw_memset((PVOID) ntx, 0, 10);
5081                         _rtw_memset((PVOID) rateSection, 0, 10);
5082                         if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) {
5083                                 RTW_ERR("Fail to parse band!\n");
5084                                 goto exit;
5085                         }
5086                         if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) {
5087                                 RTW_ERR("Fail to parse bandwidth!\n");
5088                                 goto exit;
5089                         }
5090                         if (!ParseQualifiedString(szLine, &i, ntx, ' ', ',')) {
5091                                 RTW_ERR("Fail to parse ntx!\n");
5092                                 goto exit;
5093                         }
5094                         if (!ParseQualifiedString(szLine, &i, rateSection, ' ', ',')) {
5095                                 RTW_ERR("Fail to parse rate!\n");
5096                                 goto exit;
5097                         }
5098
5099                         loadingStage = LD_STAGE_TAB_START;
5100                 } else if (loadingStage == LD_STAGE_TAB_START) {
5101                         /* read "##     START" */
5102                         if (szLine[0] != '#' || szLine[1] != '#')
5103                                 continue;
5104
5105                         /* skip the space */
5106                         i = 2;
5107                         while (szLine[i] == ' ' || szLine[i] == '\t')
5108                                 ++i;
5109
5110                         if (!eqNByte((u8 *)(szLine + i), (u8 *)("START"), 5)) {
5111                                 RTW_ERR("Missing \"##   START\" label\n");
5112                                 goto exit;
5113                         }
5114
5115                         loadingStage = LD_STAGE_COLUMN_DEFINE;
5116                 } else if (loadingStage == LD_STAGE_COLUMN_DEFINE) {
5117                         /* read "##     #5#     FCC     ETSI    MKK     IC      KCC" */
5118                         if (szLine[0] != '#' || szLine[1] != '#')
5119                                 continue;
5120
5121                         /* skip the space */
5122                         i = 2;
5123                         while (szLine[i] == ' ' || szLine[i] == '\t')
5124                                 ++i;
5125
5126                         _rtw_memset((PVOID) colNumBuf, 0, 10);
5127                         if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) {
5128                                 RTW_ERR("Fail to parse column number!\n");
5129                                 goto exit;
5130                         }
5131                         if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum)) {
5132                                 RTW_ERR("Column number \"%s\" is not unsigned decimal\n", colNumBuf);
5133                                 goto exit;
5134                         }
5135                         if (colNum == 0) {
5136                                 RTW_ERR("Column number is 0\n");
5137                                 goto exit;
5138                         }
5139
5140                         if (DBG_TXPWR_LMT_FILE_PARSE)
5141                                 RTW_PRINT("[%s][%s][%s][%s] column num:%d\n", band, bandwidth, rateSection, ntx, colNum);
5142
5143                         regulation = (char **)rtw_zmalloc(sizeof(char *) * colNum);
5144                         if (!regulation) {
5145                                 RTW_ERR("Regulation alloc fail\n");
5146                                 goto exit;
5147                         }
5148
5149                         for (forCnt = 0; forCnt < colNum; ++forCnt) {
5150                                 u32 i_ns;
5151
5152                                 /* skip the space */
5153                                 while (szLine[i] == ' ' || szLine[i] == '\t')
5154                                         i++;
5155                                 i_ns = i;
5156
5157                                 while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0')
5158                                         i++;
5159
5160                                 regulation[forCnt] = (char *)rtw_malloc(i - i_ns + 1);
5161                                 if (!regulation[forCnt]) {
5162                                         RTW_ERR("Regulation alloc fail\n");
5163                                         goto exit;
5164                                 }
5165
5166                                 _rtw_memcpy(regulation[forCnt], szLine + i_ns, i - i_ns);
5167                                 regulation[forCnt][i - i_ns] = '\0';
5168                         }
5169
5170                         if (DBG_TXPWR_LMT_FILE_PARSE) {
5171                                 RTW_PRINT("column name:");
5172                                 for (forCnt = 0; forCnt < colNum; ++forCnt)
5173                                         _RTW_PRINT(" %s", regulation[forCnt]);
5174                                 _RTW_PRINT("\n");
5175                         }
5176
5177                         loadingStage = LD_STAGE_CH_ROW;
5178                 } else if (loadingStage == LD_STAGE_CH_ROW) {
5179                         char    channel[10] = {0}, powerLimit[10] = {0};
5180                         u8      cnt = 0;
5181
5182                         /* the table ends */
5183                         if (szLine[0] == '#' && szLine[1] == '#') {
5184                                 i = 2;
5185                                 while (szLine[i] == ' ' || szLine[i] == '\t')
5186                                         ++i;
5187
5188                                 if (eqNByte((u8 *)(szLine + i), (u8 *)("END"), 3)) {
5189                                         loadingStage = LD_STAGE_TAB_DEFINE;
5190                                         if (regulation) {
5191                                                 for (forCnt = 0; forCnt < colNum; ++forCnt) {
5192                                                         if (regulation[forCnt]) {
5193                                                                 rtw_mfree(regulation[forCnt], strlen(regulation[forCnt]) + 1);
5194                                                                 regulation[forCnt] = NULL;
5195                                                         }
5196                                                 }
5197                                                 rtw_mfree((u8 *)regulation, sizeof(char *) * colNum);
5198                                                 regulation = NULL;
5199                                         }
5200                                         colNum = 0;
5201                                         continue;
5202                                 } else {
5203                                         RTW_ERR("Missing \"##   END\" label\n");
5204                                         goto exit;
5205                                 }
5206                         }
5207
5208                         if ((szLine[0] != 'c' && szLine[0] != 'C') ||
5209                                 (szLine[1] != 'h' && szLine[1] != 'H')
5210                         ) {
5211                                 RTW_WARN("Wrong channel prefix: '%c','%c'(%d,%d)\n", szLine[0], szLine[1], szLine[0], szLine[1]);
5212                                 continue;
5213                         }
5214                         i = 2;/* move to the  location behind 'h' */
5215
5216                         /* load the channel number */
5217                         cnt = 0;
5218                         while (szLine[i] >= '0' && szLine[i] <= '9') {
5219                                 channel[cnt] = szLine[i];
5220                                 ++cnt;
5221                                 ++i;
5222                         }
5223                         /* RTW_INFO("chnl %s!\n", channel); */
5224
5225                         for (forCnt = 0; forCnt < colNum; ++forCnt) {
5226                                 /* skip the space between channel number and the power limit value */
5227                                 while (szLine[i] == ' ' || szLine[i] == '\t')
5228                                         ++i;
5229
5230                                 /* load the power limit value */
5231                                 _rtw_memset((PVOID) powerLimit, 0, 10);
5232
5233                                 if (szLine[i] == 'W' && szLine[i + 1] == 'W') {
5234                                         /*
5235                                         * case "WW" assign special ww value
5236                                         * means to get minimal limit in other regulations at same channel
5237                                         */
5238                                         s8 ww_value = phy_txpwr_ww_lmt_value(Adapter);
5239
5240                                         sprintf(powerLimit, "%d", ww_value);
5241                                         i += 2;
5242
5243                                 } else if (szLine[i] == 'N' && szLine[i + 1] == 'A') {
5244                                         /*
5245                                         * case "NA" assign max txgi value
5246                                         * means no limitation
5247                                         */
5248                                         sprintf(powerLimit, "%d", hal_spec->txgi_max);
5249                                         i += 2;
5250
5251                                 } else if ((szLine[i] >= '0' && szLine[i] <= '9') || szLine[i] == '.'
5252                                         || szLine[i] == '+' || szLine[i] == '-'
5253                                 ){
5254                                         /* case of dBm value */
5255                                         u8 integer = 0, fraction = 0, negative = 0;
5256                                         u32 u4bMove;
5257                                         s8 lmt = 0;
5258
5259                                         if (szLine[i] == '+' || szLine[i] == '-') {
5260                                                 if (szLine[i] == '-')
5261                                                         negative = 1;
5262                                                 i++;
5263                                         }
5264
5265                                         if (GetFractionValueFromString(&szLine[i], &integer, &fraction, &u4bMove))
5266                                                 i += u4bMove;
5267                                         else {
5268                                                 RTW_ERR("Limit \"%s\" is not valid decimal\n", &szLine[i]);
5269                                                 goto exit;
5270                                         }
5271
5272                                         /* transform to string of value in unit of txgi */
5273                                         lmt = integer * hal_spec->txgi_pdbm + ((u16)fraction * (u16)hal_spec->txgi_pdbm) / 100;
5274                                         if (negative)
5275                                                 lmt = -lmt;
5276                                         sprintf(powerLimit, "%d", lmt);
5277
5278                                 } else {
5279                                         RTW_ERR("Wrong limit expression \"%c%c\"(%d, %d)\n"
5280                                                 , szLine[i], szLine[i + 1], szLine[i], szLine[i + 1]);
5281                                         goto exit;
5282                                 }
5283
5284                                 /* store the power limit value */
5285                                 phy_set_tx_power_limit(pDM_Odm, (u8 *)regulation[forCnt], (u8 *)band,
5286                                         (u8 *)bandwidth, (u8 *)rateSection, (u8 *)ntx, (u8 *)channel, (u8 *)powerLimit);
5287
5288                         }
5289                 }
5290         }
5291
5292         rtStatus = _SUCCESS;
5293
5294 exit:
5295         if (regulation) {
5296                 for (forCnt = 0; forCnt < colNum; ++forCnt) {
5297                         if (regulation[forCnt]) {
5298                                 rtw_mfree(regulation[forCnt], strlen(regulation[forCnt]) + 1);
5299                                 regulation[forCnt] = NULL;
5300                         }
5301                 }
5302                 rtw_mfree((u8 *)regulation, sizeof(char *) * colNum);
5303                 regulation = NULL;
5304         }
5305
5306         RTW_INFO("%s return %d\n", __func__, rtStatus);
5307         return rtStatus;
5308 }
5309
5310 int
5311 PHY_ConfigRFWithPowerLimitTableParaFile(
5312         IN      PADAPTER        Adapter,
5313         IN      const char      *pFileName
5314 )
5315 {
5316         HAL_DATA_TYPE           *pHalData = GET_HAL_DATA(Adapter);
5317         int     rlen = 0, rtStatus = _FAIL;
5318
5319         if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_LMT_PARA_FILE))
5320                 return rtStatus;
5321
5322         _rtw_memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN);
5323
5324         if (pHalData->rf_tx_pwr_lmt == NULL) {
5325                 rtw_get_phy_file_path(Adapter, pFileName);
5326                 if (rtw_is_file_readable(rtw_phy_para_file_path) == _TRUE) {
5327                         rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN);
5328                         if (rlen > 0) {
5329                                 rtStatus = _SUCCESS;
5330                                 pHalData->rf_tx_pwr_lmt = rtw_zvmalloc(rlen);
5331                                 if (pHalData->rf_tx_pwr_lmt) {
5332                                         _rtw_memcpy(pHalData->rf_tx_pwr_lmt, pHalData->para_file_buf, rlen);
5333                                         pHalData->rf_tx_pwr_lmt_len = rlen;
5334                                 } else
5335                                         RTW_INFO("%s rf_tx_pwr_lmt alloc fail !\n", __FUNCTION__);
5336                         }
5337                 }
5338         } else {
5339                 if ((pHalData->rf_tx_pwr_lmt_len != 0) && (pHalData->rf_tx_pwr_lmt != NULL)) {
5340                         _rtw_memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len);
5341                         rtStatus = _SUCCESS;
5342                 } else
5343                         RTW_INFO("%s(): Critical Error !!!\n", __FUNCTION__);
5344         }
5345
5346         if (rtStatus == _SUCCESS) {
5347                 /* RTW_INFO("%s(): read %s ok\n", __FUNCTION__, pFileName); */
5348                 rtStatus = phy_ParsePowerLimitTableFile(Adapter, pHalData->para_file_buf);
5349         } else
5350                 RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __FUNCTION__, pFileName);
5351
5352         return rtStatus;
5353 }
5354 #endif /* CONFIG_TXPWR_LIMIT */
5355
5356 void phy_free_filebuf_mask(_adapter *padapter, u8 mask)
5357 {
5358         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
5359
5360         if (pHalData->mac_reg && (mask & LOAD_MAC_PARA_FILE)) {
5361                 rtw_vmfree(pHalData->mac_reg, pHalData->mac_reg_len);
5362                 pHalData->mac_reg = NULL;
5363         }
5364         if (mask & LOAD_BB_PARA_FILE) {
5365                 if (pHalData->bb_phy_reg) {
5366                         rtw_vmfree(pHalData->bb_phy_reg, pHalData->bb_phy_reg_len);
5367                         pHalData->bb_phy_reg = NULL;
5368                 }
5369                 if (pHalData->bb_agc_tab) {
5370                         rtw_vmfree(pHalData->bb_agc_tab, pHalData->bb_agc_tab_len);
5371                         pHalData->bb_agc_tab = NULL;
5372                 }
5373         }
5374         if (pHalData->bb_phy_reg_pg && (mask & LOAD_BB_PG_PARA_FILE)) {
5375                 rtw_vmfree(pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len);
5376                 pHalData->bb_phy_reg_pg = NULL;
5377         }
5378         if (pHalData->bb_phy_reg_mp && (mask & LOAD_BB_MP_PARA_FILE)) {
5379                 rtw_vmfree(pHalData->bb_phy_reg_mp, pHalData->bb_phy_reg_mp_len);
5380                 pHalData->bb_phy_reg_mp = NULL;
5381         }
5382         if (mask & LOAD_RF_PARA_FILE) {
5383                 if (pHalData->rf_radio_a) {
5384                         rtw_vmfree(pHalData->rf_radio_a, pHalData->rf_radio_a_len);
5385                         pHalData->rf_radio_a = NULL;
5386                 }
5387                 if (pHalData->rf_radio_b) {
5388                         rtw_vmfree(pHalData->rf_radio_b, pHalData->rf_radio_b_len);
5389                         pHalData->rf_radio_b = NULL;
5390                 }
5391         }
5392         if (pHalData->rf_tx_pwr_track && (mask & LOAD_RF_TXPWR_TRACK_PARA_FILE)) {
5393                 rtw_vmfree(pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len);
5394                 pHalData->rf_tx_pwr_track = NULL;
5395         }
5396         if (pHalData->rf_tx_pwr_lmt && (mask & LOAD_RF_TXPWR_LMT_PARA_FILE)) {
5397                 rtw_vmfree(pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len);
5398                 pHalData->rf_tx_pwr_lmt = NULL;
5399         }
5400 }
5401
5402 inline void phy_free_filebuf(_adapter *padapter)
5403 {
5404         phy_free_filebuf_mask(padapter, 0xFF);
5405 }
5406
5407 #endif