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