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