GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / staging / rtlwifi / phydm / rtl_phydm.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2016  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  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 #include "mp_precomp.h"
26 #include "phydm_precomp.h"
27 #include <linux/module.h>
28
29 static int _rtl_phydm_init_com_info(struct rtl_priv *rtlpriv,
30                                     enum odm_ic_type ic_type,
31                                     struct rtl_phydm_params *params)
32 {
33         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
34         struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
35         struct rtl_phy *rtlphy = &rtlpriv->phy;
36         struct rtl_mac *mac = rtl_mac(rtlpriv);
37         struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
38         struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
39         u8 odm_board_type = ODM_BOARD_DEFAULT;
40         u32 support_ability;
41         int i;
42
43         dm->adapter = (void *)rtlpriv;
44
45         odm_cmn_info_init(dm, ODM_CMNINFO_PLATFORM, ODM_CE);
46
47         odm_cmn_info_init(dm, ODM_CMNINFO_IC_TYPE, ic_type);
48
49         odm_cmn_info_init(dm, ODM_CMNINFO_INTERFACE, ODM_ITRF_PCIE);
50
51         odm_cmn_info_init(dm, ODM_CMNINFO_MP_TEST_CHIP, params->mp_chip);
52
53         odm_cmn_info_init(dm, ODM_CMNINFO_PATCH_ID, rtlhal->oem_id);
54
55         odm_cmn_info_init(dm, ODM_CMNINFO_BWIFI_TEST, 1);
56
57         if (rtlphy->rf_type == RF_1T1R)
58                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
59         else if (rtlphy->rf_type == RF_1T2R)
60                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
61         else if (rtlphy->rf_type == RF_2T2R)
62                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
63         else if (rtlphy->rf_type == RF_2T2R_GREEN)
64                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R_GREEN);
65         else if (rtlphy->rf_type == RF_2T3R)
66                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T3R);
67         else if (rtlphy->rf_type == RF_2T4R)
68                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T4R);
69         else if (rtlphy->rf_type == RF_3T3R)
70                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T3R);
71         else if (rtlphy->rf_type == RF_3T4R)
72                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T4R);
73         else if (rtlphy->rf_type == RF_4T4R)
74                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_4T4R);
75         else
76                 odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_XTXR);
77
78         /* 1 ======= BoardType: ODM_CMNINFO_BOARD_TYPE ======= */
79         if (rtlhal->external_lna_2g != 0) {
80                 odm_board_type |= ODM_BOARD_EXT_LNA;
81                 odm_cmn_info_init(dm, ODM_CMNINFO_EXT_LNA, 1);
82         }
83         if (rtlhal->external_lna_5g != 0) {
84                 odm_board_type |= ODM_BOARD_EXT_LNA_5G;
85                 odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_LNA, 1);
86         }
87         if (rtlhal->external_pa_2g != 0) {
88                 odm_board_type |= ODM_BOARD_EXT_PA;
89                 odm_cmn_info_init(dm, ODM_CMNINFO_EXT_PA, 1);
90         }
91         if (rtlhal->external_pa_5g != 0) {
92                 odm_board_type |= ODM_BOARD_EXT_PA_5G;
93                 odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_PA, 1);
94         }
95         if (rtlpriv->cfg->ops->get_btc_status())
96                 odm_board_type |= ODM_BOARD_BT;
97
98         odm_cmn_info_init(dm, ODM_CMNINFO_BOARD_TYPE, odm_board_type);
99         /* 1 ============== End of BoardType ============== */
100
101         odm_cmn_info_init(dm, ODM_CMNINFO_GPA, rtlhal->type_gpa);
102         odm_cmn_info_init(dm, ODM_CMNINFO_APA, rtlhal->type_apa);
103         odm_cmn_info_init(dm, ODM_CMNINFO_GLNA, rtlhal->type_glna);
104         odm_cmn_info_init(dm, ODM_CMNINFO_ALNA, rtlhal->type_alna);
105
106         odm_cmn_info_init(dm, ODM_CMNINFO_RFE_TYPE, rtlhal->rfe_type);
107
108         odm_cmn_info_init(dm, ODM_CMNINFO_EXT_TRSW, 0);
109
110         /*Add by YuChen for kfree init*/
111         odm_cmn_info_init(dm, ODM_CMNINFO_REGRFKFREEENABLE, 2);
112         odm_cmn_info_init(dm, ODM_CMNINFO_RFKFREEENABLE, 0);
113
114         /*Antenna diversity relative parameters*/
115         odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_DIV,
116                           &rtlefuse->antenna_div_cfg);
117         odm_cmn_info_init(dm, ODM_CMNINFO_RF_ANTENNA_TYPE,
118                           rtlefuse->antenna_div_type);
119         odm_cmn_info_init(dm, ODM_CMNINFO_BE_FIX_TX_ANT, 0);
120         odm_cmn_info_init(dm, ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH, 0);
121
122         /* (8822B) efuse 0x3D7 & 0x3D8 for TX PA bias */
123         odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D7, params->efuse0x3d7);
124         odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D8, params->efuse0x3d8);
125
126         /*Add by YuChen for adaptivity init*/
127         odm_cmn_info_hook(dm, ODM_CMNINFO_ADAPTIVITY,
128                           &rtlpriv->phydm.adaptivity_en);
129         phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE,
130                                    false);
131         phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DCBACKOFF, 0);
132         phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY,
133                                    false);
134         phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_L2H_INI, 0);
135         phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF, 0);
136
137         odm_cmn_info_init(dm, ODM_CMNINFO_IQKFWOFFLOAD, 0);
138
139         /* Pointer reference */
140         odm_cmn_info_hook(dm, ODM_CMNINFO_TX_UNI,
141                           &rtlpriv->stats.txbytesunicast);
142         odm_cmn_info_hook(dm, ODM_CMNINFO_RX_UNI,
143                           &rtlpriv->stats.rxbytesunicast);
144         odm_cmn_info_hook(dm, ODM_CMNINFO_BAND, &rtlhal->current_bandtype);
145         odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_RATE,
146                           &rtlpriv->phydm.forced_data_rate);
147         odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_IGI_LB,
148                           &rtlpriv->phydm.forced_igi_lb);
149
150         odm_cmn_info_hook(dm, ODM_CMNINFO_SEC_CHNL_OFFSET,
151                           &mac->cur_40_prime_sc);
152         odm_cmn_info_hook(dm, ODM_CMNINFO_BW, &rtlphy->current_chan_bw);
153         odm_cmn_info_hook(dm, ODM_CMNINFO_CHNL, &rtlphy->current_channel);
154
155         odm_cmn_info_hook(dm, ODM_CMNINFO_SCAN, &mac->act_scanning);
156         odm_cmn_info_hook(dm, ODM_CMNINFO_POWER_SAVING,
157                           &ppsc->dot11_psmode); /* may add new boolean flag */
158         /*Add by Yuchen for phydm beamforming*/
159         odm_cmn_info_hook(dm, ODM_CMNINFO_TX_TP,
160                           &rtlpriv->stats.txbytesunicast_inperiod_tp);
161         odm_cmn_info_hook(dm, ODM_CMNINFO_RX_TP,
162                           &rtlpriv->stats.rxbytesunicast_inperiod_tp);
163         odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_TEST,
164                           &rtlpriv->phydm.antenna_test);
165         for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++)
166                 odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, i,
167                                             NULL);
168
169         phydm_init_debug_setting(dm);
170
171         odm_cmn_info_init(dm, ODM_CMNINFO_FAB_VER, params->fab_ver);
172         odm_cmn_info_init(dm, ODM_CMNINFO_CUT_VER, params->cut_ver);
173
174         /* after ifup, ability is updated again */
175         support_ability = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK;
176         odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, support_ability);
177
178         return 0;
179 }
180
181 static int rtl_phydm_init_priv(struct rtl_priv *rtlpriv,
182                                struct rtl_phydm_params *params)
183 {
184         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
185         enum odm_ic_type ic;
186
187         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
188                 ic = ODM_RTL8822B;
189         else
190                 return 0;
191
192         rtlpriv->phydm.internal =
193                 kzalloc(sizeof(struct phy_dm_struct), GFP_KERNEL);
194         if (!rtlpriv->phydm.internal)
195                 return 0;
196
197         _rtl_phydm_init_com_info(rtlpriv, ic, params);
198
199         odm_init_all_timers(dm);
200
201         return 1;
202 }
203
204 static int rtl_phydm_deinit_priv(struct rtl_priv *rtlpriv)
205 {
206         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
207
208         odm_cancel_all_timers(dm);
209
210         kfree(rtlpriv->phydm.internal);
211         rtlpriv->phydm.internal = NULL;
212
213         return 0;
214 }
215
216 static bool rtl_phydm_load_txpower_by_rate(struct rtl_priv *rtlpriv)
217 {
218         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
219         enum hal_status status;
220
221         status = odm_config_bb_with_header_file(dm, CONFIG_BB_PHY_REG_PG);
222         if (status != HAL_STATUS_SUCCESS)
223                 return false;
224
225         return true;
226 }
227
228 static bool rtl_phydm_load_txpower_limit(struct rtl_priv *rtlpriv)
229 {
230         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
231         enum hal_status status;
232
233         if (IS_HARDWARE_TYPE_8822B(rtlpriv)) {
234                 odm_read_and_config_mp_8822b_txpwr_lmt(dm);
235         } else {
236                 status = odm_config_rf_with_header_file(dm, CONFIG_RF_TXPWR_LMT,
237                                                         0);
238                 if (status != HAL_STATUS_SUCCESS)
239                         return false;
240         }
241
242         return true;
243 }
244
245 static int rtl_phydm_init_dm(struct rtl_priv *rtlpriv)
246 {
247         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
248         u32 support_ability = 0;
249
250         /* clang-format off */
251         support_ability = 0
252                         | ODM_BB_DIG
253                         | ODM_BB_RA_MASK
254                         | ODM_BB_DYNAMIC_TXPWR
255                         | ODM_BB_FA_CNT
256                         | ODM_BB_RSSI_MONITOR
257                         | ODM_BB_CCK_PD
258         /*              | ODM_BB_PWR_SAVE*/
259                         | ODM_BB_CFO_TRACKING
260                         | ODM_MAC_EDCA_TURBO
261                         | ODM_RF_TX_PWR_TRACK
262                         | ODM_RF_CALIBRATION
263                         | ODM_BB_NHM_CNT
264         /*              | ODM_BB_PWR_TRAIN*/
265                         ;
266         /* clang-format on */
267
268         odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, support_ability);
269
270         odm_dm_init(dm);
271
272         return 0;
273 }
274
275 static int rtl_phydm_deinit_dm(struct rtl_priv *rtlpriv)
276 {
277         return 0;
278 }
279
280 static int rtl_phydm_reset_dm(struct rtl_priv *rtlpriv)
281 {
282         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
283
284         odm_dm_reset(dm);
285
286         return 0;
287 }
288
289 static bool rtl_phydm_parameter_init(struct rtl_priv *rtlpriv, bool post)
290 {
291         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
292
293         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
294                 return config_phydm_parameter_init(dm, post ? ODM_POST_SETTING :
295                                                               ODM_PRE_SETTING);
296
297         return false;
298 }
299
300 static bool rtl_phydm_phy_bb_config(struct rtl_priv *rtlpriv)
301 {
302         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
303         enum hal_status status;
304
305         status = odm_config_bb_with_header_file(dm, CONFIG_BB_PHY_REG);
306         if (status != HAL_STATUS_SUCCESS)
307                 return false;
308
309         status = odm_config_bb_with_header_file(dm, CONFIG_BB_AGC_TAB);
310         if (status != HAL_STATUS_SUCCESS)
311                 return false;
312
313         return true;
314 }
315
316 static bool rtl_phydm_phy_rf_config(struct rtl_priv *rtlpriv)
317 {
318         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
319         struct rtl_phy *rtlphy = &rtlpriv->phy;
320         enum hal_status status;
321         enum odm_rf_radio_path rfpath;
322
323         for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
324                 status = odm_config_rf_with_header_file(dm, CONFIG_RF_RADIO,
325                                                         rfpath);
326                 if (status != HAL_STATUS_SUCCESS)
327                         return false;
328         }
329
330         status = odm_config_rf_with_tx_pwr_track_header_file(dm);
331         if (status != HAL_STATUS_SUCCESS)
332                 return false;
333
334         return true;
335 }
336
337 static bool rtl_phydm_phy_mac_config(struct rtl_priv *rtlpriv)
338 {
339         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
340         enum hal_status status;
341
342         status = odm_config_mac_with_header_file(dm);
343         if (status != HAL_STATUS_SUCCESS)
344                 return false;
345
346         return true;
347 }
348
349 static bool rtl_phydm_trx_mode(struct rtl_priv *rtlpriv,
350                                enum radio_mask tx_path, enum radio_mask rx_path,
351                                bool is_tx2_path)
352 {
353         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
354
355         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
356                 return config_phydm_trx_mode_8822b(dm,
357                                                    (enum odm_rf_path)tx_path,
358                                                    (enum odm_rf_path)rx_path,
359                                                    is_tx2_path);
360
361         return false;
362 }
363
364 static bool rtl_phydm_watchdog(struct rtl_priv *rtlpriv)
365 {
366         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
367         struct rtl_mac *mac = rtl_mac(rtlpriv);
368         struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
369         bool fw_current_inpsmode = false;
370         bool fw_ps_awake = true;
371         u8 is_linked = false;
372         u8 bsta_state = false;
373         u8 is_bt_enabled = false;
374
375         /* check whether do watchdog */
376         rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FW_PSMODE_STATUS,
377                                       (u8 *)(&fw_current_inpsmode));
378         rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FWLPS_RF_ON,
379                                       (u8 *)(&fw_ps_awake));
380         if (ppsc->p2p_ps_info.p2p_ps_mode)
381                 fw_ps_awake = false;
382
383         if ((ppsc->rfpwr_state == ERFON) &&
384             ((!fw_current_inpsmode) && fw_ps_awake) &&
385             (!ppsc->rfchange_inprogress))
386                 ;
387         else
388                 return false;
389
390         /* update common info before doing watchdog */
391         if (mac->link_state >= MAC80211_LINKED) {
392                 is_linked = true;
393                 if (mac->vif && mac->vif->type == NL80211_IFTYPE_STATION)
394                         bsta_state = true;
395         }
396
397         if (rtlpriv->cfg->ops->get_btc_status())
398                 is_bt_enabled = !rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(
399                         rtlpriv);
400
401         odm_cmn_info_update(dm, ODM_CMNINFO_LINK, is_linked);
402         odm_cmn_info_update(dm, ODM_CMNINFO_STATION_STATE, bsta_state);
403         odm_cmn_info_update(dm, ODM_CMNINFO_BT_ENABLED, is_bt_enabled);
404
405         /* do watchdog */
406         odm_dm_watchdog(dm);
407
408         return true;
409 }
410
411 static bool rtl_phydm_switch_band(struct rtl_priv *rtlpriv, u8 central_ch)
412 {
413         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
414
415         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
416                 return config_phydm_switch_band_8822b(dm, central_ch);
417
418         return false;
419 }
420
421 static bool rtl_phydm_switch_channel(struct rtl_priv *rtlpriv, u8 central_ch)
422 {
423         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
424
425         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
426                 return config_phydm_switch_channel_8822b(dm, central_ch);
427
428         return false;
429 }
430
431 static bool rtl_phydm_switch_bandwidth(struct rtl_priv *rtlpriv,
432                                        u8 primary_ch_idx,
433                                        enum ht_channel_width bandwidth)
434 {
435         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
436         enum odm_bw odm_bw = (enum odm_bw)bandwidth;
437
438         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
439                 return config_phydm_switch_bandwidth_8822b(dm, primary_ch_idx,
440                                                            odm_bw);
441
442         return false;
443 }
444
445 static bool rtl_phydm_iq_calibrate(struct rtl_priv *rtlpriv)
446 {
447         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
448
449         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
450                 phy_iq_calibrate_8822b(dm, false);
451         else
452                 return false;
453
454         return true;
455 }
456
457 static bool rtl_phydm_clear_txpowertracking_state(struct rtl_priv *rtlpriv)
458 {
459         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
460
461         odm_clear_txpowertracking_state(dm);
462
463         return true;
464 }
465
466 static bool rtl_phydm_pause_dig(struct rtl_priv *rtlpriv, bool pause)
467 {
468         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
469
470         if (pause)
471                 odm_pause_dig(dm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_0, 0x1e);
472         else /* resume */
473                 odm_pause_dig(dm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_0, 0xff);
474
475         return true;
476 }
477
478 static u32 rtl_phydm_read_rf_reg(struct rtl_priv *rtlpriv,
479                                  enum radio_path rfpath, u32 addr, u32 mask)
480 {
481         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
482         enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
483
484         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
485                 return config_phydm_read_rf_reg_8822b(dm, odm_rfpath, addr,
486                                                       mask);
487
488         return -1;
489 }
490
491 static bool rtl_phydm_write_rf_reg(struct rtl_priv *rtlpriv,
492                                    enum radio_path rfpath, u32 addr, u32 mask,
493                                    u32 data)
494 {
495         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
496         enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
497
498         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
499                 return config_phydm_write_rf_reg_8822b(dm, odm_rfpath, addr,
500                                                        mask, data);
501
502         return false;
503 }
504
505 static u8 rtl_phydm_read_txagc(struct rtl_priv *rtlpriv, enum radio_path rfpath,
506                                u8 hw_rate)
507 {
508         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
509         enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
510
511         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
512                 return config_phydm_read_txagc_8822b(dm, odm_rfpath, hw_rate);
513
514         return -1;
515 }
516
517 static bool rtl_phydm_write_txagc(struct rtl_priv *rtlpriv, u32 power_index,
518                                   enum radio_path rfpath, u8 hw_rate)
519 {
520         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
521         enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
522
523         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
524                 return config_phydm_write_txagc_8822b(dm, power_index,
525                                                       odm_rfpath, hw_rate);
526
527         return false;
528 }
529
530 static bool rtl_phydm_c2h_content_parsing(struct rtl_priv *rtlpriv, u8 cmd_id,
531                                           u8 cmd_len, u8 *content)
532 {
533         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
534
535         if (phydm_c2H_content_parsing(dm, cmd_id, cmd_len, content))
536                 return true;
537
538         return false;
539 }
540
541 static bool rtl_phydm_query_phy_status(struct rtl_priv *rtlpriv, u8 *phystrpt,
542                                        struct ieee80211_hdr *hdr,
543                                        struct rtl_stats *pstatus)
544 {
545         /* NOTE: phystrpt may be NULL, and need to fill default value */
546
547         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
548         struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
549         struct rtl_mac *mac = rtl_mac(rtlpriv);
550         struct dm_per_pkt_info pktinfo; /* input of pydm */
551         struct dm_phy_status_info phy_info; /* output of phydm */
552         __le16 fc = hdr->frame_control;
553
554         /* fill driver pstatus */
555         ether_addr_copy(pstatus->psaddr, ieee80211_get_SA(hdr));
556
557         /* fill pktinfo */
558         memset(&pktinfo, 0, sizeof(pktinfo));
559
560         pktinfo.data_rate = pstatus->rate;
561
562         if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION) {
563                 pktinfo.station_id = 0;
564         } else {
565                 /* TODO: use rtl_find_sta() to find ID */
566                 pktinfo.station_id = 0xFF;
567         }
568
569         pktinfo.is_packet_match_bssid =
570                 (!ieee80211_is_ctl(fc) &&
571                  (ether_addr_equal(mac->bssid,
572                                    ieee80211_has_tods(fc) ?
573                                            hdr->addr1 :
574                                            ieee80211_has_fromds(fc) ?
575                                            hdr->addr2 :
576                                            hdr->addr3)) &&
577                  (!pstatus->hwerror) && (!pstatus->crc) && (!pstatus->icv));
578         pktinfo.is_packet_to_self =
579                 pktinfo.is_packet_match_bssid &&
580                 (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr));
581         pktinfo.is_to_self = (!pstatus->icv) && (!pstatus->crc) &&
582                              (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr));
583         pktinfo.is_packet_beacon = (ieee80211_is_beacon(fc) ? true : false);
584
585         /* query phy status */
586         if (phystrpt)
587                 odm_phy_status_query(dm, &phy_info, phystrpt, &pktinfo);
588         else
589                 memset(&phy_info, 0, sizeof(phy_info));
590
591         /* copy phy_info from phydm to driver */
592         pstatus->rx_pwdb_all = phy_info.rx_pwdb_all;
593         pstatus->bt_rx_rssi_percentage = phy_info.bt_rx_rssi_percentage;
594         pstatus->recvsignalpower = phy_info.recv_signal_power;
595         pstatus->signalquality = phy_info.signal_quality;
596         pstatus->rx_mimo_signalquality[0] = phy_info.rx_mimo_signal_quality[0];
597         pstatus->rx_mimo_signalquality[1] = phy_info.rx_mimo_signal_quality[1];
598         pstatus->rx_packet_bw =
599                 phy_info.band_width; /* HT_CHANNEL_WIDTH_20 <- ODM_BW20M */
600
601         /* fill driver pstatus */
602         pstatus->packet_matchbssid = pktinfo.is_packet_match_bssid;
603         pstatus->packet_toself = pktinfo.is_packet_to_self;
604         pstatus->packet_beacon = pktinfo.is_packet_beacon;
605
606         return true;
607 }
608
609 static u8 rtl_phydm_rate_id_mapping(struct rtl_priv *rtlpriv,
610                                     enum wireless_mode wireless_mode,
611                                     enum rf_type rf_type,
612                                     enum ht_channel_width bw)
613 {
614         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
615
616         return phydm_rate_id_mapping(dm, wireless_mode, rf_type, bw);
617 }
618
619 static bool rtl_phydm_get_ra_bitmap(struct rtl_priv *rtlpriv,
620                                     enum wireless_mode wireless_mode,
621                                     enum rf_type rf_type,
622                                     enum ht_channel_width bw,
623                                     u8 tx_rate_level, /* 0~6 */
624                                     u32 *tx_bitmap_msb,
625                                     u32 *tx_bitmap_lsb)
626 {
627         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
628         const u8 mimo_ps_enable = 0;
629         const u8 disable_cck_rate = 0;
630
631         phydm_update_hal_ra_mask(dm, wireless_mode, rf_type, bw, mimo_ps_enable,
632                                  disable_cck_rate, tx_bitmap_msb, tx_bitmap_lsb,
633                                  tx_rate_level);
634
635         return true;
636 }
637
638 static u8 _rtl_phydm_get_macid(struct rtl_priv *rtlpriv,
639                                struct ieee80211_sta *sta)
640 {
641         struct rtl_mac *mac = rtl_mac(rtlpriv);
642
643         if (mac->opmode == NL80211_IFTYPE_STATION ||
644             mac->opmode == NL80211_IFTYPE_MESH_POINT) {
645                 return 0;
646         } else if (mac->opmode == NL80211_IFTYPE_AP ||
647                    mac->opmode == NL80211_IFTYPE_ADHOC)
648                 return sta->aid + 1;
649
650         return 0;
651 }
652
653 static bool rtl_phydm_add_sta(struct rtl_priv *rtlpriv,
654                               struct ieee80211_sta *sta)
655 {
656         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
657         struct rtl_sta_info *sta_entry = (struct rtl_sta_info *)sta->drv_priv;
658         u8 mac_id = _rtl_phydm_get_macid(rtlpriv, sta);
659
660         odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, mac_id,
661                                     sta_entry);
662
663         return true;
664 }
665
666 static bool rtl_phydm_del_sta(struct rtl_priv *rtlpriv,
667                               struct ieee80211_sta *sta)
668 {
669         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
670         u8 mac_id = _rtl_phydm_get_macid(rtlpriv, sta);
671
672         odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, mac_id, NULL);
673
674         return true;
675 }
676
677 static u32 rtl_phydm_get_version(struct rtl_priv *rtlpriv)
678 {
679         u32 ver = 0;
680
681         if (IS_HARDWARE_TYPE_8822B(rtlpriv))
682                 ver = RELEASE_VERSION_8822B;
683
684         return ver;
685 }
686
687 static bool rtl_phydm_modify_ra_pcr_threshold(struct rtl_priv *rtlpriv,
688                                               u8 ra_offset_direction,
689                                               u8 ra_threshold_offset)
690 {
691         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
692
693         phydm_modify_RA_PCR_threshold(dm, ra_offset_direction,
694                                       ra_threshold_offset);
695
696         return true;
697 }
698
699 static u32 rtl_phydm_query_counter(struct rtl_priv *rtlpriv,
700                                    const char *info_type)
701 {
702         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
703         static const struct query_entry {
704                 const char *query_name;
705                 enum phydm_info_query query_id;
706         } query_table[] = {
707 #define QUERY_ENTRY(name)       {#name, name}
708                 QUERY_ENTRY(PHYDM_INFO_FA_OFDM),
709                 QUERY_ENTRY(PHYDM_INFO_FA_CCK),
710                 QUERY_ENTRY(PHYDM_INFO_CCA_OFDM),
711                 QUERY_ENTRY(PHYDM_INFO_CCA_CCK),
712                 QUERY_ENTRY(PHYDM_INFO_CRC32_OK_CCK),
713                 QUERY_ENTRY(PHYDM_INFO_CRC32_OK_LEGACY),
714                 QUERY_ENTRY(PHYDM_INFO_CRC32_OK_HT),
715                 QUERY_ENTRY(PHYDM_INFO_CRC32_OK_VHT),
716                 QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_CCK),
717                 QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_LEGACY),
718                 QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_HT),
719                 QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_VHT),
720         };
721 #define QUERY_TABLE_SIZE        ARRAY_SIZE(query_table)
722
723         int i;
724         const struct query_entry *entry;
725
726         if (!strcmp(info_type, "IQK_TOTAL"))
727                 return dm->n_iqk_cnt;
728
729         if (!strcmp(info_type, "IQK_OK"))
730                 return dm->n_iqk_ok_cnt;
731
732         if (!strcmp(info_type, "IQK_FAIL"))
733                 return dm->n_iqk_fail_cnt;
734
735         for (i = 0; i < QUERY_TABLE_SIZE; i++) {
736                 entry = &query_table[i];
737
738                 if (!strcmp(info_type, entry->query_name))
739                         return phydm_cmn_info_query(dm, entry->query_id);
740         }
741
742         pr_err("Unrecognized info_type:%s!!!!:\n", info_type);
743
744         return 0xDEADDEAD;
745 }
746
747 static bool rtl_phydm_debug_cmd(struct rtl_priv *rtlpriv, char *in, u32 in_len,
748                                 char *out, u32 out_len)
749 {
750         struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
751
752         phydm_cmd(dm, in, in_len, 1, out, out_len);
753
754         return true;
755 }
756
757 static struct rtl_phydm_ops rtl_phydm_operation = {
758         /* init/deinit priv */
759         .phydm_init_priv = rtl_phydm_init_priv,
760         .phydm_deinit_priv = rtl_phydm_deinit_priv,
761         .phydm_load_txpower_by_rate = rtl_phydm_load_txpower_by_rate,
762         .phydm_load_txpower_limit = rtl_phydm_load_txpower_limit,
763
764         /* init hw */
765         .phydm_init_dm = rtl_phydm_init_dm,
766         .phydm_deinit_dm = rtl_phydm_deinit_dm,
767         .phydm_reset_dm = rtl_phydm_reset_dm,
768         .phydm_parameter_init = rtl_phydm_parameter_init,
769         .phydm_phy_bb_config = rtl_phydm_phy_bb_config,
770         .phydm_phy_rf_config = rtl_phydm_phy_rf_config,
771         .phydm_phy_mac_config = rtl_phydm_phy_mac_config,
772         .phydm_trx_mode = rtl_phydm_trx_mode,
773
774         /* watchdog */
775         .phydm_watchdog = rtl_phydm_watchdog,
776
777         /* channel */
778         .phydm_switch_band = rtl_phydm_switch_band,
779         .phydm_switch_channel = rtl_phydm_switch_channel,
780         .phydm_switch_bandwidth = rtl_phydm_switch_bandwidth,
781         .phydm_iq_calibrate = rtl_phydm_iq_calibrate,
782         .phydm_clear_txpowertracking_state =
783                 rtl_phydm_clear_txpowertracking_state,
784         .phydm_pause_dig = rtl_phydm_pause_dig,
785
786         /* read/write reg */
787         .phydm_read_rf_reg = rtl_phydm_read_rf_reg,
788         .phydm_write_rf_reg = rtl_phydm_write_rf_reg,
789         .phydm_read_txagc = rtl_phydm_read_txagc,
790         .phydm_write_txagc = rtl_phydm_write_txagc,
791
792         /* RX */
793         .phydm_c2h_content_parsing = rtl_phydm_c2h_content_parsing,
794         .phydm_query_phy_status = rtl_phydm_query_phy_status,
795
796         /* TX */
797         .phydm_rate_id_mapping = rtl_phydm_rate_id_mapping,
798         .phydm_get_ra_bitmap = rtl_phydm_get_ra_bitmap,
799
800         /* STA */
801         .phydm_add_sta = rtl_phydm_add_sta,
802         .phydm_del_sta = rtl_phydm_del_sta,
803
804         /* BTC */
805         .phydm_get_version = rtl_phydm_get_version,
806         .phydm_modify_ra_pcr_threshold = rtl_phydm_modify_ra_pcr_threshold,
807         .phydm_query_counter = rtl_phydm_query_counter,
808
809         /* debug */
810         .phydm_debug_cmd = rtl_phydm_debug_cmd,
811 };
812
813 struct rtl_phydm_ops *rtl_phydm_get_ops_pointer(void)
814 {
815         return &rtl_phydm_operation;
816 }
817 EXPORT_SYMBOL(rtl_phydm_get_ops_pointer);
818
819 /* ********************************************************
820  * Define phydm callout function in below
821  * ********************************************************
822  */
823
824 u8 phy_get_tx_power_index(void *adapter, u8 rf_path, u8 rate,
825                           enum ht_channel_width bandwidth, u8 channel)
826 {
827         /* rate: DESC_RATE1M */
828         struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
829
830         return rtlpriv->cfg->ops->get_txpower_index(rtlpriv->hw, rf_path, rate,
831                                                     bandwidth, channel);
832 }
833
834 void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs)
835 {
836         struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
837
838         return rtlpriv->cfg->ops->set_tx_power_index_by_rs(rtlpriv->hw, ch,
839                                                            path, rs);
840 }
841
842 void phy_store_tx_power_by_rate(void *adapter, u32 band, u32 rfpath, u32 txnum,
843                                 u32 regaddr, u32 bitmask, u32 data)
844 {
845         struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
846
847         rtlpriv->cfg->ops->store_tx_power_by_rate(
848                 rtlpriv->hw, band, rfpath, txnum, regaddr, bitmask, data);
849 }
850
851 void phy_set_tx_power_limit(void *dm, u8 *regulation, u8 *band, u8 *bandwidth,
852                             u8 *rate_section, u8 *rf_path, u8 *channel,
853                             u8 *power_limit)
854 {
855         struct rtl_priv *rtlpriv =
856                 (struct rtl_priv *)((struct phy_dm_struct *)dm)->adapter;
857
858         rtlpriv->cfg->ops->phy_set_txpower_limit(rtlpriv->hw, regulation, band,
859                                                  bandwidth, rate_section,
860                                                  rf_path, channel, power_limit);
861 }
862
863 void rtl_hal_update_ra_mask(void *adapter, struct rtl_sta_info *psta,
864                             u8 rssi_level)
865 {
866         struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
867         struct ieee80211_sta *sta =
868                 container_of((void *)psta, struct ieee80211_sta, drv_priv);
869
870         rtlpriv->cfg->ops->update_rate_tbl(rtlpriv->hw, sta, rssi_level, false);
871 }
872
873 MODULE_AUTHOR("Realtek WlanFAE  <wlanfae@realtek.com>");
874 MODULE_AUTHOR("Larry Finger     <Larry.FInger@lwfinger.net>");
875 MODULE_LICENSE("GPL");
876 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");