linux/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2010  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 "fw.h"
  35#include "trx.h"
  36#include "../btcoexist/rtl_btc.h"
  37
  38static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = {
  39        0x081, /* 0, -12.0dB */
  40        0x088, /* 1, -11.5dB */
  41        0x090, /* 2, -11.0dB */
  42        0x099, /* 3, -10.5dB */
  43        0x0A2, /* 4, -10.0dB */
  44        0x0AC, /* 5, -9.5dB */
  45        0x0B6, /* 6, -9.0dB */
  46        0x0C0, /* 7, -8.5dB */
  47        0x0CC, /* 8, -8.0dB */
  48        0x0D8, /* 9, -7.5dB */
  49        0x0E5, /* 10, -7.0dB */
  50        0x0F2, /* 11, -6.5dB */
  51        0x101, /* 12, -6.0dB */
  52        0x110, /* 13, -5.5dB */
  53        0x120, /* 14, -5.0dB */
  54        0x131, /* 15, -4.5dB */
  55        0x143, /* 16, -4.0dB */
  56        0x156, /* 17, -3.5dB */
  57        0x16A, /* 18, -3.0dB */
  58        0x180, /* 19, -2.5dB */
  59        0x197, /* 20, -2.0dB */
  60        0x1AF, /* 21, -1.5dB */
  61        0x1C8, /* 22, -1.0dB */
  62        0x1E3, /* 23, -0.5dB */
  63        0x200, /* 24, +0  dB */
  64        0x21E, /* 25, +0.5dB */
  65        0x23E, /* 26, +1.0dB */
  66        0x261, /* 27, +1.5dB */
  67        0x285, /* 28, +2.0dB */
  68        0x2AB, /* 29, +2.5dB */
  69        0x2D3, /* 30, +3.0dB */
  70        0x2FE, /* 31, +3.5dB */
  71        0x32B, /* 32, +4.0dB */
  72        0x35C, /* 33, +4.5dB */
  73        0x38E, /* 34, +5.0dB */
  74        0x3C4, /* 35, +5.5dB */
  75        0x3FE  /* 36, +6.0dB */
  76};
  77
  78static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = {
  79        0x081, /* 0, -12.0dB */
  80        0x088, /* 1, -11.5dB */
  81        0x090, /* 2, -11.0dB */
  82        0x099, /* 3, -10.5dB */
  83        0x0A2, /* 4, -10.0dB */
  84        0x0AC, /* 5, -9.5dB */
  85        0x0B6, /* 6, -9.0dB */
  86        0x0C0, /* 7, -8.5dB */
  87        0x0CC, /* 8, -8.0dB */
  88        0x0D8, /* 9, -7.5dB */
  89        0x0E5, /* 10, -7.0dB */
  90        0x0F2, /* 11, -6.5dB */
  91        0x101, /* 12, -6.0dB */
  92        0x110, /* 13, -5.5dB */
  93        0x120, /* 14, -5.0dB */
  94        0x131, /* 15, -4.5dB */
  95        0x143, /* 16, -4.0dB */
  96        0x156, /* 17, -3.5dB */
  97        0x16A, /* 18, -3.0dB */
  98        0x180, /* 19, -2.5dB */
  99        0x197, /* 20, -2.0dB */
 100        0x1AF, /* 21, -1.5dB */
 101        0x1C8, /* 22, -1.0dB */
 102        0x1E3, /* 23, -0.5dB */
 103        0x200, /* 24, +0  dB */
 104        0x21E, /* 25, +0.5dB */
 105        0x23E, /* 26, +1.0dB */
 106        0x261, /* 27, +1.5dB */
 107        0x285, /* 28, +2.0dB */
 108        0x2AB, /* 29, +2.5dB */
 109        0x2D3, /* 30, +3.0dB */
 110        0x2FE, /* 31, +3.5dB */
 111        0x32B, /* 32, +4.0dB */
 112        0x35C, /* 33, +4.5dB */
 113        0x38E, /* 34, +5.0dB */
 114        0x3C4, /* 35, +5.5dB */
 115        0x3FE  /* 36, +6.0dB */
 116};
 117
 118static const u32 ofdmswing_table[] = {
 119        0x0b40002d, /* 0, -15.0dB */
 120        0x0c000030, /* 1, -14.5dB */
 121        0x0cc00033, /* 2, -14.0dB */
 122        0x0d800036, /* 3, -13.5dB */
 123        0x0e400039, /* 4, -13.0dB */
 124        0x0f00003c, /* 5, -12.5dB */
 125        0x10000040, /* 6, -12.0dB */
 126        0x11000044, /* 7, -11.5dB */
 127        0x12000048, /* 8, -11.0dB */
 128        0x1300004c, /* 9, -10.5dB */
 129        0x14400051, /* 10, -10.0dB */
 130        0x15800056, /* 11, -9.5dB */
 131        0x16c0005b, /* 12, -9.0dB */
 132        0x18000060, /* 13, -8.5dB */
 133        0x19800066, /* 14, -8.0dB */
 134        0x1b00006c, /* 15, -7.5dB */
 135        0x1c800072, /* 16, -7.0dB */
 136        0x1e400079, /* 17, -6.5dB */
 137        0x20000080, /* 18, -6.0dB */
 138        0x22000088, /* 19, -5.5dB */
 139        0x24000090, /* 20, -5.0dB */
 140        0x26000098, /* 21, -4.5dB */
 141        0x288000a2, /* 22, -4.0dB */
 142        0x2ac000ab, /* 23, -3.5dB */
 143        0x2d4000b5, /* 24, -3.0dB */
 144        0x300000c0, /* 25, -2.5dB */
 145        0x32c000cb, /* 26, -2.0dB */
 146        0x35c000d7, /* 27, -1.5dB */
 147        0x390000e4, /* 28, -1.0dB */
 148        0x3c8000f2, /* 29, -0.5dB */
 149        0x40000100, /* 30, +0dB */
 150        0x43c0010f, /* 31, +0.5dB */
 151        0x47c0011f, /* 32, +1.0dB */
 152        0x4c000130, /* 33, +1.5dB */
 153        0x50800142, /* 34, +2.0dB */
 154        0x55400155, /* 35, +2.5dB */
 155        0x5a400169, /* 36, +3.0dB */
 156        0x5fc0017f, /* 37, +3.5dB */
 157        0x65400195, /* 38, +4.0dB */
 158        0x6b8001ae, /* 39, +4.5dB */
 159        0x71c001c7, /* 40, +5.0dB */
 160        0x788001e2, /* 41, +5.5dB */
 161        0x7f8001fe  /* 42, +6.0dB */
 162};
 163
 164static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
 165        {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */
 166        {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */
 167        {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */
 168        {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */
 169        {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */
 170        {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */
 171        {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */
 172        {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */
 173        {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */
 174        {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */
 175        {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
 176        {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
 177        {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
 178        {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
 179        {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
 180        {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
 181        {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
 182        {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
 183        {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
 184        {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
 185        {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
 186        {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
 187        {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
 188        {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
 189        {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
 190        {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
 191        {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
 192        {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
 193        {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
 194        {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
 195        {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
 196        {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
 197        {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */
 198};
 199
 200static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
 201        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */
 202        {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */
 203        {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */
 204        {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */
 205        {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */
 206        {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */
 207        {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */
 208        {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */
 209        {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */
 210        {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */
 211        {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
 212        {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
 213        {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
 214        {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
 215        {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
 216        {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
 217        {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
 218        {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
 219        {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
 220        {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
 221        {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
 222        {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
 223        {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
 224        {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
 225        {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
 226        {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
 227        {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
 228        {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
 229        {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
 230        {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
 231        {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
 232        {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
 233        {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */
 234};
 235
 236static const u32 edca_setting_dl[PEER_MAX] = {
 237        0xa44f,         /* 0 UNKNOWN */
 238        0x5ea44f,       /* 1 REALTEK_90 */
 239        0x5e4322,       /* 2 REALTEK_92SE */
 240        0x5ea42b,               /* 3 BROAD      */
 241        0xa44f,         /* 4 RAL */
 242        0xa630,         /* 5 ATH */
 243        0x5ea630,               /* 6 CISCO */
 244        0x5ea42b,               /* 7 MARVELL */
 245};
 246
 247static const u32 edca_setting_ul[PEER_MAX] = {
 248        0x5e4322,       /* 0 UNKNOWN */
 249        0xa44f,         /* 1 REALTEK_90 */
 250        0x5ea44f,       /* 2 REALTEK_92SE */
 251        0x5ea32b,       /* 3 BROAD */
 252        0x5ea422,       /* 4 RAL */
 253        0x5ea322,       /* 5 ATH */
 254        0x3ea430,       /* 6 CISCO */
 255        0x5ea44f,       /* 7 MARV */
 256};
 257
 258static u8 rtl8818e_delta_swing_table_idx_24gb_p[] = {
 259        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4,
 260        4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9};
 261
 262static u8 rtl8818e_delta_swing_table_idx_24gb_n[] = {
 263        0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,
 264        7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11};
 265
 266static u8 rtl8812ae_delta_swing_table_idx_24gb_n[]  = {
 267        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 268        6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 269
 270static u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = {
 271        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 272        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 273
 274static u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = {
 275        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 276        6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 277
 278static u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = {
 279        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 280        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 281
 282static u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = {
 283        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 284        6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 285
 286static u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = {
 287        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 288        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 289
 290static u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = {
 291        0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 292        6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 293
 294static u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = {
 295        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 296        6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 297
 298static u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = {
 299        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7,
 300        7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13},
 301        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
 302        7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13},
 303        {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11,
 304        12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18},
 305};
 306
 307static u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = {
 308        {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8,
 309        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 310        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 311        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 312        {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9,
 313        9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 314};
 315
 316static u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 317        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 318        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13},
 319        {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9,
 320        9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13},
 321        {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11,
 322        12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18},
 323};
 324
 325static u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 326        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8,
 327        8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 328        {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 329        9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 330        {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9,
 331        10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 332};
 333
 334static u8 rtl8821ae_delta_swing_table_idx_24gb_n[] = {
 335        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 336        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 337
 338static u8 rtl8821ae_delta_swing_table_idx_24gb_p[]  = {
 339        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 340        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 341
 342static u8 rtl8821ae_delta_swing_table_idx_24ga_n[]  = {
 343        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 344        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 345
 346static u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = {
 347        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 348        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 349
 350static u8 rtl8821ae_delta_swing_table_idx_24gcckb_n[] = {
 351        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 352        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 353
 354static u8 rtl8821ae_delta_swing_table_idx_24gcckb_p[] = {
 355        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 356        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 357
 358static u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = {
 359        0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 360        6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 361
 362static u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = {
 363        0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 364        8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 365
 366static u8 rtl8821ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = {
 367        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 368        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 369        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 370        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 371        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 372        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 373};
 374
 375static u8 rtl8821ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = {
 376        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 377        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 378        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 379        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 380        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 381        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 382};
 383
 384static u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 385        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 386        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 387        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 388        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 389        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 390        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 391};
 392
 393static u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 394        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 395        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 396        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 397        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 398        {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 399        12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 400};
 401
 402void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw,
 403                                       u8 type, u8 *pdirection,
 404                                       u32 *poutwrite_val)
 405{
 406        struct rtl_priv *rtlpriv = rtl_priv(hw);
 407        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 408        u8 pwr_val = 0;
 409
 410        if (type == 0) {
 411                if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <=
 412                        rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) {
 413                        *pdirection = 1;
 414                        pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] -
 415                                        rtldm->swing_idx_ofdm[RF90_PATH_A];
 416                } else {
 417                        *pdirection = 2;
 418                        pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] -
 419                                rtldm->swing_idx_ofdm_base[RF90_PATH_A];
 420                }
 421        } else if (type == 1) {
 422                if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) {
 423                        *pdirection = 1;
 424                        pwr_val = rtldm->swing_idx_cck_base -
 425                                        rtldm->swing_idx_cck;
 426                } else {
 427                        *pdirection = 2;
 428                        pwr_val = rtldm->swing_idx_cck -
 429                                rtldm->swing_idx_cck_base;
 430                }
 431        }
 432
 433        if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 434                pwr_val = TXPWRTRACK_MAX_IDX;
 435
 436        *poutwrite_val = pwr_val | (pwr_val << 8)|
 437                                (pwr_val << 16)|
 438                                (pwr_val << 24);
 439}
 440
 441void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw)
 442{
 443        struct rtl_priv *rtlpriv = rtl_priv(hw);
 444        struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 445        struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 446        u8 p = 0;
 447
 448        rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 449        rtldm->swing_idx_cck = rtldm->default_cck_index;
 450        rtldm->cck_index = 0;
 451
 452        for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) {
 453                rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index;
 454                rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index;
 455                rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 456
 457                rtldm->power_index_offset[p] = 0;
 458                rtldm->delta_power_index[p] = 0;
 459                rtldm->delta_power_index_last[p] = 0;
 460                /*Initial Mix mode power tracking*/
 461                rtldm->absolute_ofdm_swing_idx[p] = 0;
 462                rtldm->remnant_ofdm_swing_idx[p] = 0;
 463        }
 464        /*Initial at Modify Tx Scaling Mode*/
 465        rtldm->modify_txagc_flag_path_a = false;
 466        /*Initial at Modify Tx Scaling Mode*/
 467        rtldm->modify_txagc_flag_path_b = false;
 468        rtldm->remnant_cck_idx = 0;
 469        rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 470        rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 471        rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 472}
 473
 474static u8  rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw)
 475{
 476        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 477        u8 i = 0;
 478        u32  bb_swing;
 479
 480        bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype,
 481                                          RF90_PATH_A);
 482
 483        for (i = 0; i < TXSCALE_TABLE_SIZE; ++i)
 484                if (bb_swing == rtl8821ae_txscaling_table[i])
 485                        break;
 486
 487        return i;
 488}
 489
 490void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(
 491                                struct ieee80211_hw *hw)
 492{
 493        struct rtl_priv *rtlpriv = rtl_priv(hw);
 494        struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 495        struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 496        u8 default_swing_index  = 0;
 497        u8 p = 0;
 498
 499        rtlpriv->dm.txpower_track_control = true;
 500        rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 501        rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 502        rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 503        default_swing_index = rtl8821ae_dm_get_swing_index(hw);
 504
 505        rtldm->default_ofdm_index =
 506                (default_swing_index == TXSCALE_TABLE_SIZE) ?
 507                24 : default_swing_index;
 508        rtldm->default_cck_index = 24;
 509
 510        rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 511        rtldm->cck_index = rtldm->default_cck_index;
 512
 513        for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) {
 514                rtldm->swing_idx_ofdm_base[p] =
 515                        rtldm->default_ofdm_index;
 516                rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 517                rtldm->delta_power_index[p] = 0;
 518                rtldm->power_index_offset[p] = 0;
 519                rtldm->delta_power_index_last[p] = 0;
 520        }
 521}
 522
 523void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
 524{
 525        struct rtl_priv *rtlpriv = rtl_priv(hw);
 526
 527        rtlpriv->dm.current_turbo_edca = false;
 528        rtlpriv->dm.is_any_nonbepkts = false;
 529        rtlpriv->dm.is_cur_rdlstate = false;
 530}
 531
 532void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 533{
 534        struct rtl_priv *rtlpriv = rtl_priv(hw);
 535        struct rate_adaptive *p_ra = &rtlpriv->ra;
 536
 537        p_ra->ratr_state = DM_RATR_STA_INIT;
 538        p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 539
 540        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 541        if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 542                rtlpriv->dm.useramask = true;
 543        else
 544                rtlpriv->dm.useramask = false;
 545
 546        p_ra->high_rssi_thresh_for_ra = 50;
 547        p_ra->low_rssi_thresh_for_ra40m = 20;
 548}
 549
 550static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 551{
 552        struct rtl_priv *rtlpriv = rtl_priv(hw);
 553
 554        rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 555
 556        rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
 557        rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 558}
 559
 560static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw)
 561{
 562        struct rtl_priv *rtlpriv = rtl_priv(hw);
 563        struct rtl_phy *rtlphy = &rtlpriv->phy;
 564        u8 tmp;
 565
 566        rtlphy->cck_high_power =
 567                (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC,
 568                                    ODM_BIT_CCK_RPT_FORMAT_11AC);
 569
 570        tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC,
 571                                ODM_BIT_BB_RX_PATH_11AC);
 572        if (tmp & BIT(0))
 573                rtlpriv->dm.rfpath_rxenable[0] = true;
 574        if (tmp & BIT(1))
 575                rtlpriv->dm.rfpath_rxenable[1] = true;
 576}
 577
 578void rtl8821ae_dm_init(struct ieee80211_hw *hw)
 579{
 580        struct rtl_priv *rtlpriv = rtl_priv(hw);
 581        struct rtl_phy *rtlphy = &rtlpriv->phy;
 582        u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 583
 584        spin_lock(&rtlpriv->locks.iqk_lock);
 585        rtlphy->lck_inprogress = false;
 586        spin_unlock(&rtlpriv->locks.iqk_lock);
 587
 588        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 589        rtl8821ae_dm_common_info_self_init(hw);
 590        rtl_dm_diginit(hw, cur_igvalue);
 591        rtl8821ae_dm_init_rate_adaptive_mask(hw);
 592        rtl8821ae_dm_init_edca_turbo(hw);
 593        rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw);
 594        rtl8821ae_dm_init_dynamic_atc_switch(hw);
 595}
 596
 597static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 598{
 599        struct rtl_priv *rtlpriv = rtl_priv(hw);
 600        struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 601        struct rtl_mac *mac = rtl_mac(rtlpriv);
 602
 603        /* Determine the minimum RSSI  */
 604        if ((mac->link_state < MAC80211_LINKED) &&
 605            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 606                rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 607                RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 608                         "Not connected to any\n");
 609        }
 610        if (mac->link_state >= MAC80211_LINKED) {
 611                if (mac->opmode == NL80211_IFTYPE_AP ||
 612                    mac->opmode == NL80211_IFTYPE_ADHOC) {
 613                        rtl_dm_dig->min_undec_pwdb_for_dm =
 614                            rtlpriv->dm.entry_min_undec_sm_pwdb;
 615                        RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 616                                 "AP Client PWDB = 0x%lx\n",
 617                                 rtlpriv->dm.entry_min_undec_sm_pwdb);
 618                } else {
 619                        rtl_dm_dig->min_undec_pwdb_for_dm =
 620                            rtlpriv->dm.undec_sm_pwdb;
 621                        RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 622                                 "STA Default Port PWDB = 0x%x\n",
 623                                 rtl_dm_dig->min_undec_pwdb_for_dm);
 624                }
 625        } else {
 626                rtl_dm_dig->min_undec_pwdb_for_dm =
 627                    rtlpriv->dm.entry_min_undec_sm_pwdb;
 628                RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 629                         "AP Ext Port or disconnet PWDB = 0x%x\n",
 630                         rtl_dm_dig->min_undec_pwdb_for_dm);
 631        }
 632        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 633                 "MinUndecoratedPWDBForDM =%d\n",
 634                 rtl_dm_dig->min_undec_pwdb_for_dm);
 635}
 636
 637static void  rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw)
 638{
 639        struct rtl_priv *rtlpriv = rtl_priv(hw);
 640
 641        rtl_write_byte(rtlpriv, RA_RSSI_DUMP,
 642                       rtlpriv->stats.rx_rssi_percentage[0]);
 643        rtl_write_byte(rtlpriv, RB_RSSI_DUMP,
 644                       rtlpriv->stats.rx_rssi_percentage[1]);
 645
 646        /* Rx EVM*/
 647        rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP,
 648                       rtlpriv->stats.rx_evm_dbm[0]);
 649        rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP,
 650                       rtlpriv->stats.rx_evm_dbm[1]);
 651
 652        /*Rx SNR*/
 653        rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP,
 654                       (u8)(rtlpriv->stats.rx_snr_db[0]));
 655        rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP,
 656                       (u8)(rtlpriv->stats.rx_snr_db[1]));
 657
 658        /*Rx Cfo_Short*/
 659        rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP,
 660                       rtlpriv->stats.rx_cfo_short[0]);
 661        rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP,
 662                       rtlpriv->stats.rx_cfo_short[1]);
 663
 664        /*Rx Cfo_Tail*/
 665        rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP,
 666                       rtlpriv->stats.rx_cfo_tail[0]);
 667        rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP,
 668                       rtlpriv->stats.rx_cfo_tail[1]);
 669}
 670
 671static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 672{
 673        struct rtl_priv *rtlpriv = rtl_priv(hw);
 674        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 675        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 676        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 677        struct rtl_sta_info *drv_priv;
 678        u8 h2c_parameter[4] = { 0 };
 679        long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 680        u8 stbc_tx = 0;
 681        u64 cur_txokcnt = 0, cur_rxokcnt = 0;
 682        static u64 last_txokcnt = 0, last_rxokcnt;
 683
 684        cur_txokcnt = rtlpriv->stats.txbytesunicast - last_txokcnt;
 685        cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt;
 686        last_txokcnt = rtlpriv->stats.txbytesunicast;
 687        last_rxokcnt = rtlpriv->stats.rxbytesunicast;
 688        if (cur_rxokcnt > (last_txokcnt * 6))
 689                h2c_parameter[3] = 0x01;
 690        else
 691                h2c_parameter[3] = 0x00;
 692
 693        /* AP & ADHOC & MESH */
 694        if (mac->opmode == NL80211_IFTYPE_AP ||
 695            mac->opmode == NL80211_IFTYPE_ADHOC ||
 696            mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 697                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 698                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 699                        if (drv_priv->rssi_stat.undec_sm_pwdb <
 700                                        tmp_entry_min_pwdb)
 701                                tmp_entry_min_pwdb =
 702                                        drv_priv->rssi_stat.undec_sm_pwdb;
 703                        if (drv_priv->rssi_stat.undec_sm_pwdb >
 704                                        tmp_entry_max_pwdb)
 705                                tmp_entry_max_pwdb =
 706                                        drv_priv->rssi_stat.undec_sm_pwdb;
 707                }
 708                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 709
 710                /* If associated entry is found */
 711                if (tmp_entry_max_pwdb != 0) {
 712                        rtlpriv->dm.entry_max_undec_sm_pwdb =
 713                                tmp_entry_max_pwdb;
 714                        RTPRINT(rtlpriv, FDM, DM_PWDB,
 715                                "EntryMaxPWDB = 0x%lx(%ld)\n",
 716                                tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 717                } else {
 718                        rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 719                }
 720                /* If associated entry is found */
 721                if (tmp_entry_min_pwdb != 0xff) {
 722                        rtlpriv->dm.entry_min_undec_sm_pwdb =
 723                                tmp_entry_min_pwdb;
 724                        RTPRINT(rtlpriv, FDM, DM_PWDB,
 725                                "EntryMinPWDB = 0x%lx(%ld)\n",
 726                                tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 727                } else {
 728                        rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 729                }
 730        }
 731        /* Indicate Rx signal strength to FW. */
 732        if (rtlpriv->dm.useramask) {
 733                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
 734                        if (mac->mode == WIRELESS_MODE_AC_24G ||
 735                            mac->mode == WIRELESS_MODE_AC_5G ||
 736                            mac->mode == WIRELESS_MODE_AC_ONLY)
 737                                stbc_tx = (mac->vht_cur_stbc &
 738                                           STBC_VHT_ENABLE_TX) ? 1 : 0;
 739                        else
 740                                stbc_tx = (mac->ht_cur_stbc &
 741                                           STBC_HT_ENABLE_TX) ? 1 : 0;
 742                        h2c_parameter[3] |= stbc_tx << 1;
 743                }
 744                h2c_parameter[2] =
 745                        (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 746                h2c_parameter[1] = 0x20;
 747                h2c_parameter[0] = 0;
 748                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 749                        rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4,
 750                                               h2c_parameter);
 751                else
 752                        rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3,
 753                                               h2c_parameter);
 754        } else {
 755                rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
 756        }
 757        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 758                rtl8812ae_dm_rssi_dump_to_register(hw);
 759        rtl8821ae_dm_find_minimum_rssi(hw);
 760        dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 761}
 762
 763void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca)
 764{
 765        struct rtl_priv *rtlpriv = rtl_priv(hw);
 766        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 767
 768        if (dm_digtable->cur_cck_cca_thres != current_cca)
 769                rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca);
 770
 771        dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
 772        dm_digtable->cur_cck_cca_thres = current_cca;
 773}
 774
 775void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 776{
 777        struct rtl_priv *rtlpriv = rtl_priv(hw);
 778        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 779
 780        if (dm_digtable->stop_dig)
 781                return;
 782
 783        if (dm_digtable->cur_igvalue != current_igi) {
 784                rtl_set_bbreg(hw, DM_REG_IGI_A_11AC,
 785                              DM_BIT_IGI_11AC, current_igi);
 786                if (rtlpriv->phy.rf_type != RF_1T1R)
 787                        rtl_set_bbreg(hw, DM_REG_IGI_B_11AC,
 788                                      DM_BIT_IGI_11AC, current_igi);
 789        }
 790        dm_digtable->cur_igvalue = current_igi;
 791}
 792
 793static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 794{
 795        struct rtl_priv *rtlpriv = rtl_priv(hw);
 796        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 797        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 798        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 799        u8 dig_min_0;
 800        u8 dig_max_of_min;
 801        bool first_connect, first_disconnect;
 802        u8 dm_dig_max, dm_dig_min, offset;
 803        u8 current_igi = dm_digtable->cur_igvalue;
 804
 805        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "\n");
 806
 807        if (mac->act_scanning) {
 808                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 809                         "Return: In Scan Progress\n");
 810                return;
 811        }
 812
 813        /*add by Neil Chen to avoid PSD is processing*/
 814        dig_min_0 = dm_digtable->dig_min_0;
 815        first_connect = (mac->link_state >= MAC80211_LINKED) &&
 816                        (!dm_digtable->media_connect_0);
 817        first_disconnect = (mac->link_state < MAC80211_LINKED) &&
 818                        (dm_digtable->media_connect_0);
 819
 820        /*1 Boundary Decision*/
 821
 822        dm_dig_max = 0x5A;
 823
 824        if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 825                dm_dig_min = DM_DIG_MIN;
 826        else
 827                dm_dig_min = 0x1C;
 828
 829        dig_max_of_min = DM_DIG_MAX_AP;
 830
 831        if (mac->link_state >= MAC80211_LINKED) {
 832                if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 833                        offset = 20;
 834                else
 835                        offset = 10;
 836
 837                if ((dm_digtable->rssi_val_min + offset) > dm_dig_max)
 838                        dm_digtable->rx_gain_max = dm_dig_max;
 839                else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min)
 840                        dm_digtable->rx_gain_max = dm_dig_min;
 841                else
 842                        dm_digtable->rx_gain_max =
 843                                dm_digtable->rssi_val_min + offset;
 844
 845                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 846                         "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x",
 847                         dm_digtable->rssi_val_min,
 848                         dm_digtable->rx_gain_max);
 849                if (rtlpriv->dm.one_entry_only) {
 850                        offset = 0;
 851
 852                        if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 853                                dig_min_0 = dm_dig_min;
 854                        else if (dm_digtable->rssi_val_min -
 855                                offset > dig_max_of_min)
 856                                dig_min_0 = dig_max_of_min;
 857                        else
 858                                dig_min_0 =
 859                                        dm_digtable->rssi_val_min - offset;
 860
 861                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 862                                 "bOneEntryOnly=TRUE, dig_min_0=0x%x\n",
 863                                 dig_min_0);
 864                } else {
 865                        dig_min_0 = dm_dig_min;
 866                }
 867        } else {
 868                dm_digtable->rx_gain_max = dm_dig_max;
 869                dig_min_0 = dm_dig_min;
 870                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 871                         "No Link\n");
 872        }
 873
 874        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 875                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 876                         "Abnormally false alarm case.\n");
 877
 878                if (dm_digtable->large_fa_hit != 3)
 879                        dm_digtable->large_fa_hit++;
 880                if (dm_digtable->forbidden_igi < current_igi) {
 881                        dm_digtable->forbidden_igi = current_igi;
 882                        dm_digtable->large_fa_hit = 1;
 883                }
 884
 885                if (dm_digtable->large_fa_hit >= 3) {
 886                        if ((dm_digtable->forbidden_igi + 1) >
 887                                dm_digtable->rx_gain_max)
 888                                dm_digtable->rx_gain_min =
 889                                        dm_digtable->rx_gain_max;
 890                        else
 891                                dm_digtable->rx_gain_min =
 892                                        (dm_digtable->forbidden_igi + 1);
 893                        dm_digtable->recover_cnt = 3600;
 894                }
 895        } else {
 896                /*Recovery mechanism for IGI lower bound*/
 897                if (dm_digtable->recover_cnt != 0) {
 898                        dm_digtable->recover_cnt--;
 899                } else {
 900                        if (dm_digtable->large_fa_hit < 3) {
 901                                if ((dm_digtable->forbidden_igi - 1) <
 902                                    dig_min_0) {
 903                                        dm_digtable->forbidden_igi =
 904                                                dig_min_0;
 905                                        dm_digtable->rx_gain_min =
 906                                                dig_min_0;
 907                                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 908                                                 "Normal Case: At Lower Bound\n");
 909                                } else {
 910                                        dm_digtable->forbidden_igi--;
 911                                        dm_digtable->rx_gain_min =
 912                                          (dm_digtable->forbidden_igi + 1);
 913                                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 914                                                 "Normal Case: Approach Lower Bound\n");
 915                                }
 916                        } else {
 917                                dm_digtable->large_fa_hit = 0;
 918                        }
 919                }
 920        }
 921        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 922                 "pDM_DigTable->LargeFAHit=%d\n",
 923                 dm_digtable->large_fa_hit);
 924
 925        if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10)
 926                dm_digtable->rx_gain_min = dm_dig_min;
 927
 928        if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 929                dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 930
 931        /*Adjust initial gain by false alarm*/
 932        if (mac->link_state >= MAC80211_LINKED) {
 933                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 934                         "DIG AfterLink\n");
 935                if (first_connect) {
 936                        if (dm_digtable->rssi_val_min <= dig_max_of_min)
 937                                current_igi = dm_digtable->rssi_val_min;
 938                        else
 939                                current_igi = dig_max_of_min;
 940                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 941                                 "First Connect\n");
 942                } else {
 943                        if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 944                                current_igi = current_igi + 4;
 945                        else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 946                                current_igi = current_igi + 2;
 947                        else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 948                                current_igi = current_igi - 2;
 949
 950                        if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) &&
 951                            (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) {
 952                                current_igi = dm_digtable->rx_gain_min;
 953                                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 954                                         "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n");
 955                        }
 956                }
 957        } else {
 958                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 959                         "DIG BeforeLink\n");
 960                if (first_disconnect) {
 961                        current_igi = dm_digtable->rx_gain_min;
 962                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 963                                 "First DisConnect\n");
 964                } else {
 965                        /* 2012.03.30 LukeLee: enable DIG before
 966                         * link but with very high thresholds
 967                         */
 968                        if (rtlpriv->falsealm_cnt.cnt_all > 2000)
 969                                current_igi = current_igi + 4;
 970                        else if (rtlpriv->falsealm_cnt.cnt_all > 600)
 971                                current_igi = current_igi + 2;
 972                        else if (rtlpriv->falsealm_cnt.cnt_all < 300)
 973                                current_igi = current_igi - 2;
 974
 975                        if (current_igi >= 0x3e)
 976                                current_igi = 0x3e;
 977
 978                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
 979                }
 980        }
 981        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 982                 "DIG End Adjust IGI\n");
 983        /* Check initial gain by upper/lower bound*/
 984
 985        if (current_igi > dm_digtable->rx_gain_max)
 986                current_igi = dm_digtable->rx_gain_max;
 987        if (current_igi < dm_digtable->rx_gain_min)
 988                current_igi = dm_digtable->rx_gain_min;
 989
 990        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 991                 "rx_gain_max=0x%x, rx_gain_min=0x%x\n",
 992                dm_digtable->rx_gain_max, dm_digtable->rx_gain_min);
 993        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 994                 "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all);
 995        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 996                 "CurIGValue=0x%x\n", current_igi);
 997
 998        rtl8821ae_dm_write_dig(hw, current_igi);
 999        dm_digtable->media_connect_0 =
1000                ((mac->link_state >= MAC80211_LINKED) ? true : false);
1001        dm_digtable->dig_min_0 = dig_min_0;
1002}
1003
1004static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
1005{
1006        struct rtl_priv *rtlpriv = rtl_priv(hw);
1007        u8 cnt = 0;
1008        struct rtl_sta_info *drv_priv;
1009
1010        rtlpriv->dm.tx_rate = 0xff;
1011
1012        rtlpriv->dm.one_entry_only = false;
1013
1014        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1015            rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1016                rtlpriv->dm.one_entry_only = true;
1017                return;
1018        }
1019
1020        if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1021            rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1022            rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1023                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1024                list_for_each_entry(drv_priv, &rtlpriv->entry_list, list)
1025                        cnt++;
1026                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1027
1028                if (cnt == 1)
1029                        rtlpriv->dm.one_entry_only = true;
1030        }
1031}
1032
1033static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
1034{
1035        struct rtl_priv *rtlpriv = rtl_priv(hw);
1036        struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
1037        u32 cck_enable = 0;
1038
1039        /*read OFDM FA counter*/
1040        falsealm_cnt->cnt_ofdm_fail =
1041                rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD);
1042        falsealm_cnt->cnt_cck_fail =
1043                rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD);
1044
1045        cck_enable =  rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28));
1046        if (cck_enable)  /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/
1047                falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
1048                                        falsealm_cnt->cnt_cck_fail;
1049        else
1050                falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
1051
1052        /*reset OFDM FA coutner*/
1053        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
1054        rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
1055        /* reset CCK FA counter*/
1056        rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
1057        rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
1058
1059        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n",
1060                 falsealm_cnt->cnt_cck_fail);
1061        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n",
1062                 falsealm_cnt->cnt_ofdm_fail);
1063        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n",
1064                 falsealm_cnt->cnt_all);
1065}
1066
1067static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
1068                struct ieee80211_hw *hw)
1069{
1070        struct rtl_priv *rtlpriv = rtl_priv(hw);
1071        static u8 tm_trigger;
1072
1073        if (!tm_trigger) {
1074                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
1075                              BIT(17) | BIT(16), 0x03);
1076                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1077                         "Trigger 8812 Thermal Meter!!\n");
1078                tm_trigger = 1;
1079                return;
1080        }
1081        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1082                 "Schedule TxPowerTracking direct call!!\n");
1083        rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
1084        tm_trigger = 0;
1085}
1086
1087static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
1088{
1089        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1090        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1091        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1092
1093        if (mac->link_state >= MAC80211_LINKED) {
1094                if (rtldm->linked_interval < 3)
1095                        rtldm->linked_interval++;
1096
1097                if (rtldm->linked_interval == 2) {
1098                        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
1099                                rtl8812ae_phy_iq_calibrate(hw, false);
1100                        else
1101                                rtl8821ae_phy_iq_calibrate(hw, false);
1102                }
1103        } else {
1104                rtldm->linked_interval = 0;
1105        }
1106}
1107
1108static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
1109                                            u8 **up_a, u8 **down_a,
1110                                            u8 **up_b, u8 **down_b)
1111{
1112        struct rtl_priv *rtlpriv = rtl_priv(hw);
1113        struct rtl_phy *rtlphy = &rtlpriv->phy;
1114        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1115        u8 channel = rtlphy->current_channel;
1116        u8 rate = rtldm->tx_rate;
1117
1118        if (1 <= channel && channel <= 14) {
1119                if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1120                        *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
1121                        *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
1122                        *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
1123                        *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
1124                } else {
1125                        *up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
1126                        *down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
1127                        *up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
1128                        *down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
1129                }
1130        } else if (36 <= channel && channel <= 64) {
1131                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
1132                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
1133                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
1134                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
1135        } else if (100 <= channel && channel <= 140) {
1136                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
1137                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
1138                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
1139                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
1140        } else if (149 <= channel && channel <= 173) {
1141                *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
1142                *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
1143                *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
1144                *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
1145        } else {
1146            *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
1147            *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
1148            *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
1149            *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
1150        }
1151}
1152
1153void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
1154{
1155        struct rtl_priv *rtlpriv = rtl_priv(hw);
1156        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1157        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1158        u8 p = 0;
1159
1160        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1161                 "Get C2H Command! Rate=0x%x\n", rate);
1162
1163        rtldm->tx_rate = rate;
1164
1165        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
1166                rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
1167        } else {
1168                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1169                        rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
1170        }
1171}
1172
1173u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
1174{
1175        struct rtl_priv *rtlpriv = rtl_priv(hw);
1176        u8 ret_rate = MGN_1M;
1177
1178        switch (rate) {
1179        case DESC_RATE1M:
1180                ret_rate = MGN_1M;
1181                break;
1182        case DESC_RATE2M:
1183                ret_rate = MGN_2M;
1184                break;
1185        case DESC_RATE5_5M:
1186                ret_rate = MGN_5_5M;
1187                break;
1188        case DESC_RATE11M:
1189                ret_rate = MGN_11M;
1190                break;
1191        case DESC_RATE6M:
1192                ret_rate = MGN_6M;
1193                break;
1194        case DESC_RATE9M:
1195                ret_rate = MGN_9M;
1196                break;
1197        case DESC_RATE12M:
1198                ret_rate = MGN_12M;
1199                break;
1200        case DESC_RATE18M:
1201                ret_rate = MGN_18M;
1202                break;
1203        case DESC_RATE24M:
1204                ret_rate = MGN_24M;
1205                break;
1206        case DESC_RATE36M:
1207                ret_rate = MGN_36M;
1208                break;
1209        case DESC_RATE48M:
1210                ret_rate = MGN_48M;
1211                break;
1212        case DESC_RATE54M:
1213                ret_rate = MGN_54M;
1214                break;
1215        case DESC_RATEMCS0:
1216                ret_rate = MGN_MCS0;
1217                break;
1218        case DESC_RATEMCS1:
1219                ret_rate = MGN_MCS1;
1220                break;
1221        case DESC_RATEMCS2:
1222                ret_rate = MGN_MCS2;
1223                break;
1224        case DESC_RATEMCS3:
1225                ret_rate = MGN_MCS3;
1226                break;
1227        case DESC_RATEMCS4:
1228                ret_rate = MGN_MCS4;
1229                break;
1230        case DESC_RATEMCS5:
1231                ret_rate = MGN_MCS5;
1232                break;
1233        case DESC_RATEMCS6:
1234                ret_rate = MGN_MCS6;
1235                break;
1236        case DESC_RATEMCS7:
1237                ret_rate = MGN_MCS7;
1238                break;
1239        case DESC_RATEMCS8:
1240                ret_rate = MGN_MCS8;
1241                break;
1242        case DESC_RATEMCS9:
1243                ret_rate = MGN_MCS9;
1244                break;
1245        case DESC_RATEMCS10:
1246                ret_rate = MGN_MCS10;
1247                break;
1248        case DESC_RATEMCS11:
1249                ret_rate = MGN_MCS11;
1250                break;
1251        case DESC_RATEMCS12:
1252                ret_rate = MGN_MCS12;
1253                break;
1254        case DESC_RATEMCS13:
1255                ret_rate = MGN_MCS13;
1256                break;
1257        case DESC_RATEMCS14:
1258                ret_rate = MGN_MCS14;
1259                break;
1260        case DESC_RATEMCS15:
1261                ret_rate = MGN_MCS15;
1262                break;
1263        case DESC_RATEVHT1SS_MCS0:
1264                ret_rate = MGN_VHT1SS_MCS0;
1265                break;
1266        case DESC_RATEVHT1SS_MCS1:
1267                ret_rate = MGN_VHT1SS_MCS1;
1268                break;
1269        case DESC_RATEVHT1SS_MCS2:
1270                ret_rate = MGN_VHT1SS_MCS2;
1271                break;
1272        case DESC_RATEVHT1SS_MCS3:
1273                ret_rate = MGN_VHT1SS_MCS3;
1274                break;
1275        case DESC_RATEVHT1SS_MCS4:
1276                ret_rate = MGN_VHT1SS_MCS4;
1277                break;
1278        case DESC_RATEVHT1SS_MCS5:
1279                ret_rate = MGN_VHT1SS_MCS5;
1280                break;
1281        case DESC_RATEVHT1SS_MCS6:
1282                ret_rate = MGN_VHT1SS_MCS6;
1283                break;
1284        case DESC_RATEVHT1SS_MCS7:
1285                ret_rate = MGN_VHT1SS_MCS7;
1286                break;
1287        case DESC_RATEVHT1SS_MCS8:
1288                ret_rate = MGN_VHT1SS_MCS8;
1289                break;
1290        case DESC_RATEVHT1SS_MCS9:
1291                ret_rate = MGN_VHT1SS_MCS9;
1292                break;
1293        case DESC_RATEVHT2SS_MCS0:
1294                ret_rate = MGN_VHT2SS_MCS0;
1295                break;
1296        case DESC_RATEVHT2SS_MCS1:
1297                ret_rate = MGN_VHT2SS_MCS1;
1298                break;
1299        case DESC_RATEVHT2SS_MCS2:
1300                ret_rate = MGN_VHT2SS_MCS2;
1301                break;
1302        case DESC_RATEVHT2SS_MCS3:
1303                ret_rate = MGN_VHT2SS_MCS3;
1304                break;
1305        case DESC_RATEVHT2SS_MCS4:
1306                ret_rate = MGN_VHT2SS_MCS4;
1307                break;
1308        case DESC_RATEVHT2SS_MCS5:
1309                ret_rate = MGN_VHT2SS_MCS5;
1310                break;
1311        case DESC_RATEVHT2SS_MCS6:
1312                ret_rate = MGN_VHT2SS_MCS6;
1313                break;
1314        case DESC_RATEVHT2SS_MCS7:
1315                ret_rate = MGN_VHT2SS_MCS7;
1316                break;
1317        case DESC_RATEVHT2SS_MCS8:
1318                ret_rate = MGN_VHT2SS_MCS8;
1319                break;
1320        case DESC_RATEVHT2SS_MCS9:
1321                ret_rate = MGN_VHT2SS_MCS9;
1322                break;
1323        default:
1324                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1325                         "HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1326                         rate);
1327                break;
1328        }
1329        return ret_rate;
1330}
1331
1332/*-----------------------------------------------------------------------------
1333 * Function:    odm_TxPwrTrackSetPwr88E()
1334 *
1335 * Overview:    88E change all channel tx power accordign to flag.
1336 *                              OFDM & CCK are all different.
1337 *
1338 * Input:               NONE
1339 *
1340 * Output:              NONE
1341 *
1342 * Return:              NONE
1343 *
1344 * Revised History:
1345 *      When            Who             Remark
1346 *      04/23/2012      MHC             Create Version 0.
1347 *
1348 *---------------------------------------------------------------------------
1349 */
1350void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1351                                      enum pwr_track_control_method method,
1352                                      u8 rf_path, u8 channel_mapped_index)
1353{
1354        struct rtl_priv *rtlpriv = rtl_priv(hw);
1355        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1356        struct rtl_phy *rtlphy = &rtlpriv->phy;
1357        u32 final_swing_idx[2];
1358        u8 pwr_tracking_limit = 26; /*+1.0dB*/
1359        u8 tx_rate = 0xFF;
1360        char final_ofdm_swing_index = 0;
1361
1362        if (rtldm->tx_rate != 0xFF)
1363                tx_rate =
1364                        rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1365
1366        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1367                 "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
1368        /*20130429 Mimic Modify High Rate BBSwing Limit.*/
1369        if (tx_rate != 0xFF) {
1370                /*CCK*/
1371                if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1372                        pwr_tracking_limit = 32; /*+4dB*/
1373                /*OFDM*/
1374                else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1375                        pwr_tracking_limit = 30; /*+3dB*/
1376                else if (tx_rate == MGN_54M)
1377                        pwr_tracking_limit = 28; /*+2dB*/
1378                /*HT*/
1379                 /*QPSK/BPSK*/
1380                else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1381                        pwr_tracking_limit = 34; /*+5dB*/
1382                 /*16QAM*/
1383                else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1384                        pwr_tracking_limit = 30; /*+3dB*/
1385                 /*64QAM*/
1386                else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1387                        pwr_tracking_limit = 28; /*+2dB*/
1388                 /*QPSK/BPSK*/
1389                else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1390                        pwr_tracking_limit = 34; /*+5dB*/
1391                 /*16QAM*/
1392                else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1393                        pwr_tracking_limit = 30; /*+3dB*/
1394                 /*64QAM*/
1395                else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1396                        pwr_tracking_limit = 28; /*+2dB*/
1397
1398                /*2 VHT*/
1399                 /*QPSK/BPSK*/
1400                else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1401                         (tx_rate <= MGN_VHT1SS_MCS2))
1402                        pwr_tracking_limit = 34; /*+5dB*/
1403                 /*16QAM*/
1404                else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1405                         (tx_rate <= MGN_VHT1SS_MCS4))
1406                        pwr_tracking_limit = 30; /*+3dB*/
1407                 /*64QAM*/
1408                else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1409                         (tx_rate <= MGN_VHT1SS_MCS6))
1410                        pwr_tracking_limit = 28; /*+2dB*/
1411                else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1412                        pwr_tracking_limit = 26; /*+1dB*/
1413                else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1414                        pwr_tracking_limit = 24; /*+0dB*/
1415                else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1416                        pwr_tracking_limit = 22; /*-1dB*/
1417                 /*QPSK/BPSK*/
1418                else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1419                         (tx_rate <= MGN_VHT2SS_MCS2))
1420                        pwr_tracking_limit = 34; /*+5dB*/
1421                 /*16QAM*/
1422                else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1423                         (tx_rate <= MGN_VHT2SS_MCS4))
1424                        pwr_tracking_limit = 30; /*+3dB*/
1425                 /*64QAM*/
1426                else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1427                         (tx_rate <= MGN_VHT2SS_MCS6))
1428                        pwr_tracking_limit = 28; /*+2dB*/
1429                else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1430                        pwr_tracking_limit = 26; /*+1dB*/
1431                else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1432                        pwr_tracking_limit = 24; /*+0dB*/
1433                else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1434                        pwr_tracking_limit = 22; /*-1dB*/
1435                else
1436                        pwr_tracking_limit = 24;
1437        }
1438        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1439                 "TxRate=0x%x, PwrTrackingLimit=%d\n",
1440                 tx_rate, pwr_tracking_limit);
1441
1442        if (method == BBSWING) {
1443                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1444                         "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
1445
1446                if (rf_path == RF90_PATH_A) {
1447                        u32 tmp;
1448
1449                        final_swing_idx[RF90_PATH_A] =
1450                                (rtldm->ofdm_index[RF90_PATH_A] >
1451                                pwr_tracking_limit) ?
1452                                pwr_tracking_limit :
1453                                rtldm->ofdm_index[RF90_PATH_A];
1454                        tmp = final_swing_idx[RF90_PATH_A];
1455                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1456                                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1457                                 rtldm->ofdm_index[RF90_PATH_A],
1458                                 final_swing_idx[RF90_PATH_A]);
1459
1460                        rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1461                                      txscaling_tbl[tmp]);
1462                } else {
1463                        u32 tmp;
1464
1465                        final_swing_idx[RF90_PATH_B] =
1466                                rtldm->ofdm_index[RF90_PATH_B] >
1467                                pwr_tracking_limit ?
1468                                pwr_tracking_limit :
1469                                rtldm->ofdm_index[RF90_PATH_B];
1470                        tmp = final_swing_idx[RF90_PATH_B];
1471                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1472                                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1473                                 rtldm->ofdm_index[RF90_PATH_B],
1474                                 final_swing_idx[RF90_PATH_B]);
1475
1476                        rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1477                                      txscaling_tbl[tmp]);
1478                }
1479        } else if (method == MIX_MODE) {
1480                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1481                         "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1482                         rtldm->default_ofdm_index,
1483                         rtldm->absolute_ofdm_swing_idx[rf_path],
1484                         rf_path);
1485
1486                final_ofdm_swing_index = rtldm->default_ofdm_index +
1487                                rtldm->absolute_ofdm_swing_idx[rf_path];
1488
1489                if (rf_path == RF90_PATH_A) {
1490                        /*BBSwing higher then Limit*/
1491                        if (final_ofdm_swing_index > pwr_tracking_limit) {
1492                                rtldm->remnant_cck_idx =
1493                                        final_ofdm_swing_index -
1494                                        pwr_tracking_limit;
1495                                /* CCK Follow the same compensation value
1496                                 * as Path A
1497                                 */
1498                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1499                                        final_ofdm_swing_index -
1500                                        pwr_tracking_limit;
1501
1502                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1503                                              txscaling_tbl[pwr_tracking_limit]);
1504
1505                                rtldm->modify_txagc_flag_path_a = true;
1506
1507                                /*Set TxAGC Page C{};*/
1508                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1509                                        rtlphy->current_channel,
1510                                        RF90_PATH_A);
1511
1512                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1513                                         "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1514                                         pwr_tracking_limit,
1515                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
1516                        } else if (final_ofdm_swing_index < 0) {
1517                                rtldm->remnant_cck_idx = final_ofdm_swing_index;
1518                                /* CCK Follow the same compensate value as Path A*/
1519                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1520                                        final_ofdm_swing_index;
1521
1522                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1523                                        txscaling_tbl[0]);
1524
1525                                rtldm->modify_txagc_flag_path_a = true;
1526
1527                                /*Set TxAGC Page C{};*/
1528                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1529                                        rtlphy->current_channel, RF90_PATH_A);
1530
1531                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1532                                         "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1533                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
1534                        } else {
1535                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1536                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
1537
1538                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1539                                         "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1540                                        final_ofdm_swing_index);
1541                                /*If TxAGC has changed, reset TxAGC again*/
1542                                if (rtldm->modify_txagc_flag_path_a) {
1543                                        rtldm->remnant_cck_idx = 0;
1544                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1545
1546                                        /*Set TxAGC Page C{};*/
1547                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
1548                                                rtlphy->current_channel, RF90_PATH_A);
1549                                        rtldm->modify_txagc_flag_path_a = false;
1550
1551                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
1552                                                 DBG_LOUD,
1553                                                 "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1554                                }
1555                        }
1556                }
1557                /*BBSwing higher then Limit*/
1558                if (rf_path == RF90_PATH_B) {
1559                        if (final_ofdm_swing_index > pwr_tracking_limit) {
1560                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1561                                        final_ofdm_swing_index -
1562                                        pwr_tracking_limit;
1563
1564                                rtl_set_bbreg(hw, RB_TXSCALE,
1565                                        0xFFE00000,
1566                                        txscaling_tbl[pwr_tracking_limit]);
1567
1568                                rtldm->modify_txagc_flag_path_b = true;
1569
1570                                /*Set TxAGC Page E{};*/
1571                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1572                                        rtlphy->current_channel, RF90_PATH_B);
1573
1574                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1575                                         "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1576                                         pwr_tracking_limit,
1577                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
1578                        } else if (final_ofdm_swing_index < 0) {
1579                                rtldm->remnant_ofdm_swing_idx[rf_path] =
1580                                        final_ofdm_swing_index;
1581
1582                                rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1583                                              txscaling_tbl[0]);
1584
1585                                rtldm->modify_txagc_flag_path_b = true;
1586
1587                                /*Set TxAGC Page E{};*/
1588                                rtl8821ae_phy_set_txpower_level_by_path(hw,
1589                                        rtlphy->current_channel, RF90_PATH_B);
1590
1591                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1592                                         "******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1593                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
1594                        } else {
1595                                rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1596                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
1597
1598                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1599                                         "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1600                                        final_ofdm_swing_index);
1601                                 /*If TxAGC has changed, reset TxAGC again*/
1602                                if (rtldm->modify_txagc_flag_path_b) {
1603                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1604
1605                                        /*Set TxAGC Page E{};*/
1606                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
1607                                        rtlphy->current_channel, RF90_PATH_B);
1608
1609                                        rtldm->modify_txagc_flag_path_b =
1610                                                false;
1611
1612                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1613                                                 "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1614                                }
1615                        }
1616                }
1617        } else {
1618                return;
1619        }
1620}
1621
1622void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1623        struct ieee80211_hw *hw)
1624{
1625        struct rtl_priv *rtlpriv = rtl_priv(hw);
1626        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1627        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1628        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1629        u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1630        u8 thermal_value_avg_count = 0;
1631        u32 thermal_value_avg = 0;
1632        /* OFDM BB Swing should be less than +3.0dB, */
1633        u8 ofdm_min_index = 6;
1634         /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1635        u8 index_for_channel = 0;
1636        /* 1. The following TWO tables decide
1637         * the final index of OFDM/CCK swing table.
1638         */
1639        u8 *delta_swing_table_idx_tup_a;
1640        u8 *delta_swing_table_idx_tdown_a;
1641        u8 *delta_swing_table_idx_tup_b;
1642        u8 *delta_swing_table_idx_tdown_b;
1643
1644        /*2. Initilization ( 7 steps in total )*/
1645        rtl8812ae_get_delta_swing_table(hw,
1646                (u8 **)&delta_swing_table_idx_tup_a,
1647                (u8 **)&delta_swing_table_idx_tdown_a,
1648                (u8 **)&delta_swing_table_idx_tup_b,
1649                (u8 **)&delta_swing_table_idx_tdown_b);
1650
1651        rtldm->txpower_trackinginit = true;
1652
1653        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1654                 "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1655                 rtldm->swing_idx_cck_base,
1656                 rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1657                 rtldm->default_ofdm_index);
1658
1659        thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1660                /*0x42: RF Reg[15:10] 88E*/
1661                RF_T_METER_8812A, 0xfc00);
1662        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1663                 "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1664                 thermal_value, rtlefuse->eeprom_thermalmeter);
1665        if (!rtldm->txpower_track_control ||
1666            rtlefuse->eeprom_thermalmeter == 0 ||
1667            rtlefuse->eeprom_thermalmeter == 0xFF)
1668                return;
1669
1670        /* 3. Initialize ThermalValues of RFCalibrateInfo*/
1671
1672        if (rtlhal->reloadtxpowerindex)
1673                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1674                         "reload ofdm index for band switch\n");
1675
1676        /*4. Calculate average thermal meter*/
1677        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1678        rtldm->thermalvalue_avg_index++;
1679        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1680                /*Average times =  c.AverageThermalNum*/
1681                rtldm->thermalvalue_avg_index = 0;
1682
1683        for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1684                if (rtldm->thermalvalue_avg[i]) {
1685                        thermal_value_avg += rtldm->thermalvalue_avg[i];
1686                        thermal_value_avg_count++;
1687                }
1688        }
1689        /*Calculate Average ThermalValue after average enough times*/
1690        if (thermal_value_avg_count) {
1691                thermal_value = (u8)(thermal_value_avg /
1692                                thermal_value_avg_count);
1693                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1694                         "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1695                         thermal_value, rtlefuse->eeprom_thermalmeter);
1696        }
1697
1698        /*5. Calculate delta, delta_LCK, delta_IQK.
1699         *"delta" here is used to determine whether
1700         *thermal value changes or not.
1701         */
1702        delta = (thermal_value > rtldm->thermalvalue) ?
1703                (thermal_value - rtldm->thermalvalue) :
1704                (rtldm->thermalvalue - thermal_value);
1705        delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1706                (thermal_value - rtldm->thermalvalue_lck) :
1707                (rtldm->thermalvalue_lck - thermal_value);
1708        delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1709                (thermal_value - rtldm->thermalvalue_iqk) :
1710                (rtldm->thermalvalue_iqk - thermal_value);
1711
1712        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1713                 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1714                 delta, delta_lck, delta_iqk);
1715
1716        /* 6. If necessary, do LCK.
1717         * Delta temperature is equal to or larger than 20 centigrade.
1718         */
1719        if (delta_lck >= IQK_THRESHOLD) {
1720                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1721                         "delta_LCK(%d) >= Threshold_IQK(%d)\n",
1722                         delta_lck, IQK_THRESHOLD);
1723                rtldm->thermalvalue_lck = thermal_value;
1724                rtl8821ae_phy_lc_calibrate(hw);
1725        }
1726
1727        /*7. If necessary, move the index of swing table to adjust Tx power.*/
1728
1729        if (delta > 0 && rtldm->txpower_track_control) {
1730                /* "delta" here is used to record the
1731                 * absolute value of differrence.
1732                 */
1733                delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1734                        (thermal_value - rtlefuse->eeprom_thermalmeter) :
1735                        (rtlefuse->eeprom_thermalmeter - thermal_value);
1736
1737                if (delta >= TXPWR_TRACK_TABLE_SIZE)
1738                        delta = TXPWR_TRACK_TABLE_SIZE - 1;
1739
1740                /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1741
1742                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1743                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1744                                 "delta_swing_table_idx_tup_a[%d] = %d\n",
1745                                 delta, delta_swing_table_idx_tup_a[delta]);
1746                        rtldm->delta_power_index_last[RF90_PATH_A] =
1747                                rtldm->delta_power_index[RF90_PATH_A];
1748                        rtldm->delta_power_index[RF90_PATH_A] =
1749                                delta_swing_table_idx_tup_a[delta];
1750
1751                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1752                                delta_swing_table_idx_tup_a[delta];
1753                        /*Record delta swing for mix mode power tracking*/
1754
1755                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1756                                 "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1757                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1758
1759                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1760                                 "delta_swing_table_idx_tup_b[%d] = %d\n",
1761                                 delta, delta_swing_table_idx_tup_b[delta]);
1762                        rtldm->delta_power_index_last[RF90_PATH_B] =
1763                                rtldm->delta_power_index[RF90_PATH_B];
1764                        rtldm->delta_power_index[RF90_PATH_B] =
1765                                delta_swing_table_idx_tup_b[delta];
1766
1767                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1768                                delta_swing_table_idx_tup_b[delta];
1769                        /*Record delta swing for mix mode power tracking*/
1770
1771                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1772                                 "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1773                                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1774                } else {
1775                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1776                                 "delta_swing_table_idx_tdown_a[%d] = %d\n",
1777                                 delta, delta_swing_table_idx_tdown_a[delta]);
1778
1779                        rtldm->delta_power_index_last[RF90_PATH_A] =
1780                                rtldm->delta_power_index[RF90_PATH_A];
1781                        rtldm->delta_power_index[RF90_PATH_A] =
1782                                -1 * delta_swing_table_idx_tdown_a[delta];
1783
1784                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1785                                -1 * delta_swing_table_idx_tdown_a[delta];
1786                        /* Record delta swing for mix mode power tracking*/
1787                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1788                                 "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1789                                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1790
1791                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1792                                 "deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1793                                 delta, delta_swing_table_idx_tdown_b[delta]);
1794
1795                        rtldm->delta_power_index_last[RF90_PATH_B] =
1796                                rtldm->delta_power_index[RF90_PATH_B];
1797                        rtldm->delta_power_index[RF90_PATH_B] =
1798                                -1 * delta_swing_table_idx_tdown_b[delta];
1799
1800                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1801                                -1 * delta_swing_table_idx_tdown_b[delta];
1802                        /*Record delta swing for mix mode power tracking*/
1803
1804                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1805                                 "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1806                                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1807                }
1808
1809                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1810                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1811                                 "============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1812                                 (p == RF90_PATH_A ? 'A' : 'B'));
1813
1814                        if (rtldm->delta_power_index[p] ==
1815                                rtldm->delta_power_index_last[p])
1816                                /*If Thermal value changes but lookup
1817                                table value still the same*/
1818                                rtldm->power_index_offset[p] = 0;
1819                        else
1820                                rtldm->power_index_offset[p] =
1821                                        rtldm->delta_power_index[p] -
1822                                        rtldm->delta_power_index_last[p];
1823                                /* Power Index Diff between 2
1824                                 * times Power Tracking
1825                                 */
1826                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1827                                 "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1828                                 (p == RF90_PATH_A ? 'A' : 'B'),
1829                                 rtldm->power_index_offset[p],
1830                                 rtldm->delta_power_index[p] ,
1831                                 rtldm->delta_power_index_last[p]);
1832
1833                        rtldm->ofdm_index[p] =
1834                                        rtldm->swing_idx_ofdm_base[p] +
1835                                        rtldm->power_index_offset[p];
1836                        rtldm->cck_index =
1837                                        rtldm->swing_idx_cck_base +
1838                                        rtldm->power_index_offset[p];
1839
1840                        rtldm->swing_idx_cck = rtldm->cck_index;
1841                        rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1842
1843                        /****Print BB Swing Base and Index Offset */
1844
1845                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1846                                 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1847                                 rtldm->swing_idx_cck,
1848                                rtldm->swing_idx_cck_base,
1849                                rtldm->power_index_offset[p]);
1850                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1851                                 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1852                                 rtldm->swing_idx_ofdm[p],
1853                                 (p == RF90_PATH_A ? 'A' : 'B'),
1854                                 rtldm->swing_idx_ofdm_base[p],
1855                                 rtldm->power_index_offset[p]);
1856
1857                        /*7.1 Handle boundary conditions of index.*/
1858
1859                        if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1860                                rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1861                        else if (rtldm->ofdm_index[p] < ofdm_min_index)
1862                                rtldm->ofdm_index[p] = ofdm_min_index;
1863                }
1864                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1865                         "\n\n====================================================================================\n");
1866                if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1867                        rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1868                else if (rtldm->cck_index < 0)
1869                        rtldm->cck_index = 0;
1870        } else {
1871                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1872                         "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1873                         rtldm->txpower_track_control,
1874                         thermal_value,
1875                         rtldm->thermalvalue);
1876
1877                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1878                        rtldm->power_index_offset[p] = 0;
1879        }
1880        /*Print Swing base & current*/
1881        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1882                 "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1883                 rtldm->cck_index, rtldm->swing_idx_cck_base);
1884        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1885                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1886                         "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1887                         rtldm->ofdm_index[p],
1888                         (p == RF90_PATH_A ? 'A' : 'B'),
1889                         rtldm->swing_idx_ofdm_base[p]);
1890        }
1891
1892        if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1893                rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1894                rtldm->txpower_track_control) {
1895                /*7.2 Configure the Swing Table to adjust Tx Power.
1896                 *Always TRUE after Tx Power is adjusted by power tracking.
1897                 *
1898                 *2012/04/23 MH According to Luke's suggestion,
1899                 *we can not write BB digital
1900                 *to increase TX power. Otherwise, EVM will be bad.
1901                 *
1902                 *2012/04/25 MH Add for tx power tracking to set
1903                 *tx power in tx agc for 88E.
1904                 */
1905                if (thermal_value > rtldm->thermalvalue) {
1906                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1907                                 "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1908                                 rtldm->power_index_offset[RF90_PATH_A],
1909                                 delta, thermal_value,
1910                                 rtlefuse->eeprom_thermalmeter,
1911                                 rtldm->thermalvalue);
1912
1913                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1914                                 "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1915                                 rtldm->power_index_offset[RF90_PATH_B],
1916                                 delta, thermal_value,
1917                                 rtlefuse->eeprom_thermalmeter,
1918                                 rtldm->thermalvalue);
1919                } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1920                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1921                                 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1922                                 rtldm->power_index_offset[RF90_PATH_A],
1923                                 delta, thermal_value,
1924                                 rtlefuse->eeprom_thermalmeter,
1925                                 rtldm->thermalvalue);
1926
1927                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1928                                 "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1929                                 rtldm->power_index_offset[RF90_PATH_B],
1930                                 delta, thermal_value,
1931                                 rtlefuse->eeprom_thermalmeter,
1932                                 rtldm->thermalvalue);
1933                }
1934
1935                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1936                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1937                                 "Temperature(%d) higher than PG value(%d)\n",
1938                                 thermal_value, rtlefuse->eeprom_thermalmeter);
1939
1940                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1941                                 "**********Enter POWER Tracking MIX_MODE**********\n");
1942                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1943                                rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1944                                                                 p, 0);
1945                } else {
1946                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1947                                 "Temperature(%d) lower than PG value(%d)\n",
1948                                 thermal_value, rtlefuse->eeprom_thermalmeter);
1949
1950                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1951                                 "**********Enter POWER Tracking MIX_MODE**********\n");
1952                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1953                                rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1954                                                                 p, index_for_channel);
1955                }
1956                /*Record last time Power Tracking result as base.*/
1957                rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1958                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1959                                rtldm->swing_idx_ofdm_base[p] =
1960                                        rtldm->swing_idx_ofdm[p];
1961
1962                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1963                                 "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1964                                 rtldm->thermalvalue, thermal_value);
1965                /*Record last Power Tracking Thermal Value*/
1966                rtldm->thermalvalue = thermal_value;
1967        }
1968        /*Delta temperature is equal to or larger than
1969        20 centigrade (When threshold is 8).*/
1970        if (delta_iqk >= IQK_THRESHOLD)
1971                rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1972
1973        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1974                 "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
1975}
1976
1977static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a,
1978                                            u8 **down_a, u8 **up_b, u8 **down_b)
1979{
1980        struct rtl_priv *rtlpriv = rtl_priv(hw);
1981        struct rtl_phy *rtlphy = &rtlpriv->phy;
1982        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1983        u8 channel = rtlphy->current_channel;
1984        u8 rate = rtldm->tx_rate;
1985
1986        if (1 <= channel && channel <= 14) {
1987                if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1988                        *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1989                        *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1990                        *up_b = rtl8821ae_delta_swing_table_idx_24gcckb_p;
1991                        *down_b = rtl8821ae_delta_swing_table_idx_24gcckb_n;
1992                } else {
1993                        *up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1994                        *down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1995                        *up_b = rtl8821ae_delta_swing_table_idx_24gb_p;
1996                        *down_b = rtl8821ae_delta_swing_table_idx_24gb_n;
1997                }
1998        } else if (36 <= channel && channel <= 64) {
1999                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
2000                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
2001                *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[0];
2002                *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[0];
2003        } else if (100 <= channel && channel <= 140) {
2004                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
2005                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
2006                *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[1];
2007                *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[1];
2008        } else if (149 <= channel && channel <= 173) {
2009                *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
2010                *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
2011                *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[2];
2012                *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[2];
2013        } else {
2014            *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
2015            *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
2016            *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
2017            *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
2018        }
2019        return;
2020}
2021
2022/*-----------------------------------------------------------------------------
2023 * Function:    odm_TxPwrTrackSetPwr88E()
2024 *
2025 * Overview:    88E change all channel tx power accordign to flag.
2026 *                              OFDM & CCK are all different.
2027 *
2028 * Input:               NONE
2029 *
2030 * Output:              NONE
2031 *
2032 * Return:              NONE
2033 *
2034 * Revised History:
2035 *      When            Who             Remark
2036 *      04/23/2012      MHC             Create Version 0.
2037 *
2038 *---------------------------------------------------------------------------
2039 */
2040void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
2041                                      enum pwr_track_control_method method,
2042                                      u8 rf_path, u8 channel_mapped_index)
2043{
2044        struct rtl_priv *rtlpriv = rtl_priv(hw);
2045        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2046        struct rtl_phy *rtlphy = &rtlpriv->phy;
2047        u32 final_swing_idx[1];
2048        u8 pwr_tracking_limit = 26; /*+1.0dB*/
2049        u8 tx_rate = 0xFF;
2050        char final_ofdm_swing_index = 0;
2051
2052        if (rtldm->tx_rate != 0xFF)
2053                tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
2054
2055        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
2056
2057        if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
2058                /*CCK*/
2059                if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
2060                        pwr_tracking_limit = 32; /*+4dB*/
2061                /*OFDM*/
2062                else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
2063                        pwr_tracking_limit = 30; /*+3dB*/
2064                else if (tx_rate == MGN_54M)
2065                        pwr_tracking_limit = 28; /*+2dB*/
2066                /*HT*/
2067                /*QPSK/BPSK*/
2068                else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
2069                        pwr_tracking_limit = 34; /*+5dB*/
2070                /*16QAM*/
2071                else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
2072                        pwr_tracking_limit = 30; /*+3dB*/
2073                /*64QAM*/
2074                else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
2075                        pwr_tracking_limit = 28; /*+2dB*/
2076                /*2 VHT*/
2077                /*QPSK/BPSK*/
2078                else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
2079                        (tx_rate <= MGN_VHT1SS_MCS2))
2080                        pwr_tracking_limit = 34; /*+5dB*/
2081                /*16QAM*/
2082                else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
2083                        (tx_rate <= MGN_VHT1SS_MCS4))
2084                        pwr_tracking_limit = 30; /*+3dB*/
2085                /*64QAM*/
2086                else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
2087                        (tx_rate <= MGN_VHT1SS_MCS6))
2088                        pwr_tracking_limit = 28; /*+2dB*/
2089                else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
2090                        pwr_tracking_limit = 26; /*+1dB*/
2091                else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
2092                        pwr_tracking_limit = 24; /*+0dB*/
2093                else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
2094                        pwr_tracking_limit = 22; /*-1dB*/
2095                else
2096                        pwr_tracking_limit = 24;
2097        }
2098        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2099                 "TxRate=0x%x, PwrTrackingLimit=%d\n",
2100                 tx_rate, pwr_tracking_limit);
2101
2102        if (method == BBSWING) {
2103                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2104                         "===>%s\n", __func__);
2105                if (rf_path == RF90_PATH_A) {
2106                        final_swing_idx[RF90_PATH_A] =
2107                                (rtldm->ofdm_index[RF90_PATH_A] >
2108                                pwr_tracking_limit) ?
2109                                pwr_tracking_limit :
2110                                rtldm->ofdm_index[RF90_PATH_A];
2111                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2112                                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
2113                                 rtldm->ofdm_index[RF90_PATH_A],
2114                                 final_swing_idx[RF90_PATH_A]);
2115
2116                        rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2117                                txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
2118                }
2119        } else if (method == MIX_MODE) {
2120                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2121                         "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
2122                         rtldm->default_ofdm_index,
2123                         rtldm->absolute_ofdm_swing_idx[rf_path],
2124                         rf_path);
2125
2126                final_ofdm_swing_index =
2127                        rtldm->default_ofdm_index +
2128                        rtldm->absolute_ofdm_swing_idx[rf_path];
2129                /*BBSwing higher then Limit*/
2130                if (rf_path == RF90_PATH_A) {
2131                        if (final_ofdm_swing_index > pwr_tracking_limit) {
2132                                rtldm->remnant_cck_idx =
2133                                        final_ofdm_swing_index -
2134                                        pwr_tracking_limit;
2135                                /* CCK Follow the same compensate value as Path A*/
2136                                rtldm->remnant_ofdm_swing_idx[rf_path] =
2137                                        final_ofdm_swing_index -
2138                                        pwr_tracking_limit;
2139
2140                                rtl_set_bbreg(hw, RA_TXSCALE,
2141                                        0xFFE00000,
2142                                        txscaling_tbl[pwr_tracking_limit]);
2143
2144                                rtldm->modify_txagc_flag_path_a = true;
2145
2146                                /*Set TxAGC Page C{};*/
2147                                rtl8821ae_phy_set_txpower_level_by_path(hw,
2148                                        rtlphy->current_channel,
2149                                        RF90_PATH_A);
2150
2151                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2152                                        " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
2153                                         pwr_tracking_limit,
2154                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
2155                        } else if (final_ofdm_swing_index < 0) {
2156                                rtldm->remnant_cck_idx = final_ofdm_swing_index;
2157                                /* CCK Follow the same compensate value as Path A*/
2158                                rtldm->remnant_ofdm_swing_idx[rf_path] =
2159                                        final_ofdm_swing_index;
2160
2161                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2162                                        txscaling_tbl[0]);
2163
2164                                rtldm->modify_txagc_flag_path_a = true;
2165
2166                                /*Set TxAGC Page C{};*/
2167                                rtl8821ae_phy_set_txpower_level_by_path(hw,
2168                                        rtlphy->current_channel, RF90_PATH_A);
2169
2170                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2171                                         "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
2172                                         rtldm->remnant_ofdm_swing_idx[rf_path]);
2173                        } else {
2174                                rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2175                                        txscaling_tbl[(u8)final_ofdm_swing_index]);
2176
2177                                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2178                                         "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
2179                                         final_ofdm_swing_index);
2180                                /*If TxAGC has changed, reset TxAGC again*/
2181                                if (rtldm->modify_txagc_flag_path_a) {
2182                                        rtldm->remnant_cck_idx = 0;
2183                                        rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
2184
2185                                        /*Set TxAGC Page C{};*/
2186                                        rtl8821ae_phy_set_txpower_level_by_path(hw,
2187                                                rtlphy->current_channel, RF90_PATH_A);
2188
2189                                        rtldm->modify_txagc_flag_path_a = false;
2190
2191                                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
2192                                                 DBG_LOUD,
2193                                                 "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2194                                }
2195                        }
2196                }
2197        } else {
2198                return;
2199        }
2200}
2201
2202void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2203        struct ieee80211_hw *hw)
2204{
2205        struct rtl_priv *rtlpriv = rtl_priv(hw);
2206        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2207        struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2208        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2209        struct rtl_phy *rtlphy = &rtlpriv->phy;
2210
2211        u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2212        u8 thermal_value_avg_count = 0;
2213        u32 thermal_value_avg = 0;
2214
2215        u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2216        /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2217        u8 index_for_channel = 0;
2218
2219        /* 1. The following TWO tables decide the final
2220         * index of OFDM/CCK swing table.
2221         */
2222        u8 *delta_swing_table_idx_tup_a;
2223        u8 *delta_swing_table_idx_tdown_a;
2224        u8 *delta_swing_table_idx_tup_b;
2225        u8 *delta_swing_table_idx_tdown_b;
2226
2227        /*2. Initilization ( 7 steps in total )*/
2228        rtl8821ae_get_delta_swing_table(hw, (u8 **)&delta_swing_table_idx_tup_a,
2229                                        (u8 **)&delta_swing_table_idx_tdown_a,
2230                                        (u8 **)&delta_swing_table_idx_tup_b,
2231                                        (u8 **)&delta_swing_table_idx_tdown_b);
2232
2233        rtldm->txpower_trackinginit = true;
2234
2235        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2236                 "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2237                 __func__,
2238                 rtldm->swing_idx_cck_base,
2239                 rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2240                 rtldm->default_ofdm_index);
2241        /*0x42: RF Reg[15:10] 88E*/
2242        thermal_value = (u8)rtl_get_rfreg(hw,
2243                RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2244        if (!rtldm->txpower_track_control ||
2245                rtlefuse->eeprom_thermalmeter == 0 ||
2246                rtlefuse->eeprom_thermalmeter == 0xFF)
2247                return;
2248
2249        /* 3. Initialize ThermalValues of RFCalibrateInfo*/
2250
2251        if (rtlhal->reloadtxpowerindex) {
2252                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2253                         "reload ofdm index for band switch\n");
2254        }
2255
2256        /*4. Calculate average thermal meter*/
2257        rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2258        rtldm->thermalvalue_avg_index++;
2259        if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2260                /*Average times =  c.AverageThermalNum*/
2261                rtldm->thermalvalue_avg_index = 0;
2262
2263        for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2264                if (rtldm->thermalvalue_avg[i]) {
2265                        thermal_value_avg += rtldm->thermalvalue_avg[i];
2266                        thermal_value_avg_count++;
2267                }
2268        }
2269        /*Calculate Average ThermalValue after average enough times*/
2270        if (thermal_value_avg_count) {
2271                thermal_value = (u8)(thermal_value_avg /
2272                                thermal_value_avg_count);
2273                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2274                         "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2275                         thermal_value, rtlefuse->eeprom_thermalmeter);
2276        }
2277
2278        /*5. Calculate delta, delta_LCK, delta_IQK.
2279         *"delta" here is used to determine whether
2280         * thermal value changes or not.
2281         */
2282        delta = (thermal_value > rtldm->thermalvalue) ?
2283                (thermal_value - rtldm->thermalvalue) :
2284                (rtldm->thermalvalue - thermal_value);
2285        delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2286                (thermal_value - rtldm->thermalvalue_lck) :
2287                (rtldm->thermalvalue_lck - thermal_value);
2288        delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2289                (thermal_value - rtldm->thermalvalue_iqk) :
2290                (rtldm->thermalvalue_iqk - thermal_value);
2291
2292        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2293                 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2294                 delta, delta_lck, delta_iqk);
2295
2296        /* 6. If necessary, do LCK.     */
2297        /*Delta temperature is equal to or larger than 20 centigrade.*/
2298        if (delta_lck >= IQK_THRESHOLD) {
2299                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2300                         "delta_LCK(%d) >= Threshold_IQK(%d)\n",
2301                         delta_lck, IQK_THRESHOLD);
2302                rtldm->thermalvalue_lck = thermal_value;
2303                rtl8821ae_phy_lc_calibrate(hw);
2304        }
2305
2306        /*7. If necessary, move the index of swing table to adjust Tx power.*/
2307
2308        if (delta > 0 && rtldm->txpower_track_control) {
2309                /*"delta" here is used to record the
2310                 * absolute value of differrence.
2311                 */
2312                delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2313                        (thermal_value - rtlefuse->eeprom_thermalmeter) :
2314                        (rtlefuse->eeprom_thermalmeter - thermal_value);
2315
2316                if (delta >= TXSCALE_TABLE_SIZE)
2317                        delta = TXSCALE_TABLE_SIZE - 1;
2318
2319                /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2320
2321                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2322                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2323                                 "delta_swing_table_idx_tup_a[%d] = %d\n",
2324                                 delta, delta_swing_table_idx_tup_a[delta]);
2325                        rtldm->delta_power_index_last[RF90_PATH_A] =
2326                                rtldm->delta_power_index[RF90_PATH_A];
2327                        rtldm->delta_power_index[RF90_PATH_A] =
2328                                delta_swing_table_idx_tup_a[delta];
2329
2330                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2331                                delta_swing_table_idx_tup_a[delta];
2332                        /*Record delta swing for mix mode power tracking*/
2333
2334                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2335                                 "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2336                                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2337                } else {
2338                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2339                                 "delta_swing_table_idx_tdown_a[%d] = %d\n",
2340                                 delta, delta_swing_table_idx_tdown_a[delta]);
2341
2342                        rtldm->delta_power_index_last[RF90_PATH_A] =
2343                                rtldm->delta_power_index[RF90_PATH_A];
2344                        rtldm->delta_power_index[RF90_PATH_A] =
2345                                -1 * delta_swing_table_idx_tdown_a[delta];
2346
2347                        rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2348                                -1 * delta_swing_table_idx_tdown_a[delta];
2349                        /* Record delta swing for mix mode power tracking*/
2350                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2351                                 "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2352                                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2353                }
2354
2355                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2356                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2357                                 "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2358                                 (p == RF90_PATH_A ? 'A' : 'B'));
2359                        /*If Thermal value changes but lookup table value
2360                         * still the same
2361                         */
2362                        if (rtldm->delta_power_index[p] ==
2363                                rtldm->delta_power_index_last[p])
2364
2365                                rtldm->power_index_offset[p] = 0;
2366                        else
2367                                rtldm->power_index_offset[p] =
2368                                        rtldm->delta_power_index[p] -
2369                                        rtldm->delta_power_index_last[p];
2370                        /*Power Index Diff between 2 times Power Tracking*/
2371
2372                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2373                                 "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2374                                 (p == RF90_PATH_A ? 'A' : 'B'),
2375                                rtldm->power_index_offset[p],
2376                                rtldm->delta_power_index[p] ,
2377                                rtldm->delta_power_index_last[p]);
2378
2379                        rtldm->ofdm_index[p] =
2380                                        rtldm->swing_idx_ofdm_base[p] +
2381                                        rtldm->power_index_offset[p];
2382                        rtldm->cck_index =
2383                                        rtldm->swing_idx_cck_base +
2384                                        rtldm->power_index_offset[p];
2385
2386                        rtldm->swing_idx_cck = rtldm->cck_index;
2387                        rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2388
2389                        /*********Print BB Swing Base and Index Offset********/
2390
2391                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2392                                 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2393                                 rtldm->swing_idx_cck,
2394                                 rtldm->swing_idx_cck_base,
2395                                 rtldm->power_index_offset[p]);
2396                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2397                                 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2398                                 rtldm->swing_idx_ofdm[p],
2399                                 (p == RF90_PATH_A ? 'A' : 'B'),
2400                                 rtldm->swing_idx_ofdm_base[p],
2401                                 rtldm->power_index_offset[p]);
2402
2403                        /*7.1 Handle boundary conditions of index.*/
2404
2405                        if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2406                                rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2407                        else if (rtldm->ofdm_index[p] < ofdm_min_index)
2408                                rtldm->ofdm_index[p] = ofdm_min_index;
2409                }
2410                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2411                         "\n\n========================================================================================================\n");
2412                if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2413                        rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2414                else if (rtldm->cck_index < 0)
2415                        rtldm->cck_index = 0;
2416        } else {
2417                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2418                         "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2419                         rtldm->txpower_track_control,
2420                         thermal_value,
2421                         rtldm->thermalvalue);
2422
2423                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2424                        rtldm->power_index_offset[p] = 0;
2425        }
2426        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2427                 "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2428                 /*Print Swing base & current*/
2429                rtldm->cck_index, rtldm->swing_idx_cck_base);
2430        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2431                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2432                         "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2433                         rtldm->ofdm_index[p],
2434                         (p == RF90_PATH_A ? 'A' : 'B'),
2435                         rtldm->swing_idx_ofdm_base[p]);
2436        }
2437
2438        if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2439                rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2440                rtldm->txpower_track_control) {
2441                /*7.2 Configure the Swing Table to adjust Tx Power.*/
2442                /*Always TRUE after Tx Power is adjusted by power tracking.*/
2443                /*
2444                 *  2012/04/23 MH According to Luke's suggestion,
2445                 *  we can not write BB digital
2446                 *  to increase TX power. Otherwise, EVM will be bad.
2447                 *
2448                 *  2012/04/25 MH Add for tx power tracking to
2449                 *  set tx power in tx agc for 88E.
2450                 */
2451                if (thermal_value > rtldm->thermalvalue) {
2452                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2453                                 "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2454                                 rtldm->power_index_offset[RF90_PATH_A],
2455                                 delta, thermal_value,
2456                                 rtlefuse->eeprom_thermalmeter,
2457                                 rtldm->thermalvalue);
2458                } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2459                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2460                                 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2461                                 rtldm->power_index_offset[RF90_PATH_A],
2462                                 delta, thermal_value,
2463                                 rtlefuse->eeprom_thermalmeter,
2464                                 rtldm->thermalvalue);
2465                }
2466
2467                if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2468                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2469                                 "Temperature(%d) higher than PG value(%d)\n",
2470                                 thermal_value, rtlefuse->eeprom_thermalmeter);
2471
2472                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2473                                 "****Enter POWER Tracking MIX_MODE****\n");
2474                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2475                                        rtl8821ae_dm_txpwr_track_set_pwr(hw,
2476                                                MIX_MODE, p, index_for_channel);
2477                } else {
2478                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2479                                 "Temperature(%d) lower than PG value(%d)\n",
2480                                 thermal_value, rtlefuse->eeprom_thermalmeter);
2481
2482                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2483                                 "*****Enter POWER Tracking MIX_MODE*****\n");
2484                        for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2485                                rtl8812ae_dm_txpwr_track_set_pwr(hw,
2486                                        MIX_MODE, p, index_for_channel);
2487                }
2488                /*Record last time Power Tracking result as base.*/
2489                rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2490                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2491                        rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2492
2493                        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2494                                 "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2495                                 rtldm->thermalvalue, thermal_value);
2496                /*Record last Power Tracking Thermal Value*/
2497                rtldm->thermalvalue = thermal_value;
2498        }
2499        /* Delta temperature is equal to or larger than
2500         * 20 centigrade (When threshold is 8).
2501         */
2502        if (delta_iqk >= IQK_THRESHOLD) {
2503                if (!rtlphy->lck_inprogress) {
2504                        spin_lock(&rtlpriv->locks.iqk_lock);
2505                        rtlphy->lck_inprogress = true;
2506                        spin_unlock(&rtlpriv->locks.iqk_lock);
2507
2508                        rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2509
2510                        spin_lock(&rtlpriv->locks.iqk_lock);
2511                        rtlphy->lck_inprogress = false;
2512                        spin_unlock(&rtlpriv->locks.iqk_lock);
2513                }
2514        }
2515
2516        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2517}
2518
2519void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2520{
2521        struct rtl_priv *rtlpriv = rtl_priv(hw);
2522        static u8 tm_trigger;
2523
2524        if (!tm_trigger) {
2525                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2526                              0x03);
2527                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2528                         "Trigger 8821ae Thermal Meter!!\n");
2529                tm_trigger = 1;
2530                return;
2531        } else {
2532                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2533                         "Schedule TxPowerTracking !!\n");
2534
2535                rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2536                tm_trigger = 0;
2537        }
2538}
2539
2540static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2541{
2542        struct rtl_priv *rtlpriv = rtl_priv(hw);
2543        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2544        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2545        struct rate_adaptive *p_ra = &rtlpriv->ra;
2546        u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2547        u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2548        u8 go_up_gap = 5;
2549        struct ieee80211_sta *sta = NULL;
2550
2551        if (is_hal_stop(rtlhal)) {
2552                RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2553                         "driver is going to unload\n");
2554                return;
2555        }
2556
2557        if (!rtlpriv->dm.useramask) {
2558                RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2559                         "driver does not control rate adaptive mask\n");
2560                return;
2561        }
2562
2563        if (mac->link_state == MAC80211_LINKED &&
2564                mac->opmode == NL80211_IFTYPE_STATION) {
2565                switch (p_ra->pre_ratr_state) {
2566                case DM_RATR_STA_MIDDLE:
2567                        high_rssithresh_for_ra += go_up_gap;
2568                        break;
2569                case DM_RATR_STA_LOW:
2570                        high_rssithresh_for_ra += go_up_gap;
2571                        low_rssithresh_for_ra += go_up_gap;
2572                        break;
2573                default:
2574                        break;
2575                }
2576
2577                if (rtlpriv->dm.undec_sm_pwdb >
2578                    (long)high_rssithresh_for_ra)
2579                        p_ra->ratr_state = DM_RATR_STA_HIGH;
2580                else if (rtlpriv->dm.undec_sm_pwdb >
2581                         (long)low_rssithresh_for_ra)
2582                        p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2583                else
2584                        p_ra->ratr_state = DM_RATR_STA_LOW;
2585
2586                if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2587                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2588                                 "RSSI = %ld\n",
2589                                  rtlpriv->dm.undec_sm_pwdb);
2590                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2591                                 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
2592                        RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2593                                 "PreState = %d, CurState = %d\n",
2594                                  p_ra->pre_ratr_state, p_ra->ratr_state);
2595
2596                        rcu_read_lock();
2597                        sta = rtl_find_sta(hw, mac->bssid);
2598                        if (sta)
2599                                rtlpriv->cfg->ops->update_rate_tbl(hw,
2600                                                sta, p_ra->ratr_state);
2601                        rcu_read_unlock();
2602
2603                        p_ra->pre_ratr_state = p_ra->ratr_state;
2604                }
2605        }
2606}
2607
2608static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2609{
2610        struct rtl_priv *rtlpriv = rtl_priv(hw);
2611        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2612        struct rtl_mac *mac = &rtlpriv->mac80211;
2613        static u8 stage;
2614        u8 cur_stage = 0;
2615        u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2616
2617        if (mac->link_state < MAC80211_LINKED)
2618                cur_stage = 0;
2619        else if (dm_digtable->rssi_val_min < 25)
2620                cur_stage = 1;
2621        else if (dm_digtable->rssi_val_min > 30)
2622                cur_stage = 3;
2623        else
2624                cur_stage = 2;
2625
2626        if (cur_stage != stage) {
2627                if (cur_stage == 1) {
2628                        basic_rate &= (!(basic_rate ^ mac->basic_rates));
2629                        rtlpriv->cfg->ops->set_hw_reg(hw,
2630                                HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2631                } else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2632                        rtlpriv->cfg->ops->set_hw_reg(hw,
2633                                HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2634                }
2635        }
2636        stage = cur_stage;
2637}
2638
2639static void rtl8821ae_dm_edca_choose_traffic_idx(
2640        struct ieee80211_hw *hw, u64 cur_tx_bytes,
2641        u64 cur_rx_bytes, bool b_bias_on_rx,
2642        bool *pb_is_cur_rdl_state)
2643{
2644        struct rtl_priv *rtlpriv = rtl_priv(hw);
2645
2646        if (b_bias_on_rx) {
2647                if (cur_tx_bytes > (cur_rx_bytes*4)) {
2648                        *pb_is_cur_rdl_state = false;
2649                        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2650                                 "Uplink Traffic\n ");
2651                } else {
2652                        *pb_is_cur_rdl_state = true;
2653                        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2654                                 "Balance Traffic\n");
2655                }
2656        } else {
2657                if (cur_rx_bytes > (cur_tx_bytes*4)) {
2658                        *pb_is_cur_rdl_state = true;
2659                        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2660                                 "Downlink      Traffic\n");
2661                } else {
2662                        *pb_is_cur_rdl_state = false;
2663                        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2664                                 "Balance Traffic\n");
2665                }
2666        }
2667        return;
2668}
2669
2670static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2671{
2672        struct rtl_priv *rtlpriv = rtl_priv(hw);
2673        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2674        struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2675
2676        /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2677        u64 cur_tx_ok_cnt = 0;
2678        u64 cur_rx_ok_cnt = 0;
2679        u32 edca_be_ul = 0x5ea42b;
2680        u32 edca_be_dl = 0x5ea42b;
2681        u32 edca_be = 0x5ea42b;
2682        u8 iot_peer = 0;
2683        bool *pb_is_cur_rdl_state = NULL;
2684        bool b_last_is_cur_rdl_state = false;
2685        bool b_bias_on_rx = false;
2686        bool b_edca_turbo_on = false;
2687
2688        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2689                 "rtl8821ae_dm_check_edca_turbo=====>");
2690        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2691                 "Orginial BE PARAM: 0x%x\n",
2692                 rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2693
2694        if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2695                rtlpriv->dm.is_any_nonbepkts = true;
2696        rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2697
2698        /*===============================
2699         * list paramter for different platform
2700         *===============================
2701         */
2702        b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate;
2703        pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2704
2705        cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2706        cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2707
2708        rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2709        rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2710
2711        iot_peer = rtlpriv->mac80211.vendor;
2712        b_bias_on_rx = false;
2713        b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2714                           (!rtlpriv->dm.disable_framebursting)) ?
2715                           true : false;
2716
2717        if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2718                if ((iot_peer == PEER_CISCO) &&
2719                        (mac->mode == WIRELESS_MODE_N_24G)) {
2720                        edca_be_dl = edca_setting_dl[iot_peer];
2721                        edca_be_ul = edca_setting_ul[iot_peer];
2722                }
2723        }
2724
2725        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2726                 "bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2727                 rtlpriv->dm.is_any_nonbepkts,
2728                 rtlpriv->dm.disable_framebursting);
2729
2730        RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2731                 "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2732                 b_edca_turbo_on, b_bias_on_rx);
2733
2734        if (b_edca_turbo_on) {
2735                RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2736                         "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2737                RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2738                         "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2739                if (b_bias_on_rx)
2740                        rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2741                                cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2742                else
2743                        rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2744                                cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2745
2746                edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2747
2748                rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2749
2750                RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2751                         "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2752
2753                rtlpriv->dm.current_turbo_edca = true;
2754
2755                RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2756                         "EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2757                         edca_be_dl, edca_be_ul, edca_be);
2758        } else {
2759                if (rtlpriv->dm.current_turbo_edca) {
2760                        u8 tmp = AC0_BE;
2761                        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2762                                                      (u8 *)(&tmp));
2763                }
2764                rtlpriv->dm.current_turbo_edca = false;
2765        }
2766
2767        rtlpriv->dm.is_any_nonbepkts = false;
2768        rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2769        rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2770}
2771
2772static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2773{
2774        struct rtl_priv *rtlpriv = rtl_priv(hw);
2775        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2776        u8 cur_cck_cca_thresh;
2777
2778        if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2779                if (dm_digtable->rssi_val_min > 25) {
2780                        cur_cck_cca_thresh = 0xcd;
2781                } else if ((dm_digtable->rssi_val_min <= 25) &&
2782                           (dm_digtable->rssi_val_min > 10)) {
2783                        cur_cck_cca_thresh = 0x83;
2784                } else {
2785                        if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2786                                cur_cck_cca_thresh = 0x83;
2787                        else
2788                                cur_cck_cca_thresh = 0x40;
2789                }
2790        } else {
2791                if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2792                        cur_cck_cca_thresh = 0x83;
2793                else
2794                        cur_cck_cca_thresh = 0x40;
2795        }
2796
2797        if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2798                rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2799                               cur_cck_cca_thresh);
2800
2801        dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2802        dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2803        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
2804                 "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2805}
2806
2807static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2808{
2809        struct rtl_priv *rtlpriv = rtl_priv(hw);
2810        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2811        u8 crystal_cap;
2812        u32 packet_count;
2813        int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2814        int cfo_ave_diff;
2815
2816        if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2817                /*1.Enable ATC*/
2818                if (rtldm->atc_status == ATC_STATUS_OFF) {
2819                        rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2820                        rtldm->atc_status = ATC_STATUS_ON;
2821                }
2822
2823                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2824                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2825                         "atc_status = %d\n", rtldm->atc_status);
2826
2827                if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2828                        rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2829                        crystal_cap = rtldm->crystal_cap & 0x3f;
2830                        crystal_cap = crystal_cap & 0x3f;
2831                        if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2832                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2833                                              0x7ff80000, (crystal_cap |
2834                                              (crystal_cap << 6)));
2835                        else
2836                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2837                                              0xfff000, (crystal_cap |
2838                                              (crystal_cap << 6)));
2839                }
2840                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2841                         rtldm->crystal_cap);
2842        } else{
2843                /*1. Calculate CFO for path-A & path-B*/
2844                cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2845                cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2846                packet_count = rtldm->packet_count;
2847
2848                /*2.No new packet*/
2849                if (packet_count == rtldm->packet_count_pre) {
2850                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2851                                 "packet counter doesn't change\n");
2852                        return;
2853                }
2854
2855                rtldm->packet_count_pre = packet_count;
2856                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2857                         "packet counter = %d\n",
2858                         rtldm->packet_count);
2859
2860                /*3.Average CFO*/
2861                if (rtlpriv->phy.rf_type == RF_1T1R)
2862                        cfo_ave = cfo_khz_a;
2863                else
2864                        cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2865
2866                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2867                         "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2868                         cfo_khz_a, cfo_khz_b, cfo_ave);
2869
2870                /*4.Avoid abnormal large CFO*/
2871                cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2872                                                (rtldm->cfo_ave_pre - cfo_ave) :
2873                                                (cfo_ave - rtldm->cfo_ave_pre);
2874
2875                if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
2876                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2877                                 "first large CFO hit\n");
2878                        rtldm->large_cfo_hit = 1;
2879                        return;
2880                } else
2881                        rtldm->large_cfo_hit = 0;
2882
2883                rtldm->cfo_ave_pre = cfo_ave;
2884
2885                /*CFO tracking by adjusting Xtal cap.*/
2886
2887                /*1.Dynamic Xtal threshold*/
2888                if (cfo_ave >= -rtldm->cfo_threshold &&
2889                        cfo_ave <= rtldm->cfo_threshold &&
2890                        rtldm->is_freeze == 0) {
2891                        if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2892                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2893                                rtldm->is_freeze = 1;
2894                        } else {
2895                                rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2896                        }
2897                }
2898                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2899                         "Dynamic threshold = %d\n",
2900                         rtldm->cfo_threshold);
2901
2902                /* 2.Calculate Xtal offset*/
2903                if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2904                        adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2905                else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2906                         rtlpriv->dm.crystal_cap > 0)
2907                        adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2908                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2909                         "Crystal cap = 0x%x, Crystal cap offset = %d\n",
2910                         rtldm->crystal_cap, adjust_xtal);
2911
2912                /*3.Adjudt Crystal Cap.*/
2913                if (adjust_xtal != 0) {
2914                        rtldm->is_freeze = 0;
2915                        rtldm->crystal_cap += adjust_xtal;
2916
2917                        if (rtldm->crystal_cap > 0x3f)
2918                                rtldm->crystal_cap = 0x3f;
2919                        else if (rtldm->crystal_cap < 0)
2920                                rtldm->crystal_cap = 0;
2921
2922                        crystal_cap = rtldm->crystal_cap & 0x3f;
2923                        crystal_cap = crystal_cap & 0x3f;
2924                        if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2925                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2926                                              0x7ff80000, (crystal_cap |
2927                                              (crystal_cap << 6)));
2928                        else
2929                                rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2930                                              0xfff000, (crystal_cap |
2931                                              (crystal_cap << 6)));
2932                        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2933                                 "New crystal cap = 0x%x\n",
2934                                 rtldm->crystal_cap);
2935                }
2936        }
2937}
2938
2939void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2940{
2941        struct rtl_priv *rtlpriv = rtl_priv(hw);
2942        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2943        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2944        bool fw_current_inpsmode = false;
2945        bool fw_ps_awake = true;
2946
2947        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2948                                      (u8 *)(&fw_current_inpsmode));
2949
2950        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2951                                      (u8 *)(&fw_ps_awake));
2952
2953        if (ppsc->p2p_ps_info.p2p_ps_mode)
2954                fw_ps_awake = false;
2955
2956        if ((ppsc->rfpwr_state == ERFON) &&
2957            ((!fw_current_inpsmode) && fw_ps_awake) &&
2958            (!ppsc->rfchange_inprogress)) {
2959                rtl8821ae_dm_common_info_self_update(hw);
2960                rtl8821ae_dm_false_alarm_counter_statistics(hw);
2961                rtl8821ae_dm_check_rssi_monitor(hw);
2962                rtl8821ae_dm_dig(hw);
2963                rtl8821ae_dm_cck_packet_detection_thresh(hw);
2964                rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2965                rtl8821ae_dm_refresh_basic_rate_mask(hw);
2966                rtl8821ae_dm_check_edca_turbo(hw);
2967                rtl8821ae_dm_dynamic_atc_switch(hw);
2968                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2969                        rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2970                else
2971                        rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2972                rtl8821ae_dm_iq_calibrate(hw);
2973        }
2974
2975        rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2976        RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2977}
2978
2979void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2980                                        u8 *pdesc, u32 mac_id)
2981{
2982        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2983        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2984        struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2985        struct fast_ant_training *pfat_table = &rtldm->fat_table;
2986
2987        if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2988                return;
2989
2990        if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2991                SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]);
2992}
2993