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