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