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