linux/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c
<<
>>
Prefs
   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#include "phy.h"
  10
  11static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
  12{
  13        struct adapter *adapter = dm_odm->Adapter;
  14        u32 value32;
  15
  16        if (*dm_odm->mp_mode == 1) {
  17                dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
  18                phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
  19                phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  20                return;
  21        }
  22
  23        /* MAC Setting */
  24        value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
  25        phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
  26                       value32 | (BIT(23) | BIT(25)));
  27        /* Pin Settings */
  28        phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
  29        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
  30        phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
  31        phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  32        /* OFDM Settings */
  33        phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
  34                       0x000000a0);
  35        /* CCK Settings */
  36        phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
  37        phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
  38        rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
  39        phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
  40}
  41
  42static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
  43{
  44        struct adapter *adapter = dm_odm->Adapter;
  45        u32     value32;
  46
  47        if (*dm_odm->mp_mode == 1) {
  48                dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
  49                phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
  50                phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  51                               BIT(5) | BIT(4) | BIT(3), 0);
  52                return;
  53        }
  54
  55        /* MAC Setting */
  56        value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
  57        phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
  58                       value32 | (BIT(23) | BIT(25)));
  59        /* Pin Settings */
  60        phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
  61        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
  62        phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
  63        phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  64        /* OFDM Settings */
  65        phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
  66                       0x000000a0);
  67        /* CCK Settings */
  68        phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
  69        phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
  70        /* Tx Settings */
  71        phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
  72        rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
  73
  74        /* antenna mapping table */
  75        if (!dm_odm->bIsMPChip) { /* testchip */
  76                phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
  77                               BIT(10) | BIT(9) | BIT(8), 1);
  78                phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
  79                               BIT(13) | BIT(12) | BIT(11), 2);
  80        } else { /* MPchip */
  81                phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
  82                               0x0201);
  83        }
  84}
  85
  86static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
  87{
  88        struct adapter *adapter = dm_odm->Adapter;
  89        u32 value32, i;
  90        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  91
  92        if (*dm_odm->mp_mode == 1)
  93                return;
  94
  95        for (i = 0; i < 6; i++) {
  96                dm_fat_tbl->Bssid[i] = 0;
  97                dm_fat_tbl->antSumRSSI[i] = 0;
  98                dm_fat_tbl->antRSSIcnt[i] = 0;
  99                dm_fat_tbl->antAveRSSI[i] = 0;
 100        }
 101        dm_fat_tbl->TrainIdx = 0;
 102        dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
 103
 104        /* MAC Setting */
 105        value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
 106        phy_set_bb_reg(adapter, 0x4c, bMaskDWord,
 107                       value32 | (BIT(23) | BIT(25)));
 108        value32 = phy_query_bb_reg(adapter,  0x7B4, bMaskDWord);
 109        phy_set_bb_reg(adapter, 0x7b4, bMaskDWord,
 110                       value32 | (BIT(16) | BIT(17)));
 111
 112        /* Match MAC ADDR */
 113        phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
 114        phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
 115
 116        phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
 117        phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
 118        phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
 119        phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
 120        phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
 121
 122        /* antenna mapping table */
 123        if (!dm_odm->bIsMPChip) { /* testchip */
 124                phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
 125                phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
 126        } else { /* MPchip */
 127                phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
 128                phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
 129        }
 130
 131        /* Default Ant Setting when no fast training */
 132        phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
 133        phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
 134        phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
 135
 136        /* Enter Traing state */
 137        phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), 1);
 138        phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
 139}
 140
 141void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
 142{
 143        if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
 144                dm_rx_hw_antena_div_init(dm_odm);
 145        else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
 146                dm_trx_hw_antenna_div_init(dm_odm);
 147        else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
 148                dm_fast_training_init(dm_odm);
 149}
 150
 151void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
 152{
 153        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 154        struct adapter *adapter = dm_odm->Adapter;
 155        u32 default_ant, optional_ant;
 156
 157        if (dm_fat_tbl->RxIdleAnt != ant) {
 158                if (ant == MAIN_ANT) {
 159                        default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
 160                                       MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
 161                        optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
 162                                        AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
 163                } else {
 164                        default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
 165                                       AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
 166                        optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
 167                                        MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
 168                }
 169
 170                if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
 171                        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
 172                                       BIT(5) | BIT(4) | BIT(3), default_ant);
 173                        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
 174                                       BIT(8) | BIT(7) | BIT(6), optional_ant);
 175                        phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
 176                                       BIT(14) | BIT(13) | BIT(12), default_ant);
 177                        phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
 178                                       BIT(6) | BIT(7), default_ant);
 179                } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
 180                        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
 181                                       BIT(5) | BIT(4) | BIT(3), default_ant);
 182                        phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
 183                                       BIT(8) | BIT(7) | BIT(6), optional_ant);
 184                }
 185        }
 186        dm_fat_tbl->RxIdleAnt = ant;
 187}
 188
 189static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
 190{
 191        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 192        u8 target_ant;
 193
 194        if (ant == MAIN_ANT)
 195                target_ant = MAIN_ANT_CG_TRX;
 196        else
 197                target_ant = AUX_ANT_CG_TRX;
 198        dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
 199        dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
 200        dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
 201}
 202
 203void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
 204                                      u8 *desc, u8 mac_id)
 205{
 206        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 207
 208        if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
 209            (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
 210                SET_TX_DESC_ANTSEL_A_88E(desc, dm_fat_tbl->antsel_a[mac_id]);
 211                SET_TX_DESC_ANTSEL_B_88E(desc, dm_fat_tbl->antsel_b[mac_id]);
 212                SET_TX_DESC_ANTSEL_C_88E(desc, dm_fat_tbl->antsel_c[mac_id]);
 213        }
 214}
 215
 216void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm,
 217                                   u8 antsel_tr_mux, u32 mac_id, u8 rx_pwdb_all)
 218{
 219        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 220
 221        if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
 222                if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
 223                        dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
 224                        dm_fat_tbl->MainAnt_Cnt[mac_id]++;
 225                } else {
 226                        dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
 227                        dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
 228                }
 229        } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
 230                if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
 231                        dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
 232                        dm_fat_tbl->MainAnt_Cnt[mac_id]++;
 233                } else {
 234                        dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
 235                        dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
 236                }
 237        }
 238}
 239
 240static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
 241{
 242        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 243        struct rtw_dig *dig_table = &dm_odm->DM_DigTable;
 244        struct sta_info *entry;
 245        u32 i, min_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0;
 246        u32 local_min_rssi, local_max_rssi;
 247        u32 main_rssi, aux_rssi;
 248        u8 RxIdleAnt = 0, target_ant = 7;
 249
 250        for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
 251                entry = dm_odm->pODM_StaInfo[i];
 252                if (IS_STA_VALID(entry)) {
 253                        /* 2 Calculate RSSI per Antenna */
 254                        main_rssi = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ?
 255                                     (dm_fat_tbl->MainAnt_Sum[i] /
 256                                      dm_fat_tbl->MainAnt_Cnt[i]) : 0;
 257                        aux_rssi = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ?
 258                                    (dm_fat_tbl->AuxAnt_Sum[i] /
 259                                     dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
 260                        target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
 261                        /* 2 Select max_rssi for DIG */
 262                        local_max_rssi = max(main_rssi, aux_rssi);
 263                        if ((local_max_rssi > ant_div_max_rssi) &&
 264                            (local_max_rssi < 40))
 265                                ant_div_max_rssi = local_max_rssi;
 266                        if (local_max_rssi > max_rssi)
 267                                max_rssi = local_max_rssi;
 268
 269                        /* 2 Select RX Idle Antenna */
 270                        if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
 271                            (main_rssi == 0))
 272                                main_rssi = aux_rssi;
 273                        else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
 274                                 (aux_rssi == 0))
 275                                aux_rssi = main_rssi;
 276
 277                        local_min_rssi = min(main_rssi, aux_rssi);
 278                        if (local_min_rssi < min_rssi) {
 279                                min_rssi = local_min_rssi;
 280                                RxIdleAnt = target_ant;
 281                        }
 282                        /* 2 Select TRX Antenna */
 283                        if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
 284                                update_tx_ant_88eu(dm_odm, target_ant, i);
 285                }
 286                dm_fat_tbl->MainAnt_Sum[i] = 0;
 287                dm_fat_tbl->AuxAnt_Sum[i] = 0;
 288                dm_fat_tbl->MainAnt_Cnt[i] = 0;
 289                dm_fat_tbl->AuxAnt_Cnt[i] = 0;
 290        }
 291
 292        /* 2 Set RX Idle Antenna */
 293        rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
 294
 295        dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
 296        dig_table->RSSI_max = max_rssi;
 297}
 298
 299void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
 300{
 301        struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
 302        struct adapter *adapter = dm_odm->Adapter;
 303
 304        if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
 305                return;
 306        if (!dm_odm->bLinked) {
 307                ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
 308                             ("ODM_AntennaDiversity_88E(): No Link.\n"));
 309                if (dm_fat_tbl->bBecomeLinked) {
 310                        ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
 311                                     ("Need to Turn off HW AntDiv\n"));
 312                        phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
 313                        phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
 314                                       BIT(15), 0);
 315                        if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
 316                                phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
 317                                               BIT(21), 0);
 318                        dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
 319                }
 320                return;
 321        } else {
 322                if (!dm_fat_tbl->bBecomeLinked) {
 323                        ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
 324                                     ("Need to Turn on HW AntDiv\n"));
 325                        phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
 326                        phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
 327                                       BIT(15), 1);
 328                        if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
 329                                phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
 330                                               BIT(21), 1);
 331                        dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
 332                }
 333        }
 334        if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
 335            (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
 336                rtl88eu_dm_hw_ant_div(dm_odm);
 337}
 338