1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include "odm_precomp.h" |
9 | |
10 | #define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig_MP_##ic##txt(pDM_Odm)) |
11 | #define READ_AND_CONFIG READ_AND_CONFIG_MP |
12 | |
13 | static u8 odm_query_rx_pwr_percentage(s8 ant_power) |
14 | { |
15 | if ((ant_power <= -100) || (ant_power >= 20)) |
16 | return 0; |
17 | else if (ant_power >= 0) |
18 | return 100; |
19 | else |
20 | return 100 + ant_power; |
21 | |
22 | } |
23 | |
24 | s32 odm_signal_scale_mapping(struct dm_odm_t *dm_odm, s32 curr_sig) |
25 | { |
26 | s32 ret_sig = 0; |
27 | |
28 | if (dm_odm->SupportInterface == ODM_ITRF_SDIO) { |
29 | if (curr_sig >= 51 && curr_sig <= 100) |
30 | ret_sig = 100; |
31 | else if (curr_sig >= 41 && curr_sig <= 50) |
32 | ret_sig = 80 + ((curr_sig - 40)*2); |
33 | else if (curr_sig >= 31 && curr_sig <= 40) |
34 | ret_sig = 66 + (curr_sig - 30); |
35 | else if (curr_sig >= 21 && curr_sig <= 30) |
36 | ret_sig = 54 + (curr_sig - 20); |
37 | else if (curr_sig >= 10 && curr_sig <= 20) |
38 | ret_sig = 42 + (((curr_sig - 10) * 2) / 3); |
39 | else if (curr_sig >= 5 && curr_sig <= 9) |
40 | ret_sig = 22 + (((curr_sig - 5) * 3) / 2); |
41 | else if (curr_sig >= 1 && curr_sig <= 4) |
42 | ret_sig = 6 + (((curr_sig - 1) * 3) / 2); |
43 | else |
44 | ret_sig = curr_sig; |
45 | } |
46 | |
47 | return ret_sig; |
48 | } |
49 | |
50 | static u8 odm_evm_db_to_percentage(s8 value) |
51 | { |
52 | /* */ |
53 | /* -33dB~0dB to 0%~99% */ |
54 | /* */ |
55 | s8 ret_val; |
56 | |
57 | ret_val = value; |
58 | ret_val /= 2; |
59 | |
60 | if (ret_val >= 0) |
61 | ret_val = 0; |
62 | if (ret_val <= -33) |
63 | ret_val = -33; |
64 | |
65 | ret_val = 0 - ret_val; |
66 | ret_val *= 3; |
67 | |
68 | if (ret_val == 99) |
69 | ret_val = 100; |
70 | |
71 | return ret_val; |
72 | } |
73 | |
74 | static s8 (u8 lna_idx, u8 vga_idx) |
75 | { |
76 | s8 rx_pwr_all = 0x00; |
77 | |
78 | switch (lna_idx) { |
79 | /* 46 53 73 95 201301231630 */ |
80 | /* 46 53 77 99 201301241630 */ |
81 | |
82 | case 6: |
83 | rx_pwr_all = -34 - (2 * vga_idx); |
84 | break; |
85 | case 4: |
86 | rx_pwr_all = -14 - (2 * vga_idx); |
87 | break; |
88 | case 1: |
89 | rx_pwr_all = 6 - (2 * vga_idx); |
90 | break; |
91 | case 0: |
92 | rx_pwr_all = 16 - (2 * vga_idx); |
93 | break; |
94 | default: |
95 | /* rx_pwr_all = -53+(2*(31-VGA_idx)); */ |
96 | break; |
97 | } |
98 | return rx_pwr_all; |
99 | } |
100 | |
101 | static void odm_rx_phy_status_parsing(struct dm_odm_t *dm_odm, |
102 | struct odm_phy_info *phy_info, |
103 | u8 *phy_status, |
104 | struct odm_packet_info *pkt_info) |
105 | { |
106 | u8 i; |
107 | s8 rx_pwr[4], rx_pwr_all = 0; |
108 | u8 evm, pwdb_all = 0, pwdb_all_bt; |
109 | u8 , = 0; |
110 | bool is_cck_rate = false; |
111 | u8 rf_rx_num = 0; |
112 | u8 lna_idx, vga_idx; |
113 | struct phy_status_rpt_8192cd_t *phy_sta_rpt = (struct phy_status_rpt_8192cd_t *)phy_status; |
114 | |
115 | is_cck_rate = pkt_info->data_rate <= DESC_RATE11M; |
116 | phy_info->rx_mimo_signal_quality[RF_PATH_A] = -1; |
117 | phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1; |
118 | |
119 | |
120 | if (is_cck_rate) { |
121 | u8 cck_agc_rpt; |
122 | |
123 | dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++; |
124 | |
125 | /* |
126 | * (1)Hardware does not provide RSSI for CCK/ |
127 | * (2)PWDB, Average PWDB calculated by |
128 | * hardware (for rate adaptive) |
129 | */ |
130 | |
131 | cck_agc_rpt = phy_sta_rpt->cck_agc_rpt_ofdm_cfosho_a; |
132 | |
133 | /* |
134 | * 2011.11.28 LukeLee: 88E use different LNA & VGA gain table |
135 | * The RSSI formula should be modified according to the gain table |
136 | */ |
137 | lna_idx = ((cck_agc_rpt & 0xE0)>>5); |
138 | vga_idx = (cck_agc_rpt & 0x1F); |
139 | rx_pwr_all = odm_cck_rssi(lna_idx, vga_idx); |
140 | pwdb_all = odm_query_rx_pwr_percentage(ant_power: rx_pwr_all); |
141 | if (pwdb_all > 100) |
142 | pwdb_all = 100; |
143 | |
144 | phy_info->rx_pwd_ba11 = pwdb_all; |
145 | phy_info->bt_rx_rssi_percentage = pwdb_all; |
146 | phy_info->recv_signal_power = rx_pwr_all; |
147 | |
148 | /* (3) Get Signal Quality (EVM) */ |
149 | |
150 | /* if (pPktinfo->bPacketMatchBSSID) */ |
151 | { |
152 | u8 sq, sq_rpt; |
153 | |
154 | if (phy_info->rx_pwd_ba11 > 40 && !dm_odm->bInHctTest) |
155 | sq = 100; |
156 | else { |
157 | sq_rpt = phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all; |
158 | |
159 | if (sq_rpt > 64) |
160 | sq = 0; |
161 | else if (sq_rpt < 20) |
162 | sq = 100; |
163 | else |
164 | sq = ((64-sq_rpt) * 100) / 44; |
165 | |
166 | } |
167 | |
168 | phy_info->signal_quality = sq; |
169 | phy_info->rx_mimo_signal_quality[RF_PATH_A] = sq; |
170 | phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1; |
171 | } |
172 | } else { /* is OFDM rate */ |
173 | dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++; |
174 | |
175 | /* |
176 | * (1)Get RSSI for HT rate |
177 | */ |
178 | |
179 | for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { |
180 | /* 2008/01/30 MH we will judge RF RX path now. */ |
181 | if (dm_odm->RFPathRxEnable & BIT(i)) |
182 | rf_rx_num++; |
183 | /* else */ |
184 | /* continue; */ |
185 | |
186 | rx_pwr[i] = ((phy_sta_rpt->path_agc[i].gain & 0x3F) * 2) - 110; |
187 | |
188 | phy_info->rx_pwr[i] = rx_pwr[i]; |
189 | |
190 | /* Translate DBM to percentage. */ |
191 | rssi = odm_query_rx_pwr_percentage(ant_power: rx_pwr[i]); |
192 | total_rssi += rssi; |
193 | |
194 | phy_info->rx_mimo_signal_strength[i] = (u8)rssi; |
195 | |
196 | /* Get Rx snr value in DB */ |
197 | phy_info->rx_snr[i] = dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(phy_sta_rpt->path_rxsnr[i]/2); |
198 | } |
199 | |
200 | /* |
201 | * (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) |
202 | */ |
203 | rx_pwr_all = ((phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all >> 1) & 0x7f) - 110; |
204 | |
205 | pwdb_all_bt = pwdb_all = odm_query_rx_pwr_percentage(ant_power: rx_pwr_all); |
206 | |
207 | phy_info->rx_pwd_ba11 = pwdb_all; |
208 | phy_info->bt_rx_rssi_percentage = pwdb_all_bt; |
209 | phy_info->rx_power = rx_pwr_all; |
210 | phy_info->recv_signal_power = rx_pwr_all; |
211 | |
212 | /* |
213 | * (3)EVM of HT rate |
214 | * |
215 | * Only spatial stream 1 makes sense |
216 | * |
217 | * Do not use shift operation like "rx_evmX >>= 1" |
218 | * because the compiler of free build environment |
219 | * fill most significant bit to "zero" when doing |
220 | * shifting operation which may change a negative |
221 | * value to positive one, then the dbm value (which |
222 | * is supposed to be negative) is not correct |
223 | * anymore. |
224 | */ |
225 | evm = odm_evm_db_to_percentage(value: phy_sta_rpt->stream_rxevm[0]); /* dbm */ |
226 | |
227 | /* Fill value in RFD, Get the first spatial stream only */ |
228 | phy_info->signal_quality = (u8)(evm & 0xff); |
229 | |
230 | phy_info->rx_mimo_signal_quality[RF_PATH_A] = (u8)(evm & 0xff); |
231 | |
232 | odm_parsing_cfo(pDM_VOID: dm_odm, pPktinfo_VOID: pkt_info, pcfotail: phy_sta_rpt->path_cfotail); |
233 | } |
234 | |
235 | /* |
236 | * UI BSS List signal strength(in percentage), make it good |
237 | * looking, from 0~100. |
238 | * It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). |
239 | */ |
240 | if (is_cck_rate) { |
241 | phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, curr_sig: pwdb_all)); |
242 | } else { |
243 | if (rf_rx_num != 0) { |
244 | phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, curr_sig: total_rssi /= rf_rx_num)); |
245 | } |
246 | } |
247 | } |
248 | |
249 | static void ( |
250 | struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo, struct odm_packet_info *pPktinfo |
251 | ) |
252 | { |
253 | |
254 | s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK, UndecoratedSmoothedOFDM, ; |
255 | u8 isCCKrate = 0; |
256 | u8 , , i; |
257 | u32 OFDM_pkt = 0; |
258 | u32 Weighting = 0; |
259 | PSTA_INFO_T pEntry; |
260 | |
261 | |
262 | if (pPktinfo->station_id == 0xFF) |
263 | return; |
264 | |
265 | pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->station_id]; |
266 | |
267 | if (!IS_STA_VALID(pEntry)) |
268 | return; |
269 | |
270 | if ((!pPktinfo->bssid_match)) |
271 | return; |
272 | |
273 | if (pPktinfo->is_beacon) |
274 | pDM_Odm->PhyDbgInfo.NumQryBeaconPkt++; |
275 | |
276 | isCCKrate = ((pPktinfo->data_rate <= DESC_RATE11M)) ? true : false; |
277 | pDM_Odm->RxRate = pPktinfo->data_rate; |
278 | |
279 | /* Statistic for antenna/path diversity------------------ */ |
280 | if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { |
281 | |
282 | } |
283 | |
284 | /* Smart Antenna Debug Message------------------ */ |
285 | |
286 | UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; |
287 | UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; |
288 | UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; |
289 | |
290 | if (pPktinfo->to_self || pPktinfo->is_beacon) { |
291 | |
292 | if (!isCCKrate) { /* ofdm rate */ |
293 | if (pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] == 0) { |
294 | RSSI_Ave = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; |
295 | pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; |
296 | pDM_Odm->RSSI_B = 0; |
297 | } else { |
298 | pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; |
299 | pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; |
300 | |
301 | if ( |
302 | pPhyInfo->rx_mimo_signal_strength[RF_PATH_A] > |
303 | pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] |
304 | ) { |
305 | RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; |
306 | RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; |
307 | } else { |
308 | RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]; |
309 | RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A]; |
310 | } |
311 | |
312 | if ((RSSI_max-RSSI_min) < 3) |
313 | RSSI_Ave = RSSI_max; |
314 | else if ((RSSI_max-RSSI_min) < 6) |
315 | RSSI_Ave = RSSI_max - 1; |
316 | else if ((RSSI_max-RSSI_min) < 10) |
317 | RSSI_Ave = RSSI_max - 2; |
318 | else |
319 | RSSI_Ave = RSSI_max - 3; |
320 | } |
321 | |
322 | /* 1 Process OFDM RSSI */ |
323 | if (UndecoratedSmoothedOFDM <= 0) /* initialize */ |
324 | UndecoratedSmoothedOFDM = pPhyInfo->rx_pwd_ba11; |
325 | else { |
326 | if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedOFDM) { |
327 | UndecoratedSmoothedOFDM = |
328 | ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) + |
329 | RSSI_Ave)/Rx_Smooth_Factor; |
330 | UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; |
331 | } else { |
332 | UndecoratedSmoothedOFDM = |
333 | ((UndecoratedSmoothedOFDM*(Rx_Smooth_Factor-1)) + |
334 | RSSI_Ave)/Rx_Smooth_Factor; |
335 | } |
336 | } |
337 | |
338 | pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0; |
339 | |
340 | } else { |
341 | RSSI_Ave = pPhyInfo->rx_pwd_ba11; |
342 | pDM_Odm->RSSI_A = (u8) pPhyInfo->rx_pwd_ba11; |
343 | pDM_Odm->RSSI_B = 0; |
344 | |
345 | /* 1 Process CCK RSSI */ |
346 | if (UndecoratedSmoothedCCK <= 0) /* initialize */ |
347 | UndecoratedSmoothedCCK = pPhyInfo->rx_pwd_ba11; |
348 | else { |
349 | if (pPhyInfo->rx_pwd_ba11 > (u32)UndecoratedSmoothedCCK) { |
350 | UndecoratedSmoothedCCK = |
351 | ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) + |
352 | pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor; |
353 | UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; |
354 | } else { |
355 | UndecoratedSmoothedCCK = |
356 | ((UndecoratedSmoothedCCK*(Rx_Smooth_Factor-1)) + |
357 | pPhyInfo->rx_pwd_ba11)/Rx_Smooth_Factor; |
358 | } |
359 | } |
360 | pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1; |
361 | } |
362 | |
363 | /* if (pEntry) */ |
364 | { |
365 | /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ |
366 | if (pEntry->rssi_stat.ValidBit >= 64) |
367 | pEntry->rssi_stat.ValidBit = 64; |
368 | else |
369 | pEntry->rssi_stat.ValidBit++; |
370 | |
371 | for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) |
372 | OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0; |
373 | |
374 | if (pEntry->rssi_stat.ValidBit == 64) { |
375 | Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4); |
376 | UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6; |
377 | } else { |
378 | if (pEntry->rssi_stat.ValidBit != 0) |
379 | UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit; |
380 | else |
381 | UndecoratedSmoothedPWDB = 0; |
382 | } |
383 | |
384 | pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; |
385 | pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; |
386 | pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; |
387 | } |
388 | |
389 | } |
390 | } |
391 | |
392 | |
393 | /* */ |
394 | /* Endianness before calling this API */ |
395 | /* */ |
396 | void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info, |
397 | u8 *phy_status, struct odm_packet_info *pkt_info) |
398 | { |
399 | |
400 | odm_rx_phy_status_parsing(dm_odm, phy_info, phy_status, pkt_info); |
401 | |
402 | if (!dm_odm->RSSI_test) |
403 | odm_Process_RSSIForDM(pDM_Odm: dm_odm, pPhyInfo: phy_info, pPktinfo: pkt_info); |
404 | } |
405 | |
406 | /* */ |
407 | /* If you want to add a new IC, Please follow below template and generate a new one. */ |
408 | /* */ |
409 | /* */ |
410 | |
411 | enum hal_status ( |
412 | struct dm_odm_t *pDM_Odm, |
413 | enum ODM_RF_Config_Type ConfigType, |
414 | enum rf_path eRFPath |
415 | ) |
416 | { |
417 | if (ConfigType == CONFIG_RF_RADIO) |
418 | READ_AND_CONFIG(8723B, _RadioA); |
419 | else if (ConfigType == CONFIG_RF_TXPWR_LMT) |
420 | READ_AND_CONFIG(8723B, _TXPWR_LMT); |
421 | |
422 | return HAL_STATUS_SUCCESS; |
423 | } |
424 | |
425 | enum hal_status (struct dm_odm_t *pDM_Odm) |
426 | { |
427 | if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO) |
428 | READ_AND_CONFIG(8723B, _TxPowerTrack_SDIO); |
429 | |
430 | return HAL_STATUS_SUCCESS; |
431 | } |
432 | |
433 | enum hal_status ( |
434 | struct dm_odm_t *pDM_Odm, enum ODM_BB_Config_Type ConfigType |
435 | ) |
436 | { |
437 | if (ConfigType == CONFIG_BB_PHY_REG) |
438 | READ_AND_CONFIG(8723B, _PHY_REG); |
439 | else if (ConfigType == CONFIG_BB_AGC_TAB) |
440 | READ_AND_CONFIG(8723B, _AGC_TAB); |
441 | else if (ConfigType == CONFIG_BB_PHY_REG_PG) |
442 | READ_AND_CONFIG(8723B, _PHY_REG_PG); |
443 | |
444 | return HAL_STATUS_SUCCESS; |
445 | } |
446 | |
447 | |