linux/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  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
  26#include "../wifi.h"
  27#include "../base.h"
  28#include "../pci.h"
  29#include "../core.h"
  30#include "reg.h"
  31#include "def.h"
  32#include "phy.h"
  33#include "dm.h"
  34#include "../rtl8723com/dm_common.h"
  35#include "fw.h"
  36#include "hal_btc.h"
  37
  38static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
  39        0x7f8001fe,
  40        0x788001e2,
  41        0x71c001c7,
  42        0x6b8001ae,
  43        0x65400195,
  44        0x5fc0017f,
  45        0x5a400169,
  46        0x55400155,
  47        0x50800142,
  48        0x4c000130,
  49        0x47c0011f,
  50        0x43c0010f,
  51        0x40000100,
  52        0x3c8000f2,
  53        0x390000e4,
  54        0x35c000d7,
  55        0x32c000cb,
  56        0x300000c0,
  57        0x2d4000b5,
  58        0x2ac000ab,
  59        0x288000a2,
  60        0x26000098,
  61        0x24000090,
  62        0x22000088,
  63        0x20000080,
  64        0x1e400079,
  65        0x1c800072,
  66        0x1b00006c,
  67        0x19800066,
  68        0x18000060,
  69        0x16c0005b,
  70        0x15800056,
  71        0x14400051,
  72        0x1300004c,
  73        0x12000048,
  74        0x11000044,
  75        0x10000040,
  76};
  77
  78static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
  79        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
  80        {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
  81        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
  82        {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
  83        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
  84        {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
  85        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
  86        {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
  87        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
  88        {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
  89        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
  90        {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
  91        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
  92        {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
  93        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
  94        {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
  95        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
  96        {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
  97        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
  98        {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
  99        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
 100        {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
 101        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
 102        {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
 103        {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
 104        {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
 105        {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
 106        {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
 107        {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
 108        {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
 109        {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
 110        {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
 111        {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
 112};
 113
 114static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 115        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
 116        {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
 117        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
 118        {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
 119        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
 120        {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
 121        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
 122        {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
 123        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
 124        {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
 125        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
 126        {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
 127        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
 128        {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
 129        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
 130        {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
 131        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
 132        {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
 133        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
 134        {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
 135        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
 136        {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
 137        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
 138        {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
 139        {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
 140        {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
 141        {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
 142        {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
 143        {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
 144        {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
 145        {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
 146        {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
 147        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
 148};
 149
 150static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 151{
 152        struct rtl_priv *rtlpriv = rtl_priv(hw);
 153        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 154        long rssi_val_min = 0;
 155
 156        if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
 157            (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
 158                if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
 159                        rssi_val_min =
 160                            (rtlpriv->dm.entry_min_undec_sm_pwdb >
 161                             rtlpriv->dm.undec_sm_pwdb) ?
 162                            rtlpriv->dm.undec_sm_pwdb :
 163                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 164                else
 165                        rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 166        } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
 167                   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
 168                rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 169        } else if (dm_digtable->curmultista_cstate ==
 170                DIG_MULTISTA_CONNECT) {
 171                rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
 172        }
 173
 174        return (u8) rssi_val_min;
 175}
 176
 177static void rtl8723e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 178{
 179        u32 ret_value;
 180        struct rtl_priv *rtlpriv = rtl_priv(hw);
 181        struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
 182
 183        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
 184        falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
 185
 186        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
 187        falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
 188        falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
 189
 190        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
 191        falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
 192        falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
 193            falsealm_cnt->cnt_rate_illegal +
 194            falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
 195
 196        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
 197        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
 198        falsealm_cnt->cnt_cck_fail = ret_value;
 199
 200        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
 201        falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
 202        falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
 203                                 falsealm_cnt->cnt_rate_illegal +
 204                                 falsealm_cnt->cnt_crc8_fail +
 205                                 falsealm_cnt->cnt_mcs_fail +
 206                                 falsealm_cnt->cnt_cck_fail);
 207
 208        rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
 209        rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
 210        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
 211        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
 212
 213        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 214                 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
 215                 falsealm_cnt->cnt_parity_fail,
 216                 falsealm_cnt->cnt_rate_illegal,
 217                 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
 218
 219        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 220                 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
 221                 falsealm_cnt->cnt_ofdm_fail,
 222                 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
 223}
 224
 225static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
 226{
 227        struct rtl_priv *rtlpriv = rtl_priv(hw);
 228        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 229        u8 value_igi = dm_digtable->cur_igvalue;
 230
 231        if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 232                value_igi--;
 233        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
 234                value_igi += 0;
 235        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
 236                value_igi++;
 237        else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
 238                value_igi += 2;
 239        if (value_igi > DM_DIG_FA_UPPER)
 240                value_igi = DM_DIG_FA_UPPER;
 241        else if (value_igi < DM_DIG_FA_LOWER)
 242                value_igi = DM_DIG_FA_LOWER;
 243        if (rtlpriv->falsealm_cnt.cnt_all > 10000)
 244                value_igi = 0x32;
 245
 246        dm_digtable->cur_igvalue = value_igi;
 247        rtl8723e_dm_write_dig(hw);
 248}
 249
 250static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 251{
 252        struct rtl_priv *rtlpriv = rtl_priv(hw);
 253        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 254
 255        if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) {
 256                if ((dm_digtable->back_val - 2) <
 257                    dm_digtable->back_range_min)
 258                        dm_digtable->back_val =
 259                            dm_digtable->back_range_min;
 260                else
 261                        dm_digtable->back_val -= 2;
 262        } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) {
 263                if ((dm_digtable->back_val + 2) >
 264                    dm_digtable->back_range_max)
 265                        dm_digtable->back_val =
 266                            dm_digtable->back_range_max;
 267                else
 268                        dm_digtable->back_val += 2;
 269        }
 270
 271        if ((dm_digtable->rssi_val_min + 10 - dm_digtable->back_val) >
 272            dm_digtable->rx_gain_max)
 273                dm_digtable->cur_igvalue = dm_digtable->rx_gain_max;
 274        else if ((dm_digtable->rssi_val_min + 10 -
 275                  dm_digtable->back_val) < dm_digtable->rx_gain_min)
 276                dm_digtable->cur_igvalue = dm_digtable->rx_gain_min;
 277        else
 278                dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 -
 279                    dm_digtable->back_val;
 280
 281        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 282                 "rssi_val_min = %x back_val %x\n",
 283                  dm_digtable->rssi_val_min, dm_digtable->back_val);
 284
 285        rtl8723e_dm_write_dig(hw);
 286}
 287
 288static void rtl8723e_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 289{
 290        static u8 binitialized;
 291        struct rtl_priv *rtlpriv = rtl_priv(hw);
 292        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 293        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 294        long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
 295        bool multi_sta = false;
 296
 297        if (mac->opmode == NL80211_IFTYPE_ADHOC)
 298                multi_sta = true;
 299
 300        if (!multi_sta || (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) {
 301                binitialized = false;
 302                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 303                return;
 304        } else if (!binitialized) {
 305                binitialized = true;
 306                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
 307                dm_digtable->cur_igvalue = 0x20;
 308                rtl8723e_dm_write_dig(hw);
 309        }
 310
 311        if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
 312                if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
 313                    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
 314
 315                        if (dm_digtable->dig_ext_port_stage ==
 316                            DIG_EXT_PORT_STAGE_2) {
 317                                dm_digtable->cur_igvalue = 0x20;
 318                                rtl8723e_dm_write_dig(hw);
 319                        }
 320
 321                        dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
 322                } else if (rssi_strength > dm_digtable->rssi_highthresh) {
 323                        dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
 324                        rtl92c_dm_ctrl_initgain_by_fa(hw);
 325                }
 326        } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
 327                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
 328                dm_digtable->cur_igvalue = 0x20;
 329                rtl8723e_dm_write_dig(hw);
 330        }
 331
 332        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 333                 "curmultista_cstate = %x dig_ext_port_stage %x\n",
 334                 dm_digtable->curmultista_cstate,
 335                 dm_digtable->dig_ext_port_stage);
 336}
 337
 338static void rtl8723e_dm_initial_gain_sta(struct ieee80211_hw *hw)
 339{
 340        struct rtl_priv *rtlpriv = rtl_priv(hw);
 341        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 342
 343        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 344                 "presta_cstate = %x, cursta_cstate = %x\n",
 345                  dm_digtable->presta_cstate,
 346                  dm_digtable->cursta_cstate);
 347
 348        if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
 349            dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
 350            dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 351                if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
 352                        dm_digtable->rssi_val_min =
 353                            rtl8723e_dm_initial_gain_min_pwdb(hw);
 354                        rtl92c_dm_ctrl_initgain_by_rssi(hw);
 355                }
 356        } else {
 357                dm_digtable->rssi_val_min = 0;
 358                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 359                dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 360                dm_digtable->cur_igvalue = 0x20;
 361                dm_digtable->pre_igvalue = 0;
 362                rtl8723e_dm_write_dig(hw);
 363        }
 364}
 365
 366static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 367{
 368        struct rtl_priv *rtlpriv = rtl_priv(hw);
 369        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 370
 371        if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 372                dm_digtable->rssi_val_min = rtl8723e_dm_initial_gain_min_pwdb(hw);
 373
 374                if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
 375                        if (dm_digtable->rssi_val_min <= 25)
 376                                dm_digtable->cur_cck_pd_state =
 377                                    CCK_PD_STAGE_LOWRSSI;
 378                        else
 379                                dm_digtable->cur_cck_pd_state =
 380                                    CCK_PD_STAGE_HIGHRSSI;
 381                } else {
 382                        if (dm_digtable->rssi_val_min <= 20)
 383                                dm_digtable->cur_cck_pd_state =
 384                                    CCK_PD_STAGE_LOWRSSI;
 385                        else
 386                                dm_digtable->cur_cck_pd_state =
 387                                    CCK_PD_STAGE_HIGHRSSI;
 388                }
 389        } else {
 390                dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
 391        }
 392
 393        if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
 394                if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
 395                        if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
 396                                dm_digtable->cur_cck_fa_state =
 397                                    CCK_FA_STAGE_HIGH;
 398                        else
 399                                dm_digtable->cur_cck_fa_state =
 400                                    CCK_FA_STAGE_LOW;
 401                        if (dm_digtable->pre_cck_fa_state !=
 402                            dm_digtable->cur_cck_fa_state) {
 403                                if (dm_digtable->cur_cck_fa_state ==
 404                                    CCK_FA_STAGE_LOW)
 405                                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
 406                                                      0x83);
 407                                else
 408                                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
 409                                                      0xcd);
 410
 411                                dm_digtable->pre_cck_fa_state =
 412                                    dm_digtable->cur_cck_fa_state;
 413                        }
 414
 415                        rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
 416
 417                } else {
 418                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
 419                        rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
 420
 421                }
 422                dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
 423        }
 424
 425        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
 426                 "CCKPDStage=%x\n", dm_digtable->cur_cck_pd_state);
 427
 428}
 429
 430static void rtl8723e_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 431{
 432        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 433        struct rtl_priv *rtlpriv = rtl_priv(hw);
 434        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 435
 436        if (mac->act_scanning)
 437                return;
 438
 439        if (mac->link_state >= MAC80211_LINKED)
 440                dm_digtable->cursta_cstate = DIG_STA_CONNECT;
 441        else
 442                dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
 443
 444        rtl8723e_dm_initial_gain_sta(hw);
 445        rtl8723e_dm_initial_gain_multi_sta(hw);
 446        rtl8723e_dm_cck_packet_detection_thresh(hw);
 447
 448        dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
 449
 450}
 451
 452static void rtl8723e_dm_dig(struct ieee80211_hw *hw)
 453{
 454        struct rtl_priv *rtlpriv = rtl_priv(hw);
 455        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 456
 457        if (!rtlpriv->dm.dm_initialgain_enable)
 458                return;
 459        if (!dm_digtable->dig_enable_flag)
 460                return;
 461
 462        rtl8723e_dm_ctrl_initgain_by_twoport(hw);
 463
 464}
 465
 466static void rtl8723e_dm_dynamic_txpower(struct ieee80211_hw *hw)
 467{
 468        struct rtl_priv *rtlpriv = rtl_priv(hw);
 469        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 470        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 471        long undec_sm_pwdb;
 472
 473        if (!rtlpriv->dm.dynamic_txpower_enable)
 474                return;
 475
 476        if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
 477                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 478                return;
 479        }
 480
 481        if ((mac->link_state < MAC80211_LINKED) &&
 482            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 483                RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 484                         "Not connected to any\n");
 485
 486                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 487
 488                rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
 489                return;
 490        }
 491
 492        if (mac->link_state >= MAC80211_LINKED) {
 493                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 494                        undec_sm_pwdb =
 495                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 496                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 497                                 "AP Client PWDB = 0x%lx\n",
 498                                  undec_sm_pwdb);
 499                } else {
 500                        undec_sm_pwdb =
 501                            rtlpriv->dm.undec_sm_pwdb;
 502                        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 503                                 "STA Default Port PWDB = 0x%lx\n",
 504                                  undec_sm_pwdb);
 505                }
 506        } else {
 507                undec_sm_pwdb =
 508                    rtlpriv->dm.entry_min_undec_sm_pwdb;
 509
 510                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 511                         "AP Ext Port PWDB = 0x%lx\n",
 512                          undec_sm_pwdb);
 513        }
 514
 515        if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 516                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 517                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 518                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
 519        } else if ((undec_sm_pwdb <
 520                    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
 521                   (undec_sm_pwdb >=
 522                    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 523                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 524                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 525                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
 526        } else if (undec_sm_pwdb <
 527                   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 528                rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 529                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 530                         "TXHIGHPWRLEVEL_NORMAL\n");
 531        }
 532
 533        if (rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl) {
 534                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 535                         "PHY_SetTxPowerLevel8192S() Channel = %d\n",
 536                          rtlphy->current_channel);
 537                rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel);
 538        }
 539
 540        rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
 541}
 542
 543void rtl8723e_dm_write_dig(struct ieee80211_hw *hw)
 544{
 545        struct rtl_priv *rtlpriv = rtl_priv(hw);
 546        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 547
 548        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 549                 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
 550                  dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
 551                  dm_digtable->back_val);
 552
 553        if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
 554                rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 555                              dm_digtable->cur_igvalue);
 556                rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
 557                              dm_digtable->cur_igvalue);
 558
 559                dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
 560        }
 561}
 562
 563static void rtl8723e_dm_pwdb_monitor(struct ieee80211_hw *hw)
 564{
 565}
 566
 567static void rtl8723e_dm_check_edca_turbo(struct ieee80211_hw *hw)
 568{
 569        struct rtl_priv *rtlpriv = rtl_priv(hw);
 570        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 571
 572        static u64 last_txok_cnt;
 573        static u64 last_rxok_cnt;
 574        static u32 last_bt_edca_ul;
 575        static u32 last_bt_edca_dl;
 576        u64 cur_txok_cnt = 0;
 577        u64 cur_rxok_cnt = 0;
 578        u32 edca_be_ul = 0x5ea42b;
 579        u32 edca_be_dl = 0x5ea42b;
 580        bool bt_change_edca = false;
 581
 582        if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||
 583            (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {
 584                rtlpriv->dm.current_turbo_edca = false;
 585                last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;
 586                last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;
 587        }
 588
 589        if (rtlpriv->btcoexist.bt_edca_ul != 0) {
 590                edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;
 591                bt_change_edca = true;
 592        }
 593
 594        if (rtlpriv->btcoexist.bt_edca_dl != 0) {
 595                edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
 596                bt_change_edca = true;
 597        }
 598
 599        if (mac->link_state != MAC80211_LINKED) {
 600                rtlpriv->dm.current_turbo_edca = false;
 601                return;
 602        }
 603        if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
 604             (!rtlpriv->dm.disable_framebursting))) {
 605
 606                cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
 607                cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
 608
 609                if (cur_rxok_cnt > 4 * cur_txok_cnt) {
 610                        if (!rtlpriv->dm.is_cur_rdlstate ||
 611                            !rtlpriv->dm.current_turbo_edca) {
 612                                rtl_write_dword(rtlpriv,
 613                                                REG_EDCA_BE_PARAM,
 614                                                edca_be_dl);
 615                                rtlpriv->dm.is_cur_rdlstate = true;
 616                        }
 617                } else {
 618                        if (rtlpriv->dm.is_cur_rdlstate ||
 619                            !rtlpriv->dm.current_turbo_edca) {
 620                                rtl_write_dword(rtlpriv,
 621                                                REG_EDCA_BE_PARAM,
 622                                                edca_be_ul);
 623                                rtlpriv->dm.is_cur_rdlstate = false;
 624                        }
 625                }
 626                rtlpriv->dm.current_turbo_edca = true;
 627        } else {
 628                if (rtlpriv->dm.current_turbo_edca) {
 629                        u8 tmp = AC0_BE;
 630                        rtlpriv->cfg->ops->set_hw_reg(hw,
 631                                                      HW_VAR_AC_PARAM,
 632                                                      (u8 *)(&tmp));
 633                        rtlpriv->dm.current_turbo_edca = false;
 634                }
 635        }
 636
 637        rtlpriv->dm.is_any_nonbepkts = false;
 638        last_txok_cnt = rtlpriv->stats.txbytesunicast;
 639        last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
 640}
 641
 642static void rtl8723e_dm_initialize_txpower_tracking_thermalmeter(
 643                                struct ieee80211_hw *hw)
 644{
 645        struct rtl_priv *rtlpriv = rtl_priv(hw);
 646
 647        rtlpriv->dm.txpower_tracking = true;
 648        rtlpriv->dm.txpower_trackinginit = false;
 649
 650        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 651                 "pMgntInfo->txpower_tracking = %d\n",
 652                  rtlpriv->dm.txpower_tracking);
 653}
 654
 655static void rtl8723e_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
 656{
 657        rtl8723e_dm_initialize_txpower_tracking_thermalmeter(hw);
 658}
 659
 660void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 661{
 662        return;
 663}
 664
 665void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 666{
 667        struct rtl_priv *rtlpriv = rtl_priv(hw);
 668        struct rate_adaptive *p_ra = &(rtlpriv->ra);
 669
 670        p_ra->ratr_state = DM_RATR_STA_INIT;
 671        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 672
 673        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 674                rtlpriv->dm.useramask = true;
 675        else
 676                rtlpriv->dm.useramask = false;
 677
 678}
 679
 680void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
 681{
 682        struct rtl_priv *rtlpriv = rtl_priv(hw);
 683        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
 684        static u8 initialize;
 685        static u32 reg_874, reg_c70, reg_85c, reg_a74;
 686
 687        if (initialize == 0) {
 688                reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 689                                         MASKDWORD) & 0x1CC000) >> 14;
 690
 691                reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
 692                                         MASKDWORD) & BIT(3)) >> 3;
 693
 694                reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
 695                                         MASKDWORD) & 0xFF000000) >> 24;
 696
 697                reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
 698
 699                initialize = 1;
 700        }
 701
 702        if (!bforce_in_normal) {
 703                if (dm_pstable->rssi_val_min != 0) {
 704                        if (dm_pstable->pre_rfstate == RF_NORMAL) {
 705                                if (dm_pstable->rssi_val_min >= 30)
 706                                        dm_pstable->cur_rfstate = RF_SAVE;
 707                                else
 708                                        dm_pstable->cur_rfstate = RF_NORMAL;
 709                        } else {
 710                                if (dm_pstable->rssi_val_min <= 25)
 711                                        dm_pstable->cur_rfstate = RF_NORMAL;
 712                                else
 713                                        dm_pstable->cur_rfstate = RF_SAVE;
 714                        }
 715                } else {
 716                        dm_pstable->cur_rfstate = RF_MAX;
 717                }
 718        } else {
 719                dm_pstable->cur_rfstate = RF_NORMAL;
 720        }
 721
 722        if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
 723                if (dm_pstable->cur_rfstate == RF_SAVE) {
 724                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 725                                      BIT(5), 0x1);
 726                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 727                                      0x1C0000, 0x2);
 728                        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
 729                        rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
 730                                      0xFF000000, 0x63);
 731                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 732                                      0xC000, 0x2);
 733                        rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
 734                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
 735                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
 736                } else {
 737                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 738                                      0x1CC000, reg_874);
 739                        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
 740                                      reg_c70);
 741                        rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
 742                                      reg_85c);
 743                        rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
 744                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
 745                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
 746                                      BIT(5), 0x0);
 747                }
 748
 749                dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
 750        }
 751}
 752
 753static void rtl8723e_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
 754{
 755        struct rtl_priv *rtlpriv = rtl_priv(hw);
 756        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 757        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
 758
 759        if (((mac->link_state == MAC80211_NOLINK)) &&
 760            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 761                dm_pstable->rssi_val_min = 0;
 762                RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 763                         "Not connected to any\n");
 764        }
 765
 766        if (mac->link_state == MAC80211_LINKED) {
 767                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 768                        dm_pstable->rssi_val_min =
 769                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 770                        RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 771                                 "AP Client PWDB = 0x%lx\n",
 772                                  dm_pstable->rssi_val_min);
 773                } else {
 774                        dm_pstable->rssi_val_min =
 775                            rtlpriv->dm.undec_sm_pwdb;
 776                        RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 777                                 "STA Default Port PWDB = 0x%lx\n",
 778                                  dm_pstable->rssi_val_min);
 779                }
 780        } else {
 781                dm_pstable->rssi_val_min =
 782                    rtlpriv->dm.entry_min_undec_sm_pwdb;
 783
 784                RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 785                         "AP Ext Port PWDB = 0x%lx\n",
 786                          dm_pstable->rssi_val_min);
 787        }
 788
 789        rtl8723e_dm_rf_saving(hw, false);
 790}
 791
 792void rtl8723e_dm_init(struct ieee80211_hw *hw)
 793{
 794        struct rtl_priv *rtlpriv = rtl_priv(hw);
 795
 796        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 797        rtl_dm_diginit(hw, 0x20);
 798        rtl8723_dm_init_dynamic_txpower(hw);
 799        rtl8723_dm_init_edca_turbo(hw);
 800        rtl8723e_dm_init_rate_adaptive_mask(hw);
 801        rtl8723e_dm_initialize_txpower_tracking(hw);
 802        rtl8723_dm_init_dynamic_bb_powersaving(hw);
 803}
 804
 805void rtl8723e_dm_watchdog(struct ieee80211_hw *hw)
 806{
 807        struct rtl_priv *rtlpriv = rtl_priv(hw);
 808        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 809        bool fw_current_inpsmode = false;
 810        bool fw_ps_awake = true;
 811        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
 812                                      (u8 *)(&fw_current_inpsmode));
 813        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
 814                                      (u8 *)(&fw_ps_awake));
 815
 816        if (ppsc->p2p_ps_info.p2p_ps_mode)
 817                fw_ps_awake = false;
 818
 819        spin_lock(&rtlpriv->locks.rf_ps_lock);
 820        if ((ppsc->rfpwr_state == ERFON) &&
 821            ((!fw_current_inpsmode) && fw_ps_awake) &&
 822            (!ppsc->rfchange_inprogress)) {
 823                rtl8723e_dm_pwdb_monitor(hw);
 824                rtl8723e_dm_dig(hw);
 825                rtl8723e_dm_false_alarm_counter_statistics(hw);
 826                rtl8723e_dm_dynamic_bb_powersaving(hw);
 827                rtl8723e_dm_dynamic_txpower(hw);
 828                rtl8723e_dm_check_txpower_tracking(hw);
 829                /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
 830                rtl8723e_dm_bt_coexist(hw);
 831                rtl8723e_dm_check_edca_turbo(hw);
 832        }
 833        spin_unlock(&rtlpriv->locks.rf_ps_lock);
 834        if (rtlpriv->btcoexist.init_set)
 835                rtl_write_byte(rtlpriv, 0x76e, 0xc);
 836}
 837
 838static void rtl8723e_dm_init_bt_coexist(struct ieee80211_hw *hw)
 839{
 840        struct rtl_priv *rtlpriv = rtl_priv(hw);
 841
 842        rtlpriv->btcoexist.bt_rfreg_origin_1e
 843                = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff);
 844        rtlpriv->btcoexist.bt_rfreg_origin_1f
 845                = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0);
 846
 847        rtlpriv->btcoexist.cstate = 0;
 848        rtlpriv->btcoexist.previous_state = 0;
 849        rtlpriv->btcoexist.cstate_h = 0;
 850        rtlpriv->btcoexist.previous_state_h = 0;
 851        rtlpriv->btcoexist.lps_counter = 0;
 852
 853        /*  Enable counter statistics */
 854        rtl_write_byte(rtlpriv, 0x76e, 0x4);
 855        rtl_write_byte(rtlpriv, 0x778, 0x3);
 856        rtl_write_byte(rtlpriv, 0x40, 0x20);
 857
 858        rtlpriv->btcoexist.init_set = true;
 859}
 860
 861void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw)
 862{
 863        struct rtl_priv *rtlpriv = rtl_priv(hw);
 864        u8 tmp_byte = 0;
 865        if (!rtlpriv->btcoexist.bt_coexistence) {
 866                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
 867                         "[DM]{BT], BT not exist!!\n");
 868                return;
 869        }
 870
 871        if (!rtlpriv->btcoexist.init_set) {
 872                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
 873                         "[DM][BT], rtl8723e_dm_bt_coexist()\n");
 874                rtl8723e_dm_init_bt_coexist(hw);
 875        }
 876
 877        tmp_byte = rtl_read_byte(rtlpriv, 0x40);
 878        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
 879                 "[DM][BT], 0x40 is 0x%x\n", tmp_byte);
 880        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
 881                 "[DM][BT], bt_dm_coexist start\n");
 882        rtl8723e_dm_bt_coexist_8723(hw);
 883}
 884