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