root/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dm_rx_hw_antena_div_init
  2. dm_trx_hw_antenna_div_init
  3. dm_fast_training_init
  4. rtl88eu_dm_antenna_div_init
  5. rtl88eu_dm_update_rx_idle_ant
  6. update_tx_ant_88eu
  7. rtl88eu_dm_set_tx_ant_by_tx_info
  8. rtl88eu_dm_ant_sel_statistics
  9. rtl88eu_dm_hw_ant_div
  10. rtl88eu_dm_antenna_diversity

   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 
  11 static 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 
  42 static 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 
  86 static 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 
 141 void 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 
 151 void 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 
 189 static 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 
 203 void 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 
 216 void 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 
 240 static 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 
 299 void 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 }

/* [<][>][^][v][top][bottom][index][help] */