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_txokcnt = 0, cur_rxokcnt = 0; 659 static u64 last_txokcnt = 0, last_rxokcnt; 660 661 cur_txokcnt = rtlpriv->stats.txbytesunicast - last_txokcnt; 662 cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt; 663 last_txokcnt = rtlpriv->stats.txbytesunicast; 664 last_rxokcnt = rtlpriv->stats.rxbytesunicast; 665 if (cur_rxokcnt > (last_txokcnt * 6)) 666 h2c_parameter[3] = 0x01; 667 else 668 h2c_parameter[3] = 0x00; 669 670 /* AP & ADHOC & MESH */ 671 if (mac->opmode == NL80211_IFTYPE_AP || 672 mac->opmode == NL80211_IFTYPE_ADHOC || 673 mac->opmode == NL80211_IFTYPE_MESH_POINT) { 674 spin_lock_bh(&rtlpriv->locks.entry_list_lock); 675 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { 676 if (drv_priv->rssi_stat.undec_sm_pwdb < 677 tmp_entry_min_pwdb) 678 tmp_entry_min_pwdb = 679 drv_priv->rssi_stat.undec_sm_pwdb; 680 if (drv_priv->rssi_stat.undec_sm_pwdb > 681 tmp_entry_max_pwdb) 682 tmp_entry_max_pwdb = 683 drv_priv->rssi_stat.undec_sm_pwdb; 684 } 685 spin_unlock_bh(&rtlpriv->locks.entry_list_lock); 686 687 /* If associated entry is found */ 688 if (tmp_entry_max_pwdb != 0) { 689 rtlpriv->dm.entry_max_undec_sm_pwdb = 690 tmp_entry_max_pwdb; 691 RTPRINT(rtlpriv, FDM, DM_PWDB, 692 "EntryMaxPWDB = 0x%lx(%ld)\n", 693 tmp_entry_max_pwdb, tmp_entry_max_pwdb); 694 } else { 695 rtlpriv->dm.entry_max_undec_sm_pwdb = 0; 696 } 697 /* If associated entry is found */ 698 if (tmp_entry_min_pwdb != 0xff) { 699 rtlpriv->dm.entry_min_undec_sm_pwdb = 700 tmp_entry_min_pwdb; 701 RTPRINT(rtlpriv, FDM, DM_PWDB, 702 "EntryMinPWDB = 0x%lx(%ld)\n", 703 tmp_entry_min_pwdb, tmp_entry_min_pwdb); 704 } else { 705 rtlpriv->dm.entry_min_undec_sm_pwdb = 0; 706 } 707 } 708 /* Indicate Rx signal strength to FW. */ 709 if (rtlpriv->dm.useramask) { 710 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { 711 if (mac->mode == WIRELESS_MODE_AC_24G || 712 mac->mode == WIRELESS_MODE_AC_5G || 713 mac->mode == WIRELESS_MODE_AC_ONLY) 714 stbc_tx = (mac->vht_cur_stbc & 715 STBC_VHT_ENABLE_TX) ? 1 : 0; 716 else 717 stbc_tx = (mac->ht_cur_stbc & 718 STBC_HT_ENABLE_TX) ? 1 : 0; 719 h2c_parameter[3] |= stbc_tx << 1; 720 } 721 h2c_parameter[2] = 722 (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); 723 h2c_parameter[1] = 0x20; 724 h2c_parameter[0] = 0; 725 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 726 rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4, 727 h2c_parameter); 728 else 729 rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3, 730 h2c_parameter); 731 } else { 732 rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); 733 } 734 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 735 rtl8812ae_dm_rssi_dump_to_register(hw); 736 rtl8821ae_dm_find_minimum_rssi(hw); 737 dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm; 738 } 739 740 void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca) 741 { 742 struct rtl_priv *rtlpriv = rtl_priv(hw); 743 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 744 745 if (dm_digtable->cur_cck_cca_thres != current_cca) 746 rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca); 747 748 dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; 749 dm_digtable->cur_cck_cca_thres = current_cca; 750 } 751 752 void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) 753 { 754 struct rtl_priv *rtlpriv = rtl_priv(hw); 755 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 756 757 if (dm_digtable->stop_dig) 758 return; 759 760 if (dm_digtable->cur_igvalue != current_igi) { 761 rtl_set_bbreg(hw, DM_REG_IGI_A_11AC, 762 DM_BIT_IGI_11AC, current_igi); 763 if (rtlpriv->phy.rf_type != RF_1T1R) 764 rtl_set_bbreg(hw, DM_REG_IGI_B_11AC, 765 DM_BIT_IGI_11AC, current_igi); 766 } 767 dm_digtable->cur_igvalue = current_igi; 768 } 769 770 static void rtl8821ae_dm_dig(struct ieee80211_hw *hw) 771 { 772 struct rtl_priv *rtlpriv = rtl_priv(hw); 773 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 774 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 775 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 776 u8 dig_min_0; 777 u8 dig_max_of_min; 778 bool first_connect, first_disconnect; 779 u8 dm_dig_max, dm_dig_min, offset; 780 u8 current_igi = dm_digtable->cur_igvalue; 781 782 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "\n"); 783 784 if (mac->act_scanning) { 785 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 786 "Return: In Scan Progress\n"); 787 return; 788 } 789 790 /*add by Neil Chen to avoid PSD is processing*/ 791 dig_min_0 = dm_digtable->dig_min_0; 792 first_connect = (mac->link_state >= MAC80211_LINKED) && 793 (!dm_digtable->media_connect_0); 794 first_disconnect = (mac->link_state < MAC80211_LINKED) && 795 (dm_digtable->media_connect_0); 796 797 /*1 Boundary Decision*/ 798 799 dm_dig_max = 0x5A; 800 801 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) 802 dm_dig_min = DM_DIG_MIN; 803 else 804 dm_dig_min = 0x1C; 805 806 dig_max_of_min = DM_DIG_MAX_AP; 807 808 if (mac->link_state >= MAC80211_LINKED) { 809 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) 810 offset = 20; 811 else 812 offset = 10; 813 814 if ((dm_digtable->rssi_val_min + offset) > dm_dig_max) 815 dm_digtable->rx_gain_max = dm_dig_max; 816 else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min) 817 dm_digtable->rx_gain_max = dm_dig_min; 818 else 819 dm_digtable->rx_gain_max = 820 dm_digtable->rssi_val_min + offset; 821 822 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 823 "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x\n", 824 dm_digtable->rssi_val_min, 825 dm_digtable->rx_gain_max); 826 if (rtlpriv->dm.one_entry_only) { 827 offset = 0; 828 829 if (dm_digtable->rssi_val_min - offset < dm_dig_min) 830 dig_min_0 = dm_dig_min; 831 else if (dm_digtable->rssi_val_min - 832 offset > dig_max_of_min) 833 dig_min_0 = dig_max_of_min; 834 else 835 dig_min_0 = 836 dm_digtable->rssi_val_min - offset; 837 838 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 839 "bOneEntryOnly=TRUE, dig_min_0=0x%x\n", 840 dig_min_0); 841 } else { 842 dig_min_0 = dm_dig_min; 843 } 844 } else { 845 dm_digtable->rx_gain_max = dm_dig_max; 846 dig_min_0 = dm_dig_min; 847 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 848 "No Link\n"); 849 } 850 851 if (rtlpriv->falsealm_cnt.cnt_all > 10000) { 852 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 853 "Abnormally false alarm case.\n"); 854 855 if (dm_digtable->large_fa_hit != 3) 856 dm_digtable->large_fa_hit++; 857 if (dm_digtable->forbidden_igi < current_igi) { 858 dm_digtable->forbidden_igi = current_igi; 859 dm_digtable->large_fa_hit = 1; 860 } 861 862 if (dm_digtable->large_fa_hit >= 3) { 863 if ((dm_digtable->forbidden_igi + 1) > 864 dm_digtable->rx_gain_max) 865 dm_digtable->rx_gain_min = 866 dm_digtable->rx_gain_max; 867 else 868 dm_digtable->rx_gain_min = 869 (dm_digtable->forbidden_igi + 1); 870 dm_digtable->recover_cnt = 3600; 871 } 872 } else { 873 /*Recovery mechanism for IGI lower bound*/ 874 if (dm_digtable->recover_cnt != 0) { 875 dm_digtable->recover_cnt--; 876 } else { 877 if (dm_digtable->large_fa_hit < 3) { 878 if ((dm_digtable->forbidden_igi - 1) < 879 dig_min_0) { 880 dm_digtable->forbidden_igi = 881 dig_min_0; 882 dm_digtable->rx_gain_min = 883 dig_min_0; 884 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 885 "Normal Case: At Lower Bound\n"); 886 } else { 887 dm_digtable->forbidden_igi--; 888 dm_digtable->rx_gain_min = 889 (dm_digtable->forbidden_igi + 1); 890 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 891 "Normal Case: Approach Lower Bound\n"); 892 } 893 } else { 894 dm_digtable->large_fa_hit = 0; 895 } 896 } 897 } 898 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 899 "pDM_DigTable->LargeFAHit=%d\n", 900 dm_digtable->large_fa_hit); 901 902 if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) 903 dm_digtable->rx_gain_min = dm_dig_min; 904 905 if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) 906 dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; 907 908 /*Adjust initial gain by false alarm*/ 909 if (mac->link_state >= MAC80211_LINKED) { 910 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 911 "DIG AfterLink\n"); 912 if (first_connect) { 913 if (dm_digtable->rssi_val_min <= dig_max_of_min) 914 current_igi = dm_digtable->rssi_val_min; 915 else 916 current_igi = dig_max_of_min; 917 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 918 "First Connect\n"); 919 } else { 920 if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) 921 current_igi = current_igi + 4; 922 else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) 923 current_igi = current_igi + 2; 924 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) 925 current_igi = current_igi - 2; 926 927 if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) && 928 (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) { 929 current_igi = dm_digtable->rx_gain_min; 930 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 931 "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n"); 932 } 933 } 934 } else { 935 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 936 "DIG BeforeLink\n"); 937 if (first_disconnect) { 938 current_igi = dm_digtable->rx_gain_min; 939 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 940 "First DisConnect\n"); 941 } else { 942 /* 2012.03.30 LukeLee: enable DIG before 943 * link but with very high thresholds 944 */ 945 if (rtlpriv->falsealm_cnt.cnt_all > 2000) 946 current_igi = current_igi + 4; 947 else if (rtlpriv->falsealm_cnt.cnt_all > 600) 948 current_igi = current_igi + 2; 949 else if (rtlpriv->falsealm_cnt.cnt_all < 300) 950 current_igi = current_igi - 2; 951 952 if (current_igi >= 0x3e) 953 current_igi = 0x3e; 954 955 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n"); 956 } 957 } 958 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 959 "DIG End Adjust IGI\n"); 960 /* Check initial gain by upper/lower bound*/ 961 962 if (current_igi > dm_digtable->rx_gain_max) 963 current_igi = dm_digtable->rx_gain_max; 964 if (current_igi < dm_digtable->rx_gain_min) 965 current_igi = dm_digtable->rx_gain_min; 966 967 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 968 "rx_gain_max=0x%x, rx_gain_min=0x%x\n", 969 dm_digtable->rx_gain_max, dm_digtable->rx_gain_min); 970 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 971 "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all); 972 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 973 "CurIGValue=0x%x\n", current_igi); 974 975 rtl8821ae_dm_write_dig(hw, current_igi); 976 dm_digtable->media_connect_0 = 977 ((mac->link_state >= MAC80211_LINKED) ? true : false); 978 dm_digtable->dig_min_0 = dig_min_0; 979 } 980 981 static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw) 982 { 983 struct rtl_priv *rtlpriv = rtl_priv(hw); 984 u8 cnt = 0; 985 struct rtl_sta_info *drv_priv; 986 987 rtlpriv->dm.tx_rate = 0xff; 988 989 rtlpriv->dm.one_entry_only = false; 990 991 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && 992 rtlpriv->mac80211.link_state >= MAC80211_LINKED) { 993 rtlpriv->dm.one_entry_only = true; 994 return; 995 } 996 997 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || 998 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || 999 rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { 1000 spin_lock_bh(&rtlpriv->locks.entry_list_lock); 1001 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) 1002 cnt++; 1003 spin_unlock_bh(&rtlpriv->locks.entry_list_lock); 1004 1005 if (cnt == 1) 1006 rtlpriv->dm.one_entry_only = true; 1007 } 1008 } 1009 1010 static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) 1011 { 1012 struct rtl_priv *rtlpriv = rtl_priv(hw); 1013 struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; 1014 u32 cck_enable = 0; 1015 1016 /*read OFDM FA counter*/ 1017 falsealm_cnt->cnt_ofdm_fail = 1018 rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD); 1019 falsealm_cnt->cnt_cck_fail = 1020 rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD); 1021 1022 cck_enable = rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28)); 1023 if (cck_enable) /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/ 1024 falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + 1025 falsealm_cnt->cnt_cck_fail; 1026 else 1027 falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail; 1028 1029 /*reset OFDM FA coutner*/ 1030 rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1); 1031 rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0); 1032 /* reset CCK FA counter*/ 1033 rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0); 1034 rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1); 1035 1036 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n", 1037 falsealm_cnt->cnt_cck_fail); 1038 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n", 1039 falsealm_cnt->cnt_ofdm_fail); 1040 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n", 1041 falsealm_cnt->cnt_all); 1042 } 1043 1044 static void rtl8812ae_dm_check_txpower_tracking_thermalmeter( 1045 struct ieee80211_hw *hw) 1046 { 1047 struct rtl_priv *rtlpriv = rtl_priv(hw); 1048 1049 if (!rtlpriv->dm.tm_trigger) { 1050 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, 1051 BIT(17) | BIT(16), 0x03); 1052 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1053 "Trigger 8812 Thermal Meter!!\n"); 1054 rtlpriv->dm.tm_trigger = 1; 1055 return; 1056 } 1057 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1058 "Schedule TxPowerTracking direct call!!\n"); 1059 rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw); 1060 } 1061 1062 static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw) 1063 { 1064 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1065 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1066 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1067 1068 if (mac->link_state >= MAC80211_LINKED) { 1069 if (rtldm->linked_interval < 3) 1070 rtldm->linked_interval++; 1071 1072 if (rtldm->linked_interval == 2) { 1073 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 1074 rtl8812ae_phy_iq_calibrate(hw, false); 1075 else 1076 rtl8821ae_phy_iq_calibrate(hw, false); 1077 } 1078 } else { 1079 rtldm->linked_interval = 0; 1080 } 1081 } 1082 1083 static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw, 1084 u8 **up_a, u8 **down_a, 1085 u8 **up_b, u8 **down_b) 1086 { 1087 struct rtl_priv *rtlpriv = rtl_priv(hw); 1088 struct rtl_phy *rtlphy = &rtlpriv->phy; 1089 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1090 u8 channel = rtlphy->current_channel; 1091 u8 rate = rtldm->tx_rate; 1092 1093 if (1 <= channel && channel <= 14) { 1094 if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { 1095 *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p; 1096 *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n; 1097 *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p; 1098 *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n; 1099 } else { 1100 *up_a = rtl8812ae_delta_swing_table_idx_24ga_p; 1101 *down_a = rtl8812ae_delta_swing_table_idx_24ga_n; 1102 *up_b = rtl8812ae_delta_swing_table_idx_24gb_p; 1103 *down_b = rtl8812ae_delta_swing_table_idx_24gb_n; 1104 } 1105 } else if (36 <= channel && channel <= 64) { 1106 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0]; 1107 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0]; 1108 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0]; 1109 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0]; 1110 } else if (100 <= channel && channel <= 140) { 1111 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1]; 1112 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1]; 1113 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1]; 1114 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1]; 1115 } else if (149 <= channel && channel <= 173) { 1116 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2]; 1117 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2]; 1118 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2]; 1119 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2]; 1120 } else { 1121 *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; 1122 *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; 1123 *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; 1124 *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; 1125 } 1126 } 1127 1128 void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate) 1129 { 1130 struct rtl_priv *rtlpriv = rtl_priv(hw); 1131 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1132 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1133 u8 p = 0; 1134 1135 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1136 "Get C2H Command! Rate=0x%x\n", rate); 1137 1138 rtldm->tx_rate = rate; 1139 1140 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 1141 rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0); 1142 } else { 1143 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) 1144 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0); 1145 } 1146 } 1147 1148 u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate) 1149 { 1150 struct rtl_priv *rtlpriv = rtl_priv(hw); 1151 u8 ret_rate = MGN_1M; 1152 1153 switch (rate) { 1154 case DESC_RATE1M: 1155 ret_rate = MGN_1M; 1156 break; 1157 case DESC_RATE2M: 1158 ret_rate = MGN_2M; 1159 break; 1160 case DESC_RATE5_5M: 1161 ret_rate = MGN_5_5M; 1162 break; 1163 case DESC_RATE11M: 1164 ret_rate = MGN_11M; 1165 break; 1166 case DESC_RATE6M: 1167 ret_rate = MGN_6M; 1168 break; 1169 case DESC_RATE9M: 1170 ret_rate = MGN_9M; 1171 break; 1172 case DESC_RATE12M: 1173 ret_rate = MGN_12M; 1174 break; 1175 case DESC_RATE18M: 1176 ret_rate = MGN_18M; 1177 break; 1178 case DESC_RATE24M: 1179 ret_rate = MGN_24M; 1180 break; 1181 case DESC_RATE36M: 1182 ret_rate = MGN_36M; 1183 break; 1184 case DESC_RATE48M: 1185 ret_rate = MGN_48M; 1186 break; 1187 case DESC_RATE54M: 1188 ret_rate = MGN_54M; 1189 break; 1190 case DESC_RATEMCS0: 1191 ret_rate = MGN_MCS0; 1192 break; 1193 case DESC_RATEMCS1: 1194 ret_rate = MGN_MCS1; 1195 break; 1196 case DESC_RATEMCS2: 1197 ret_rate = MGN_MCS2; 1198 break; 1199 case DESC_RATEMCS3: 1200 ret_rate = MGN_MCS3; 1201 break; 1202 case DESC_RATEMCS4: 1203 ret_rate = MGN_MCS4; 1204 break; 1205 case DESC_RATEMCS5: 1206 ret_rate = MGN_MCS5; 1207 break; 1208 case DESC_RATEMCS6: 1209 ret_rate = MGN_MCS6; 1210 break; 1211 case DESC_RATEMCS7: 1212 ret_rate = MGN_MCS7; 1213 break; 1214 case DESC_RATEMCS8: 1215 ret_rate = MGN_MCS8; 1216 break; 1217 case DESC_RATEMCS9: 1218 ret_rate = MGN_MCS9; 1219 break; 1220 case DESC_RATEMCS10: 1221 ret_rate = MGN_MCS10; 1222 break; 1223 case DESC_RATEMCS11: 1224 ret_rate = MGN_MCS11; 1225 break; 1226 case DESC_RATEMCS12: 1227 ret_rate = MGN_MCS12; 1228 break; 1229 case DESC_RATEMCS13: 1230 ret_rate = MGN_MCS13; 1231 break; 1232 case DESC_RATEMCS14: 1233 ret_rate = MGN_MCS14; 1234 break; 1235 case DESC_RATEMCS15: 1236 ret_rate = MGN_MCS15; 1237 break; 1238 case DESC_RATEVHT1SS_MCS0: 1239 ret_rate = MGN_VHT1SS_MCS0; 1240 break; 1241 case DESC_RATEVHT1SS_MCS1: 1242 ret_rate = MGN_VHT1SS_MCS1; 1243 break; 1244 case DESC_RATEVHT1SS_MCS2: 1245 ret_rate = MGN_VHT1SS_MCS2; 1246 break; 1247 case DESC_RATEVHT1SS_MCS3: 1248 ret_rate = MGN_VHT1SS_MCS3; 1249 break; 1250 case DESC_RATEVHT1SS_MCS4: 1251 ret_rate = MGN_VHT1SS_MCS4; 1252 break; 1253 case DESC_RATEVHT1SS_MCS5: 1254 ret_rate = MGN_VHT1SS_MCS5; 1255 break; 1256 case DESC_RATEVHT1SS_MCS6: 1257 ret_rate = MGN_VHT1SS_MCS6; 1258 break; 1259 case DESC_RATEVHT1SS_MCS7: 1260 ret_rate = MGN_VHT1SS_MCS7; 1261 break; 1262 case DESC_RATEVHT1SS_MCS8: 1263 ret_rate = MGN_VHT1SS_MCS8; 1264 break; 1265 case DESC_RATEVHT1SS_MCS9: 1266 ret_rate = MGN_VHT1SS_MCS9; 1267 break; 1268 case DESC_RATEVHT2SS_MCS0: 1269 ret_rate = MGN_VHT2SS_MCS0; 1270 break; 1271 case DESC_RATEVHT2SS_MCS1: 1272 ret_rate = MGN_VHT2SS_MCS1; 1273 break; 1274 case DESC_RATEVHT2SS_MCS2: 1275 ret_rate = MGN_VHT2SS_MCS2; 1276 break; 1277 case DESC_RATEVHT2SS_MCS3: 1278 ret_rate = MGN_VHT2SS_MCS3; 1279 break; 1280 case DESC_RATEVHT2SS_MCS4: 1281 ret_rate = MGN_VHT2SS_MCS4; 1282 break; 1283 case DESC_RATEVHT2SS_MCS5: 1284 ret_rate = MGN_VHT2SS_MCS5; 1285 break; 1286 case DESC_RATEVHT2SS_MCS6: 1287 ret_rate = MGN_VHT2SS_MCS6; 1288 break; 1289 case DESC_RATEVHT2SS_MCS7: 1290 ret_rate = MGN_VHT2SS_MCS7; 1291 break; 1292 case DESC_RATEVHT2SS_MCS8: 1293 ret_rate = MGN_VHT2SS_MCS8; 1294 break; 1295 case DESC_RATEVHT2SS_MCS9: 1296 ret_rate = MGN_VHT2SS_MCS9; 1297 break; 1298 default: 1299 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1300 "HwRateToMRate8812(): Non supported Rate [%x]!!!\n", 1301 rate); 1302 break; 1303 } 1304 return ret_rate; 1305 } 1306 1307 /*----------------------------------------------------------------------------- 1308 * Function: odm_TxPwrTrackSetPwr88E() 1309 * 1310 * Overview: 88E change all channel tx power accordign to flag. 1311 * OFDM & CCK are all different. 1312 * 1313 * Input: NONE 1314 * 1315 * Output: NONE 1316 * 1317 * Return: NONE 1318 * 1319 * Revised History: 1320 * When Who Remark 1321 * 04/23/2012 MHC Create Version 0. 1322 * 1323 *--------------------------------------------------------------------------- 1324 */ 1325 void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, 1326 enum pwr_track_control_method method, 1327 u8 rf_path, u8 channel_mapped_index) 1328 { 1329 struct rtl_priv *rtlpriv = rtl_priv(hw); 1330 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1331 struct rtl_phy *rtlphy = &rtlpriv->phy; 1332 u32 final_swing_idx[2]; 1333 u8 pwr_tracking_limit = 26; /*+1.0dB*/ 1334 u8 tx_rate = 0xFF; 1335 s8 final_ofdm_swing_index = 0; 1336 1337 if (rtldm->tx_rate != 0xFF) 1338 tx_rate = 1339 rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); 1340 1341 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1342 "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); 1343 /*20130429 Mimic Modify High Rate BBSwing Limit.*/ 1344 if (tx_rate != 0xFF) { 1345 /*CCK*/ 1346 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) 1347 pwr_tracking_limit = 32; /*+4dB*/ 1348 /*OFDM*/ 1349 else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) 1350 pwr_tracking_limit = 30; /*+3dB*/ 1351 else if (tx_rate == MGN_54M) 1352 pwr_tracking_limit = 28; /*+2dB*/ 1353 /*HT*/ 1354 /*QPSK/BPSK*/ 1355 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) 1356 pwr_tracking_limit = 34; /*+5dB*/ 1357 /*16QAM*/ 1358 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) 1359 pwr_tracking_limit = 30; /*+3dB*/ 1360 /*64QAM*/ 1361 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) 1362 pwr_tracking_limit = 28; /*+2dB*/ 1363 /*QPSK/BPSK*/ 1364 else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10)) 1365 pwr_tracking_limit = 34; /*+5dB*/ 1366 /*16QAM*/ 1367 else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12)) 1368 pwr_tracking_limit = 30; /*+3dB*/ 1369 /*64QAM*/ 1370 else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15)) 1371 pwr_tracking_limit = 28; /*+2dB*/ 1372 1373 /*2 VHT*/ 1374 /*QPSK/BPSK*/ 1375 else if ((tx_rate >= MGN_VHT1SS_MCS0) && 1376 (tx_rate <= MGN_VHT1SS_MCS2)) 1377 pwr_tracking_limit = 34; /*+5dB*/ 1378 /*16QAM*/ 1379 else if ((tx_rate >= MGN_VHT1SS_MCS3) && 1380 (tx_rate <= MGN_VHT1SS_MCS4)) 1381 pwr_tracking_limit = 30; /*+3dB*/ 1382 /*64QAM*/ 1383 else if ((tx_rate >= MGN_VHT1SS_MCS5) && 1384 (tx_rate <= MGN_VHT1SS_MCS6)) 1385 pwr_tracking_limit = 28; /*+2dB*/ 1386 else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ 1387 pwr_tracking_limit = 26; /*+1dB*/ 1388 else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ 1389 pwr_tracking_limit = 24; /*+0dB*/ 1390 else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ 1391 pwr_tracking_limit = 22; /*-1dB*/ 1392 /*QPSK/BPSK*/ 1393 else if ((tx_rate >= MGN_VHT2SS_MCS0) && 1394 (tx_rate <= MGN_VHT2SS_MCS2)) 1395 pwr_tracking_limit = 34; /*+5dB*/ 1396 /*16QAM*/ 1397 else if ((tx_rate >= MGN_VHT2SS_MCS3) && 1398 (tx_rate <= MGN_VHT2SS_MCS4)) 1399 pwr_tracking_limit = 30; /*+3dB*/ 1400 /*64QAM*/ 1401 else if ((tx_rate >= MGN_VHT2SS_MCS5) && 1402 (tx_rate <= MGN_VHT2SS_MCS6)) 1403 pwr_tracking_limit = 28; /*+2dB*/ 1404 else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/ 1405 pwr_tracking_limit = 26; /*+1dB*/ 1406 else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/ 1407 pwr_tracking_limit = 24; /*+0dB*/ 1408 else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/ 1409 pwr_tracking_limit = 22; /*-1dB*/ 1410 else 1411 pwr_tracking_limit = 24; 1412 } 1413 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1414 "TxRate=0x%x, PwrTrackingLimit=%d\n", 1415 tx_rate, pwr_tracking_limit); 1416 1417 if (method == BBSWING) { 1418 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1419 "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); 1420 1421 if (rf_path == RF90_PATH_A) { 1422 u32 tmp; 1423 1424 final_swing_idx[RF90_PATH_A] = 1425 (rtldm->ofdm_index[RF90_PATH_A] > 1426 pwr_tracking_limit) ? 1427 pwr_tracking_limit : 1428 rtldm->ofdm_index[RF90_PATH_A]; 1429 tmp = final_swing_idx[RF90_PATH_A]; 1430 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1431 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", 1432 rtldm->ofdm_index[RF90_PATH_A], 1433 final_swing_idx[RF90_PATH_A]); 1434 1435 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 1436 txscaling_tbl[tmp]); 1437 } else { 1438 u32 tmp; 1439 1440 final_swing_idx[RF90_PATH_B] = 1441 rtldm->ofdm_index[RF90_PATH_B] > 1442 pwr_tracking_limit ? 1443 pwr_tracking_limit : 1444 rtldm->ofdm_index[RF90_PATH_B]; 1445 tmp = final_swing_idx[RF90_PATH_B]; 1446 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1447 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n", 1448 rtldm->ofdm_index[RF90_PATH_B], 1449 final_swing_idx[RF90_PATH_B]); 1450 1451 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, 1452 txscaling_tbl[tmp]); 1453 } 1454 } else if (method == MIX_MODE) { 1455 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1456 "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", 1457 rtldm->default_ofdm_index, 1458 rtldm->absolute_ofdm_swing_idx[rf_path], 1459 rf_path); 1460 1461 final_ofdm_swing_index = rtldm->default_ofdm_index + 1462 rtldm->absolute_ofdm_swing_idx[rf_path]; 1463 1464 if (rf_path == RF90_PATH_A) { 1465 /*BBSwing higher then Limit*/ 1466 if (final_ofdm_swing_index > pwr_tracking_limit) { 1467 rtldm->remnant_cck_idx = 1468 final_ofdm_swing_index - 1469 pwr_tracking_limit; 1470 /* CCK Follow the same compensation value 1471 * as Path A 1472 */ 1473 rtldm->remnant_ofdm_swing_idx[rf_path] = 1474 final_ofdm_swing_index - 1475 pwr_tracking_limit; 1476 1477 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 1478 txscaling_tbl[pwr_tracking_limit]); 1479 1480 rtldm->modify_txagc_flag_path_a = true; 1481 1482 /*Set TxAGC Page C{};*/ 1483 rtl8821ae_phy_set_txpower_level_by_path(hw, 1484 rtlphy->current_channel, 1485 RF90_PATH_A); 1486 1487 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1488 "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n", 1489 pwr_tracking_limit, 1490 rtldm->remnant_ofdm_swing_idx[rf_path]); 1491 } else if (final_ofdm_swing_index < 0) { 1492 rtldm->remnant_cck_idx = final_ofdm_swing_index; 1493 /* CCK Follow the same compensate value as Path A*/ 1494 rtldm->remnant_ofdm_swing_idx[rf_path] = 1495 final_ofdm_swing_index; 1496 1497 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 1498 txscaling_tbl[0]); 1499 1500 rtldm->modify_txagc_flag_path_a = true; 1501 1502 /*Set TxAGC Page C{};*/ 1503 rtl8821ae_phy_set_txpower_level_by_path(hw, 1504 rtlphy->current_channel, RF90_PATH_A); 1505 1506 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1507 "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", 1508 rtldm->remnant_ofdm_swing_idx[rf_path]); 1509 } else { 1510 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 1511 txscaling_tbl[(u8)final_ofdm_swing_index]); 1512 1513 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1514 "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n", 1515 final_ofdm_swing_index); 1516 /*If TxAGC has changed, reset TxAGC again*/ 1517 if (rtldm->modify_txagc_flag_path_a) { 1518 rtldm->remnant_cck_idx = 0; 1519 rtldm->remnant_ofdm_swing_idx[rf_path] = 0; 1520 1521 /*Set TxAGC Page C{};*/ 1522 rtl8821ae_phy_set_txpower_level_by_path(hw, 1523 rtlphy->current_channel, RF90_PATH_A); 1524 rtldm->modify_txagc_flag_path_a = false; 1525 1526 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, 1527 DBG_LOUD, 1528 "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); 1529 } 1530 } 1531 } 1532 /*BBSwing higher then Limit*/ 1533 if (rf_path == RF90_PATH_B) { 1534 if (final_ofdm_swing_index > pwr_tracking_limit) { 1535 rtldm->remnant_ofdm_swing_idx[rf_path] = 1536 final_ofdm_swing_index - 1537 pwr_tracking_limit; 1538 1539 rtl_set_bbreg(hw, RB_TXSCALE, 1540 0xFFE00000, 1541 txscaling_tbl[pwr_tracking_limit]); 1542 1543 rtldm->modify_txagc_flag_path_b = true; 1544 1545 /*Set TxAGC Page E{};*/ 1546 rtl8821ae_phy_set_txpower_level_by_path(hw, 1547 rtlphy->current_channel, RF90_PATH_B); 1548 1549 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1550 "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", 1551 pwr_tracking_limit, 1552 rtldm->remnant_ofdm_swing_idx[rf_path]); 1553 } else if (final_ofdm_swing_index < 0) { 1554 rtldm->remnant_ofdm_swing_idx[rf_path] = 1555 final_ofdm_swing_index; 1556 1557 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, 1558 txscaling_tbl[0]); 1559 1560 rtldm->modify_txagc_flag_path_b = true; 1561 1562 /*Set TxAGC Page E{};*/ 1563 rtl8821ae_phy_set_txpower_level_by_path(hw, 1564 rtlphy->current_channel, RF90_PATH_B); 1565 1566 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1567 "******Path_B Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", 1568 rtldm->remnant_ofdm_swing_idx[rf_path]); 1569 } else { 1570 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, 1571 txscaling_tbl[(u8)final_ofdm_swing_index]); 1572 1573 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1574 "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", 1575 final_ofdm_swing_index); 1576 /*If TxAGC has changed, reset TxAGC again*/ 1577 if (rtldm->modify_txagc_flag_path_b) { 1578 rtldm->remnant_ofdm_swing_idx[rf_path] = 0; 1579 1580 /*Set TxAGC Page E{};*/ 1581 rtl8821ae_phy_set_txpower_level_by_path(hw, 1582 rtlphy->current_channel, RF90_PATH_B); 1583 1584 rtldm->modify_txagc_flag_path_b = 1585 false; 1586 1587 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1588 "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); 1589 } 1590 } 1591 } 1592 } else { 1593 return; 1594 } 1595 } 1596 1597 void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( 1598 struct ieee80211_hw *hw) 1599 { 1600 struct rtl_priv *rtlpriv = rtl_priv(hw); 1601 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 1602 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1603 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 1604 u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; 1605 u8 thermal_value_avg_count = 0; 1606 u32 thermal_value_avg = 0; 1607 /* OFDM BB Swing should be less than +3.0dB, */ 1608 u8 ofdm_min_index = 6; 1609 /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ 1610 u8 index_for_channel = 0; 1611 /* 1. The following TWO tables decide 1612 * the final index of OFDM/CCK swing table. 1613 */ 1614 u8 *delta_swing_table_idx_tup_a; 1615 u8 *delta_swing_table_idx_tdown_a; 1616 u8 *delta_swing_table_idx_tup_b; 1617 u8 *delta_swing_table_idx_tdown_b; 1618 1619 /*2. Initilization ( 7 steps in total )*/ 1620 rtl8812ae_get_delta_swing_table(hw, 1621 (u8 **)&delta_swing_table_idx_tup_a, 1622 (u8 **)&delta_swing_table_idx_tdown_a, 1623 (u8 **)&delta_swing_table_idx_tup_b, 1624 (u8 **)&delta_swing_table_idx_tdown_b); 1625 1626 rtldm->txpower_trackinginit = true; 1627 1628 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1629 "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", 1630 rtldm->swing_idx_cck_base, 1631 rtldm->swing_idx_ofdm_base[RF90_PATH_A], 1632 rtldm->default_ofdm_index); 1633 1634 thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A, 1635 /*0x42: RF Reg[15:10] 88E*/ 1636 RF_T_METER_8812A, 0xfc00); 1637 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1638 "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", 1639 thermal_value, rtlefuse->eeprom_thermalmeter); 1640 if (!rtldm->txpower_track_control || 1641 rtlefuse->eeprom_thermalmeter == 0 || 1642 rtlefuse->eeprom_thermalmeter == 0xFF) 1643 return; 1644 1645 /* 3. Initialize ThermalValues of RFCalibrateInfo*/ 1646 1647 if (rtlhal->reloadtxpowerindex) 1648 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1649 "reload ofdm index for band switch\n"); 1650 1651 /*4. Calculate average thermal meter*/ 1652 rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; 1653 rtldm->thermalvalue_avg_index++; 1654 if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) 1655 /*Average times = c.AverageThermalNum*/ 1656 rtldm->thermalvalue_avg_index = 0; 1657 1658 for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { 1659 if (rtldm->thermalvalue_avg[i]) { 1660 thermal_value_avg += rtldm->thermalvalue_avg[i]; 1661 thermal_value_avg_count++; 1662 } 1663 } 1664 /*Calculate Average ThermalValue after average enough times*/ 1665 if (thermal_value_avg_count) { 1666 thermal_value = (u8)(thermal_value_avg / 1667 thermal_value_avg_count); 1668 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1669 "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", 1670 thermal_value, rtlefuse->eeprom_thermalmeter); 1671 } 1672 1673 /*5. Calculate delta, delta_LCK, delta_IQK. 1674 *"delta" here is used to determine whether 1675 *thermal value changes or not. 1676 */ 1677 delta = (thermal_value > rtldm->thermalvalue) ? 1678 (thermal_value - rtldm->thermalvalue) : 1679 (rtldm->thermalvalue - thermal_value); 1680 delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? 1681 (thermal_value - rtldm->thermalvalue_lck) : 1682 (rtldm->thermalvalue_lck - thermal_value); 1683 delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? 1684 (thermal_value - rtldm->thermalvalue_iqk) : 1685 (rtldm->thermalvalue_iqk - thermal_value); 1686 1687 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1688 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", 1689 delta, delta_lck, delta_iqk); 1690 1691 /* 6. If necessary, do LCK. 1692 * Delta temperature is equal to or larger than 20 centigrade. 1693 */ 1694 if (delta_lck >= IQK_THRESHOLD) { 1695 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1696 "delta_LCK(%d) >= Threshold_IQK(%d)\n", 1697 delta_lck, IQK_THRESHOLD); 1698 rtldm->thermalvalue_lck = thermal_value; 1699 rtl8821ae_phy_lc_calibrate(hw); 1700 } 1701 1702 /*7. If necessary, move the index of swing table to adjust Tx power.*/ 1703 1704 if (delta > 0 && rtldm->txpower_track_control) { 1705 /* "delta" here is used to record the 1706 * absolute value of differrence. 1707 */ 1708 delta = thermal_value > rtlefuse->eeprom_thermalmeter ? 1709 (thermal_value - rtlefuse->eeprom_thermalmeter) : 1710 (rtlefuse->eeprom_thermalmeter - thermal_value); 1711 1712 if (delta >= TXPWR_TRACK_TABLE_SIZE) 1713 delta = TXPWR_TRACK_TABLE_SIZE - 1; 1714 1715 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ 1716 1717 if (thermal_value > rtlefuse->eeprom_thermalmeter) { 1718 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1719 "delta_swing_table_idx_tup_a[%d] = %d\n", 1720 delta, delta_swing_table_idx_tup_a[delta]); 1721 rtldm->delta_power_index_last[RF90_PATH_A] = 1722 rtldm->delta_power_index[RF90_PATH_A]; 1723 rtldm->delta_power_index[RF90_PATH_A] = 1724 delta_swing_table_idx_tup_a[delta]; 1725 1726 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = 1727 delta_swing_table_idx_tup_a[delta]; 1728 /*Record delta swing for mix mode power tracking*/ 1729 1730 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1731 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", 1732 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); 1733 1734 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1735 "delta_swing_table_idx_tup_b[%d] = %d\n", 1736 delta, delta_swing_table_idx_tup_b[delta]); 1737 rtldm->delta_power_index_last[RF90_PATH_B] = 1738 rtldm->delta_power_index[RF90_PATH_B]; 1739 rtldm->delta_power_index[RF90_PATH_B] = 1740 delta_swing_table_idx_tup_b[delta]; 1741 1742 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = 1743 delta_swing_table_idx_tup_b[delta]; 1744 /*Record delta swing for mix mode power tracking*/ 1745 1746 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1747 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", 1748 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); 1749 } else { 1750 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1751 "delta_swing_table_idx_tdown_a[%d] = %d\n", 1752 delta, delta_swing_table_idx_tdown_a[delta]); 1753 1754 rtldm->delta_power_index_last[RF90_PATH_A] = 1755 rtldm->delta_power_index[RF90_PATH_A]; 1756 rtldm->delta_power_index[RF90_PATH_A] = 1757 -1 * delta_swing_table_idx_tdown_a[delta]; 1758 1759 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = 1760 -1 * delta_swing_table_idx_tdown_a[delta]; 1761 /* Record delta swing for mix mode power tracking*/ 1762 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1763 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", 1764 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); 1765 1766 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1767 "deltaSwingTableIdx_TDOWN_B[%d] = %d\n", 1768 delta, delta_swing_table_idx_tdown_b[delta]); 1769 1770 rtldm->delta_power_index_last[RF90_PATH_B] = 1771 rtldm->delta_power_index[RF90_PATH_B]; 1772 rtldm->delta_power_index[RF90_PATH_B] = 1773 -1 * delta_swing_table_idx_tdown_b[delta]; 1774 1775 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = 1776 -1 * delta_swing_table_idx_tdown_b[delta]; 1777 /*Record delta swing for mix mode power tracking*/ 1778 1779 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1780 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", 1781 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); 1782 } 1783 1784 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { 1785 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1786 "============================= [Path-%c]Calculating PowerIndexOffset =============================\n", 1787 (p == RF90_PATH_A ? 'A' : 'B')); 1788 1789 if (rtldm->delta_power_index[p] == 1790 rtldm->delta_power_index_last[p]) 1791 /*If Thermal value changes but lookup 1792 table value still the same*/ 1793 rtldm->power_index_offset[p] = 0; 1794 else 1795 rtldm->power_index_offset[p] = 1796 rtldm->delta_power_index[p] - 1797 rtldm->delta_power_index_last[p]; 1798 /* Power Index Diff between 2 1799 * times Power Tracking 1800 */ 1801 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1802 "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n", 1803 (p == RF90_PATH_A ? 'A' : 'B'), 1804 rtldm->power_index_offset[p], 1805 rtldm->delta_power_index[p] , 1806 rtldm->delta_power_index_last[p]); 1807 1808 rtldm->ofdm_index[p] = 1809 rtldm->swing_idx_ofdm_base[p] + 1810 rtldm->power_index_offset[p]; 1811 rtldm->cck_index = 1812 rtldm->swing_idx_cck_base + 1813 rtldm->power_index_offset[p]; 1814 1815 rtldm->swing_idx_cck = rtldm->cck_index; 1816 rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; 1817 1818 /****Print BB Swing Base and Index Offset */ 1819 1820 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1821 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", 1822 rtldm->swing_idx_cck, 1823 rtldm->swing_idx_cck_base, 1824 rtldm->power_index_offset[p]); 1825 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1826 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", 1827 rtldm->swing_idx_ofdm[p], 1828 (p == RF90_PATH_A ? 'A' : 'B'), 1829 rtldm->swing_idx_ofdm_base[p], 1830 rtldm->power_index_offset[p]); 1831 1832 /*7.1 Handle boundary conditions of index.*/ 1833 1834 if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) 1835 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; 1836 else if (rtldm->ofdm_index[p] < ofdm_min_index) 1837 rtldm->ofdm_index[p] = ofdm_min_index; 1838 } 1839 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1840 "\n\n====================================================================================\n"); 1841 if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) 1842 rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; 1843 else if (rtldm->cck_index < 0) 1844 rtldm->cck_index = 0; 1845 } else { 1846 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1847 "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", 1848 rtldm->txpower_track_control, 1849 thermal_value, 1850 rtldm->thermalvalue); 1851 1852 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) 1853 rtldm->power_index_offset[p] = 0; 1854 } 1855 /*Print Swing base & current*/ 1856 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1857 "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n", 1858 rtldm->cck_index, rtldm->swing_idx_cck_base); 1859 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { 1860 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1861 "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n", 1862 rtldm->ofdm_index[p], 1863 (p == RF90_PATH_A ? 'A' : 'B'), 1864 rtldm->swing_idx_ofdm_base[p]); 1865 } 1866 1867 if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || 1868 rtldm->power_index_offset[RF90_PATH_B] != 0) && 1869 rtldm->txpower_track_control) { 1870 /*7.2 Configure the Swing Table to adjust Tx Power. 1871 *Always TRUE after Tx Power is adjusted by power tracking. 1872 * 1873 *2012/04/23 MH According to Luke's suggestion, 1874 *we can not write BB digital 1875 *to increase TX power. Otherwise, EVM will be bad. 1876 * 1877 *2012/04/25 MH Add for tx power tracking to set 1878 *tx power in tx agc for 88E. 1879 */ 1880 if (thermal_value > rtldm->thermalvalue) { 1881 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1882 "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n", 1883 rtldm->power_index_offset[RF90_PATH_A], 1884 delta, thermal_value, 1885 rtlefuse->eeprom_thermalmeter, 1886 rtldm->thermalvalue); 1887 1888 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1889 "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", 1890 rtldm->power_index_offset[RF90_PATH_B], 1891 delta, thermal_value, 1892 rtlefuse->eeprom_thermalmeter, 1893 rtldm->thermalvalue); 1894 } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ 1895 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1896 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", 1897 rtldm->power_index_offset[RF90_PATH_A], 1898 delta, thermal_value, 1899 rtlefuse->eeprom_thermalmeter, 1900 rtldm->thermalvalue); 1901 1902 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1903 "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", 1904 rtldm->power_index_offset[RF90_PATH_B], 1905 delta, thermal_value, 1906 rtlefuse->eeprom_thermalmeter, 1907 rtldm->thermalvalue); 1908 } 1909 1910 if (thermal_value > rtlefuse->eeprom_thermalmeter) { 1911 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1912 "Temperature(%d) higher than PG value(%d)\n", 1913 thermal_value, rtlefuse->eeprom_thermalmeter); 1914 1915 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1916 "**********Enter POWER Tracking MIX_MODE**********\n"); 1917 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) 1918 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, 1919 p, 0); 1920 } else { 1921 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1922 "Temperature(%d) lower than PG value(%d)\n", 1923 thermal_value, rtlefuse->eeprom_thermalmeter); 1924 1925 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1926 "**********Enter POWER Tracking MIX_MODE**********\n"); 1927 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) 1928 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, 1929 p, index_for_channel); 1930 } 1931 /*Record last time Power Tracking result as base.*/ 1932 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; 1933 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) 1934 rtldm->swing_idx_ofdm_base[p] = 1935 rtldm->swing_idx_ofdm[p]; 1936 1937 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1938 "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n", 1939 rtldm->thermalvalue, thermal_value); 1940 /*Record last Power Tracking Thermal Value*/ 1941 rtldm->thermalvalue = thermal_value; 1942 } 1943 /*Delta temperature is equal to or larger than 1944 20 centigrade (When threshold is 8).*/ 1945 if (delta_iqk >= IQK_THRESHOLD) 1946 rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8); 1947 1948 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 1949 "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n"); 1950 } 1951 1952 static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a, 1953 u8 **down_a, u8 **up_b, u8 **down_b) 1954 { 1955 struct rtl_priv *rtlpriv = rtl_priv(hw); 1956 struct rtl_phy *rtlphy = &rtlpriv->phy; 1957 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1958 u8 channel = rtlphy->current_channel; 1959 u8 rate = rtldm->tx_rate; 1960 1961 if (1 <= channel && channel <= 14) { 1962 if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { 1963 *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p; 1964 *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n; 1965 *up_b = rtl8821ae_delta_swing_table_idx_24gcckb_p; 1966 *down_b = rtl8821ae_delta_swing_table_idx_24gcckb_n; 1967 } else { 1968 *up_a = rtl8821ae_delta_swing_table_idx_24ga_p; 1969 *down_a = rtl8821ae_delta_swing_table_idx_24ga_n; 1970 *up_b = rtl8821ae_delta_swing_table_idx_24gb_p; 1971 *down_b = rtl8821ae_delta_swing_table_idx_24gb_n; 1972 } 1973 } else if (36 <= channel && channel <= 64) { 1974 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0]; 1975 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0]; 1976 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[0]; 1977 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[0]; 1978 } else if (100 <= channel && channel <= 140) { 1979 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1]; 1980 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1]; 1981 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[1]; 1982 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[1]; 1983 } else if (149 <= channel && channel <= 173) { 1984 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2]; 1985 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2]; 1986 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[2]; 1987 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[2]; 1988 } else { 1989 *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; 1990 *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; 1991 *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; 1992 *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; 1993 } 1994 return; 1995 } 1996 1997 /*----------------------------------------------------------------------------- 1998 * Function: odm_TxPwrTrackSetPwr88E() 1999 * 2000 * Overview: 88E change all channel tx power accordign to flag. 2001 * OFDM & CCK are all different. 2002 * 2003 * Input: NONE 2004 * 2005 * Output: NONE 2006 * 2007 * Return: NONE 2008 * 2009 * Revised History: 2010 * When Who Remark 2011 * 04/23/2012 MHC Create Version 0. 2012 * 2013 *--------------------------------------------------------------------------- 2014 */ 2015 void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, 2016 enum pwr_track_control_method method, 2017 u8 rf_path, u8 channel_mapped_index) 2018 { 2019 struct rtl_priv *rtlpriv = rtl_priv(hw); 2020 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 2021 struct rtl_phy *rtlphy = &rtlpriv->phy; 2022 u32 final_swing_idx[1]; 2023 u8 pwr_tracking_limit = 26; /*+1.0dB*/ 2024 u8 tx_rate = 0xFF; 2025 s8 final_ofdm_swing_index = 0; 2026 2027 if (rtldm->tx_rate != 0xFF) 2028 tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); 2029 2030 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__); 2031 2032 if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/ 2033 /*CCK*/ 2034 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) 2035 pwr_tracking_limit = 32; /*+4dB*/ 2036 /*OFDM*/ 2037 else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) 2038 pwr_tracking_limit = 30; /*+3dB*/ 2039 else if (tx_rate == MGN_54M) 2040 pwr_tracking_limit = 28; /*+2dB*/ 2041 /*HT*/ 2042 /*QPSK/BPSK*/ 2043 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) 2044 pwr_tracking_limit = 34; /*+5dB*/ 2045 /*16QAM*/ 2046 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) 2047 pwr_tracking_limit = 30; /*+3dB*/ 2048 /*64QAM*/ 2049 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) 2050 pwr_tracking_limit = 28; /*+2dB*/ 2051 /*2 VHT*/ 2052 /*QPSK/BPSK*/ 2053 else if ((tx_rate >= MGN_VHT1SS_MCS0) && 2054 (tx_rate <= MGN_VHT1SS_MCS2)) 2055 pwr_tracking_limit = 34; /*+5dB*/ 2056 /*16QAM*/ 2057 else if ((tx_rate >= MGN_VHT1SS_MCS3) && 2058 (tx_rate <= MGN_VHT1SS_MCS4)) 2059 pwr_tracking_limit = 30; /*+3dB*/ 2060 /*64QAM*/ 2061 else if ((tx_rate >= MGN_VHT1SS_MCS5) && 2062 (tx_rate <= MGN_VHT1SS_MCS6)) 2063 pwr_tracking_limit = 28; /*+2dB*/ 2064 else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ 2065 pwr_tracking_limit = 26; /*+1dB*/ 2066 else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ 2067 pwr_tracking_limit = 24; /*+0dB*/ 2068 else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ 2069 pwr_tracking_limit = 22; /*-1dB*/ 2070 else 2071 pwr_tracking_limit = 24; 2072 } 2073 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2074 "TxRate=0x%x, PwrTrackingLimit=%d\n", 2075 tx_rate, pwr_tracking_limit); 2076 2077 if (method == BBSWING) { 2078 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2079 "===>%s\n", __func__); 2080 if (rf_path == RF90_PATH_A) { 2081 final_swing_idx[RF90_PATH_A] = 2082 (rtldm->ofdm_index[RF90_PATH_A] > 2083 pwr_tracking_limit) ? 2084 pwr_tracking_limit : 2085 rtldm->ofdm_index[RF90_PATH_A]; 2086 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2087 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", 2088 rtldm->ofdm_index[RF90_PATH_A], 2089 final_swing_idx[RF90_PATH_A]); 2090 2091 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 2092 txscaling_tbl[final_swing_idx[RF90_PATH_A]]); 2093 } 2094 } else if (method == MIX_MODE) { 2095 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2096 "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", 2097 rtldm->default_ofdm_index, 2098 rtldm->absolute_ofdm_swing_idx[rf_path], 2099 rf_path); 2100 2101 final_ofdm_swing_index = 2102 rtldm->default_ofdm_index + 2103 rtldm->absolute_ofdm_swing_idx[rf_path]; 2104 /*BBSwing higher then Limit*/ 2105 if (rf_path == RF90_PATH_A) { 2106 if (final_ofdm_swing_index > pwr_tracking_limit) { 2107 rtldm->remnant_cck_idx = 2108 final_ofdm_swing_index - 2109 pwr_tracking_limit; 2110 /* CCK Follow the same compensate value as Path A*/ 2111 rtldm->remnant_ofdm_swing_idx[rf_path] = 2112 final_ofdm_swing_index - 2113 pwr_tracking_limit; 2114 2115 rtl_set_bbreg(hw, RA_TXSCALE, 2116 0xFFE00000, 2117 txscaling_tbl[pwr_tracking_limit]); 2118 2119 rtldm->modify_txagc_flag_path_a = true; 2120 2121 /*Set TxAGC Page C{};*/ 2122 rtl8821ae_phy_set_txpower_level_by_path(hw, 2123 rtlphy->current_channel, 2124 RF90_PATH_A); 2125 2126 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2127 " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", 2128 pwr_tracking_limit, 2129 rtldm->remnant_ofdm_swing_idx[rf_path]); 2130 } else if (final_ofdm_swing_index < 0) { 2131 rtldm->remnant_cck_idx = final_ofdm_swing_index; 2132 /* CCK Follow the same compensate value as Path A*/ 2133 rtldm->remnant_ofdm_swing_idx[rf_path] = 2134 final_ofdm_swing_index; 2135 2136 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 2137 txscaling_tbl[0]); 2138 2139 rtldm->modify_txagc_flag_path_a = true; 2140 2141 /*Set TxAGC Page C{};*/ 2142 rtl8821ae_phy_set_txpower_level_by_path(hw, 2143 rtlphy->current_channel, RF90_PATH_A); 2144 2145 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2146 "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", 2147 rtldm->remnant_ofdm_swing_idx[rf_path]); 2148 } else { 2149 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, 2150 txscaling_tbl[(u8)final_ofdm_swing_index]); 2151 2152 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2153 "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", 2154 final_ofdm_swing_index); 2155 /*If TxAGC has changed, reset TxAGC again*/ 2156 if (rtldm->modify_txagc_flag_path_a) { 2157 rtldm->remnant_cck_idx = 0; 2158 rtldm->remnant_ofdm_swing_idx[rf_path] = 0; 2159 2160 /*Set TxAGC Page C{};*/ 2161 rtl8821ae_phy_set_txpower_level_by_path(hw, 2162 rtlphy->current_channel, RF90_PATH_A); 2163 2164 rtldm->modify_txagc_flag_path_a = false; 2165 2166 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, 2167 DBG_LOUD, 2168 "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n"); 2169 } 2170 } 2171 } 2172 } else { 2173 return; 2174 } 2175 } 2176 2177 void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( 2178 struct ieee80211_hw *hw) 2179 { 2180 struct rtl_priv *rtlpriv = rtl_priv(hw); 2181 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 2182 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 2183 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2184 struct rtl_phy *rtlphy = &rtlpriv->phy; 2185 2186 u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; 2187 u8 thermal_value_avg_count = 0; 2188 u32 thermal_value_avg = 0; 2189 2190 u8 ofdm_min_index = 6; /*OFDM BB Swing should be less than +3.0dB */ 2191 /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ 2192 u8 index_for_channel = 0; 2193 2194 /* 1. The following TWO tables decide the final 2195 * index of OFDM/CCK swing table. 2196 */ 2197 u8 *delta_swing_table_idx_tup_a; 2198 u8 *delta_swing_table_idx_tdown_a; 2199 u8 *delta_swing_table_idx_tup_b; 2200 u8 *delta_swing_table_idx_tdown_b; 2201 2202 /*2. Initilization ( 7 steps in total )*/ 2203 rtl8821ae_get_delta_swing_table(hw, (u8 **)&delta_swing_table_idx_tup_a, 2204 (u8 **)&delta_swing_table_idx_tdown_a, 2205 (u8 **)&delta_swing_table_idx_tup_b, 2206 (u8 **)&delta_swing_table_idx_tdown_b); 2207 2208 rtldm->txpower_trackinginit = true; 2209 2210 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2211 "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", 2212 __func__, 2213 rtldm->swing_idx_cck_base, 2214 rtldm->swing_idx_ofdm_base[RF90_PATH_A], 2215 rtldm->default_ofdm_index); 2216 /*0x42: RF Reg[15:10] 88E*/ 2217 thermal_value = (u8)rtl_get_rfreg(hw, 2218 RF90_PATH_A, RF_T_METER_8812A, 0xfc00); 2219 if (!rtldm->txpower_track_control || 2220 rtlefuse->eeprom_thermalmeter == 0 || 2221 rtlefuse->eeprom_thermalmeter == 0xFF) 2222 return; 2223 2224 /* 3. Initialize ThermalValues of RFCalibrateInfo*/ 2225 2226 if (rtlhal->reloadtxpowerindex) { 2227 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2228 "reload ofdm index for band switch\n"); 2229 } 2230 2231 /*4. Calculate average thermal meter*/ 2232 rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; 2233 rtldm->thermalvalue_avg_index++; 2234 if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) 2235 /*Average times = c.AverageThermalNum*/ 2236 rtldm->thermalvalue_avg_index = 0; 2237 2238 for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { 2239 if (rtldm->thermalvalue_avg[i]) { 2240 thermal_value_avg += rtldm->thermalvalue_avg[i]; 2241 thermal_value_avg_count++; 2242 } 2243 } 2244 /*Calculate Average ThermalValue after average enough times*/ 2245 if (thermal_value_avg_count) { 2246 thermal_value = (u8)(thermal_value_avg / 2247 thermal_value_avg_count); 2248 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2249 "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", 2250 thermal_value, rtlefuse->eeprom_thermalmeter); 2251 } 2252 2253 /*5. Calculate delta, delta_LCK, delta_IQK. 2254 *"delta" here is used to determine whether 2255 * thermal value changes or not. 2256 */ 2257 delta = (thermal_value > rtldm->thermalvalue) ? 2258 (thermal_value - rtldm->thermalvalue) : 2259 (rtldm->thermalvalue - thermal_value); 2260 delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? 2261 (thermal_value - rtldm->thermalvalue_lck) : 2262 (rtldm->thermalvalue_lck - thermal_value); 2263 delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? 2264 (thermal_value - rtldm->thermalvalue_iqk) : 2265 (rtldm->thermalvalue_iqk - thermal_value); 2266 2267 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2268 "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", 2269 delta, delta_lck, delta_iqk); 2270 2271 /* 6. If necessary, do LCK. */ 2272 /*Delta temperature is equal to or larger than 20 centigrade.*/ 2273 if (delta_lck >= IQK_THRESHOLD) { 2274 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2275 "delta_LCK(%d) >= Threshold_IQK(%d)\n", 2276 delta_lck, IQK_THRESHOLD); 2277 rtldm->thermalvalue_lck = thermal_value; 2278 rtl8821ae_phy_lc_calibrate(hw); 2279 } 2280 2281 /*7. If necessary, move the index of swing table to adjust Tx power.*/ 2282 2283 if (delta > 0 && rtldm->txpower_track_control) { 2284 /*"delta" here is used to record the 2285 * absolute value of differrence. 2286 */ 2287 delta = thermal_value > rtlefuse->eeprom_thermalmeter ? 2288 (thermal_value - rtlefuse->eeprom_thermalmeter) : 2289 (rtlefuse->eeprom_thermalmeter - thermal_value); 2290 2291 if (delta >= TXSCALE_TABLE_SIZE) 2292 delta = TXSCALE_TABLE_SIZE - 1; 2293 2294 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ 2295 2296 if (thermal_value > rtlefuse->eeprom_thermalmeter) { 2297 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2298 "delta_swing_table_idx_tup_a[%d] = %d\n", 2299 delta, delta_swing_table_idx_tup_a[delta]); 2300 rtldm->delta_power_index_last[RF90_PATH_A] = 2301 rtldm->delta_power_index[RF90_PATH_A]; 2302 rtldm->delta_power_index[RF90_PATH_A] = 2303 delta_swing_table_idx_tup_a[delta]; 2304 2305 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = 2306 delta_swing_table_idx_tup_a[delta]; 2307 /*Record delta swing for mix mode power tracking*/ 2308 2309 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2310 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", 2311 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); 2312 } else { 2313 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2314 "delta_swing_table_idx_tdown_a[%d] = %d\n", 2315 delta, delta_swing_table_idx_tdown_a[delta]); 2316 2317 rtldm->delta_power_index_last[RF90_PATH_A] = 2318 rtldm->delta_power_index[RF90_PATH_A]; 2319 rtldm->delta_power_index[RF90_PATH_A] = 2320 -1 * delta_swing_table_idx_tdown_a[delta]; 2321 2322 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = 2323 -1 * delta_swing_table_idx_tdown_a[delta]; 2324 /* Record delta swing for mix mode power tracking*/ 2325 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2326 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", 2327 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); 2328 } 2329 2330 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { 2331 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2332 "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n", 2333 (p == RF90_PATH_A ? 'A' : 'B')); 2334 /*If Thermal value changes but lookup table value 2335 * still the same 2336 */ 2337 if (rtldm->delta_power_index[p] == 2338 rtldm->delta_power_index_last[p]) 2339 2340 rtldm->power_index_offset[p] = 0; 2341 else 2342 rtldm->power_index_offset[p] = 2343 rtldm->delta_power_index[p] - 2344 rtldm->delta_power_index_last[p]; 2345 /*Power Index Diff between 2 times Power Tracking*/ 2346 2347 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2348 "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n", 2349 (p == RF90_PATH_A ? 'A' : 'B'), 2350 rtldm->power_index_offset[p], 2351 rtldm->delta_power_index[p] , 2352 rtldm->delta_power_index_last[p]); 2353 2354 rtldm->ofdm_index[p] = 2355 rtldm->swing_idx_ofdm_base[p] + 2356 rtldm->power_index_offset[p]; 2357 rtldm->cck_index = 2358 rtldm->swing_idx_cck_base + 2359 rtldm->power_index_offset[p]; 2360 2361 rtldm->swing_idx_cck = rtldm->cck_index; 2362 rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; 2363 2364 /*********Print BB Swing Base and Index Offset********/ 2365 2366 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2367 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", 2368 rtldm->swing_idx_cck, 2369 rtldm->swing_idx_cck_base, 2370 rtldm->power_index_offset[p]); 2371 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2372 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", 2373 rtldm->swing_idx_ofdm[p], 2374 (p == RF90_PATH_A ? 'A' : 'B'), 2375 rtldm->swing_idx_ofdm_base[p], 2376 rtldm->power_index_offset[p]); 2377 2378 /*7.1 Handle boundary conditions of index.*/ 2379 2380 if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) 2381 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; 2382 else if (rtldm->ofdm_index[p] < ofdm_min_index) 2383 rtldm->ofdm_index[p] = ofdm_min_index; 2384 } 2385 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2386 "\n\n========================================================================================================\n"); 2387 if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) 2388 rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; 2389 else if (rtldm->cck_index < 0) 2390 rtldm->cck_index = 0; 2391 } else { 2392 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2393 "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", 2394 rtldm->txpower_track_control, 2395 thermal_value, 2396 rtldm->thermalvalue); 2397 2398 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) 2399 rtldm->power_index_offset[p] = 0; 2400 } 2401 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2402 "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n", 2403 /*Print Swing base & current*/ 2404 rtldm->cck_index, rtldm->swing_idx_cck_base); 2405 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { 2406 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2407 "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n", 2408 rtldm->ofdm_index[p], 2409 (p == RF90_PATH_A ? 'A' : 'B'), 2410 rtldm->swing_idx_ofdm_base[p]); 2411 } 2412 2413 if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || 2414 rtldm->power_index_offset[RF90_PATH_B] != 0) && 2415 rtldm->txpower_track_control) { 2416 /*7.2 Configure the Swing Table to adjust Tx Power.*/ 2417 /*Always TRUE after Tx Power is adjusted by power tracking.*/ 2418 /* 2419 * 2012/04/23 MH According to Luke's suggestion, 2420 * we can not write BB digital 2421 * to increase TX power. Otherwise, EVM will be bad. 2422 * 2423 * 2012/04/25 MH Add for tx power tracking to 2424 * set tx power in tx agc for 88E. 2425 */ 2426 if (thermal_value > rtldm->thermalvalue) { 2427 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2428 "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n", 2429 rtldm->power_index_offset[RF90_PATH_A], 2430 delta, thermal_value, 2431 rtlefuse->eeprom_thermalmeter, 2432 rtldm->thermalvalue); 2433 } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ 2434 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2435 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", 2436 rtldm->power_index_offset[RF90_PATH_A], 2437 delta, thermal_value, 2438 rtlefuse->eeprom_thermalmeter, 2439 rtldm->thermalvalue); 2440 } 2441 2442 if (thermal_value > rtlefuse->eeprom_thermalmeter) { 2443 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2444 "Temperature(%d) higher than PG value(%d)\n", 2445 thermal_value, rtlefuse->eeprom_thermalmeter); 2446 2447 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2448 "****Enter POWER Tracking MIX_MODE****\n"); 2449 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) 2450 rtl8821ae_dm_txpwr_track_set_pwr(hw, 2451 MIX_MODE, p, index_for_channel); 2452 } else { 2453 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2454 "Temperature(%d) lower than PG value(%d)\n", 2455 thermal_value, rtlefuse->eeprom_thermalmeter); 2456 2457 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2458 "*****Enter POWER Tracking MIX_MODE*****\n"); 2459 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) 2460 rtl8812ae_dm_txpwr_track_set_pwr(hw, 2461 MIX_MODE, p, index_for_channel); 2462 } 2463 /*Record last time Power Tracking result as base.*/ 2464 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; 2465 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) 2466 rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p]; 2467 2468 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2469 "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n", 2470 rtldm->thermalvalue, thermal_value); 2471 /*Record last Power Tracking Thermal Value*/ 2472 rtldm->thermalvalue = thermal_value; 2473 } 2474 /* Delta temperature is equal to or larger than 2475 * 20 centigrade (When threshold is 8). 2476 */ 2477 if (delta_iqk >= IQK_THRESHOLD) { 2478 if (!rtlphy->lck_inprogress) { 2479 spin_lock(&rtlpriv->locks.iqk_lock); 2480 rtlphy->lck_inprogress = true; 2481 spin_unlock(&rtlpriv->locks.iqk_lock); 2482 2483 rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8); 2484 2485 spin_lock(&rtlpriv->locks.iqk_lock); 2486 rtlphy->lck_inprogress = false; 2487 spin_unlock(&rtlpriv->locks.iqk_lock); 2488 } 2489 } 2490 2491 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__); 2492 } 2493 2494 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw) 2495 { 2496 struct rtl_priv *rtlpriv = rtl_priv(hw); 2497 if (!rtlpriv->dm.tm_trigger) { 2498 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16), 2499 0x03); 2500 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2501 "Trigger 8821ae Thermal Meter!!\n"); 2502 rtlpriv->dm.tm_trigger = 1; 2503 return; 2504 } else { 2505 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 2506 "Schedule TxPowerTracking !!\n"); 2507 2508 rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw); 2509 rtlpriv->dm.tm_trigger = 0; 2510 } 2511 } 2512 2513 static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) 2514 { 2515 struct rtl_priv *rtlpriv = rtl_priv(hw); 2516 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2517 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 2518 struct rate_adaptive *p_ra = &rtlpriv->ra; 2519 u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; 2520 u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; 2521 u8 go_up_gap = 5; 2522 struct ieee80211_sta *sta = NULL; 2523 2524 if (is_hal_stop(rtlhal)) { 2525 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 2526 "driver is going to unload\n"); 2527 return; 2528 } 2529 2530 if (!rtlpriv->dm.useramask) { 2531 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 2532 "driver does not control rate adaptive mask\n"); 2533 return; 2534 } 2535 2536 if (mac->link_state == MAC80211_LINKED && 2537 mac->opmode == NL80211_IFTYPE_STATION) { 2538 switch (p_ra->pre_ratr_state) { 2539 case DM_RATR_STA_MIDDLE: 2540 high_rssithresh_for_ra += go_up_gap; 2541 break; 2542 case DM_RATR_STA_LOW: 2543 high_rssithresh_for_ra += go_up_gap; 2544 low_rssithresh_for_ra += go_up_gap; 2545 break; 2546 default: 2547 break; 2548 } 2549 2550 if (rtlpriv->dm.undec_sm_pwdb > 2551 (long)high_rssithresh_for_ra) 2552 p_ra->ratr_state = DM_RATR_STA_HIGH; 2553 else if (rtlpriv->dm.undec_sm_pwdb > 2554 (long)low_rssithresh_for_ra) 2555 p_ra->ratr_state = DM_RATR_STA_MIDDLE; 2556 else 2557 p_ra->ratr_state = DM_RATR_STA_LOW; 2558 2559 if (p_ra->pre_ratr_state != p_ra->ratr_state) { 2560 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 2561 "RSSI = %ld\n", 2562 rtlpriv->dm.undec_sm_pwdb); 2563 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 2564 "RSSI_LEVEL = %d\n", p_ra->ratr_state); 2565 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 2566 "PreState = %d, CurState = %d\n", 2567 p_ra->pre_ratr_state, p_ra->ratr_state); 2568 2569 rcu_read_lock(); 2570 sta = rtl_find_sta(hw, mac->bssid); 2571 if (sta) 2572 rtlpriv->cfg->ops->update_rate_tbl(hw, 2573 sta, p_ra->ratr_state, true); 2574 rcu_read_unlock(); 2575 2576 p_ra->pre_ratr_state = p_ra->ratr_state; 2577 } 2578 } 2579 } 2580 2581 static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw) 2582 { 2583 struct rtl_priv *rtlpriv = rtl_priv(hw); 2584 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 2585 struct rtl_mac *mac = &rtlpriv->mac80211; 2586 static u8 stage; 2587 u8 cur_stage = 0; 2588 u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M; 2589 2590 if (mac->link_state < MAC80211_LINKED) 2591 cur_stage = 0; 2592 else if (dm_digtable->rssi_val_min < 25) 2593 cur_stage = 1; 2594 else if (dm_digtable->rssi_val_min > 30) 2595 cur_stage = 3; 2596 else 2597 cur_stage = 2; 2598 2599 if (cur_stage != stage) { 2600 if (cur_stage == 1) { 2601 basic_rate &= (!(basic_rate ^ mac->basic_rates)); 2602 rtlpriv->cfg->ops->set_hw_reg(hw, 2603 HW_VAR_BASIC_RATE, (u8 *)&basic_rate); 2604 } else if (cur_stage == 3 && (stage == 1 || stage == 2)) { 2605 rtlpriv->cfg->ops->set_hw_reg(hw, 2606 HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates); 2607 } 2608 } 2609 stage = cur_stage; 2610 } 2611 2612 static void rtl8821ae_dm_edca_choose_traffic_idx( 2613 struct ieee80211_hw *hw, u64 cur_tx_bytes, 2614 u64 cur_rx_bytes, bool b_bias_on_rx, 2615 bool *pb_is_cur_rdl_state) 2616 { 2617 struct rtl_priv *rtlpriv = rtl_priv(hw); 2618 2619 if (b_bias_on_rx) { 2620 if (cur_tx_bytes > (cur_rx_bytes*4)) { 2621 *pb_is_cur_rdl_state = false; 2622 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2623 "Uplink Traffic\n"); 2624 } else { 2625 *pb_is_cur_rdl_state = true; 2626 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2627 "Balance Traffic\n"); 2628 } 2629 } else { 2630 if (cur_rx_bytes > (cur_tx_bytes*4)) { 2631 *pb_is_cur_rdl_state = true; 2632 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2633 "Downlink Traffic\n"); 2634 } else { 2635 *pb_is_cur_rdl_state = false; 2636 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2637 "Balance Traffic\n"); 2638 } 2639 } 2640 return; 2641 } 2642 2643 static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw) 2644 { 2645 struct rtl_priv *rtlpriv = rtl_priv(hw); 2646 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 2647 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 2648 2649 /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/ 2650 u64 cur_tx_ok_cnt = 0; 2651 u64 cur_rx_ok_cnt = 0; 2652 u32 edca_be_ul = 0x5ea42b; 2653 u32 edca_be_dl = 0x5ea42b; 2654 u32 edca_be = 0x5ea42b; 2655 u8 iot_peer = 0; 2656 bool *pb_is_cur_rdl_state = NULL; 2657 bool b_last_is_cur_rdl_state = false; 2658 bool b_bias_on_rx = false; 2659 bool b_edca_turbo_on = false; 2660 2661 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2662 "rtl8821ae_dm_check_edca_turbo=====>\n"); 2663 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2664 "Original BE PARAM: 0x%x\n", 2665 rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)); 2666 2667 if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100) 2668 rtlpriv->dm.is_any_nonbepkts = true; 2669 rtlpriv->dm.dbginfo.num_non_be_pkt = 0; 2670 2671 /*=============================== 2672 * list paramter for different platform 2673 *=============================== 2674 */ 2675 b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate; 2676 pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate; 2677 2678 cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt; 2679 cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt; 2680 2681 rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; 2682 rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; 2683 2684 iot_peer = rtlpriv->mac80211.vendor; 2685 b_bias_on_rx = false; 2686 b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && 2687 (!rtlpriv->dm.disable_framebursting)) ? 2688 true : false; 2689 2690 if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) { 2691 if ((iot_peer == PEER_CISCO) && 2692 (mac->mode == WIRELESS_MODE_N_24G)) { 2693 edca_be_dl = edca_setting_dl[iot_peer]; 2694 edca_be_ul = edca_setting_ul[iot_peer]; 2695 } 2696 } 2697 2698 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2699 "bIsAnyNonBEPkts : 0x%x bDisableFrameBursting : 0x%x\n", 2700 rtlpriv->dm.is_any_nonbepkts, 2701 rtlpriv->dm.disable_framebursting); 2702 2703 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2704 "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n", 2705 b_edca_turbo_on, b_bias_on_rx); 2706 2707 if (b_edca_turbo_on) { 2708 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2709 "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt); 2710 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2711 "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt); 2712 if (b_bias_on_rx) 2713 rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, 2714 cur_rx_ok_cnt, true, pb_is_cur_rdl_state); 2715 else 2716 rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, 2717 cur_rx_ok_cnt, false, pb_is_cur_rdl_state); 2718 2719 edca_be = (*pb_is_cur_rdl_state) ? edca_be_dl : edca_be_ul; 2720 2721 rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be); 2722 2723 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2724 "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be); 2725 2726 rtlpriv->dm.current_turbo_edca = true; 2727 2728 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, 2729 "EDCA_BE_DL : 0x%x EDCA_BE_UL : 0x%x EDCA_BE : 0x%x\n", 2730 edca_be_dl, edca_be_ul, edca_be); 2731 } else { 2732 if (rtlpriv->dm.current_turbo_edca) { 2733 u8 tmp = AC0_BE; 2734 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, 2735 (u8 *)(&tmp)); 2736 } 2737 rtlpriv->dm.current_turbo_edca = false; 2738 } 2739 2740 rtlpriv->dm.is_any_nonbepkts = false; 2741 rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; 2742 rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; 2743 } 2744 2745 static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) 2746 { 2747 struct rtl_priv *rtlpriv = rtl_priv(hw); 2748 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 2749 u8 cur_cck_cca_thresh; 2750 2751 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { 2752 if (dm_digtable->rssi_val_min > 25) { 2753 cur_cck_cca_thresh = 0xcd; 2754 } else if ((dm_digtable->rssi_val_min <= 25) && 2755 (dm_digtable->rssi_val_min > 10)) { 2756 cur_cck_cca_thresh = 0x83; 2757 } else { 2758 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) 2759 cur_cck_cca_thresh = 0x83; 2760 else 2761 cur_cck_cca_thresh = 0x40; 2762 } 2763 } else { 2764 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) 2765 cur_cck_cca_thresh = 0x83; 2766 else 2767 cur_cck_cca_thresh = 0x40; 2768 } 2769 2770 if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) 2771 rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC, 2772 cur_cck_cca_thresh); 2773 2774 dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; 2775 dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; 2776 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, 2777 "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); 2778 } 2779 2780 static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw) 2781 { 2782 struct rtl_priv *rtlpriv = rtl_priv(hw); 2783 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 2784 u8 crystal_cap; 2785 u32 packet_count; 2786 int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; 2787 int cfo_ave_diff; 2788 2789 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { 2790 /*1.Enable ATC*/ 2791 if (rtldm->atc_status == ATC_STATUS_OFF) { 2792 rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON); 2793 rtldm->atc_status = ATC_STATUS_ON; 2794 } 2795 2796 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n"); 2797 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2798 "atc_status = %d\n", rtldm->atc_status); 2799 2800 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { 2801 rtldm->crystal_cap = rtlpriv->efuse.crystalcap; 2802 crystal_cap = rtldm->crystal_cap & 0x3f; 2803 crystal_cap = crystal_cap & 0x3f; 2804 if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) 2805 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 2806 0x7ff80000, (crystal_cap | 2807 (crystal_cap << 6))); 2808 else 2809 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 2810 0xfff000, (crystal_cap | 2811 (crystal_cap << 6))); 2812 } 2813 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n", 2814 rtldm->crystal_cap); 2815 } else{ 2816 /*1. Calculate CFO for path-A & path-B*/ 2817 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; 2818 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; 2819 packet_count = rtldm->packet_count; 2820 2821 /*2.No new packet*/ 2822 if (packet_count == rtldm->packet_count_pre) { 2823 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2824 "packet counter doesn't change\n"); 2825 return; 2826 } 2827 2828 rtldm->packet_count_pre = packet_count; 2829 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2830 "packet counter = %d\n", 2831 rtldm->packet_count); 2832 2833 /*3.Average CFO*/ 2834 if (rtlpriv->phy.rf_type == RF_1T1R) 2835 cfo_ave = cfo_khz_a; 2836 else 2837 cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1; 2838 2839 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2840 "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n", 2841 cfo_khz_a, cfo_khz_b, cfo_ave); 2842 2843 /*4.Avoid abnormal large CFO*/ 2844 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? 2845 (rtldm->cfo_ave_pre - cfo_ave) : 2846 (cfo_ave - rtldm->cfo_ave_pre); 2847 2848 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { 2849 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2850 "first large CFO hit\n"); 2851 rtldm->large_cfo_hit = 1; 2852 return; 2853 } else 2854 rtldm->large_cfo_hit = 0; 2855 2856 rtldm->cfo_ave_pre = cfo_ave; 2857 2858 /*CFO tracking by adjusting Xtal cap.*/ 2859 2860 /*1.Dynamic Xtal threshold*/ 2861 if (cfo_ave >= -rtldm->cfo_threshold && 2862 cfo_ave <= rtldm->cfo_threshold && 2863 rtldm->is_freeze == 0) { 2864 if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { 2865 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; 2866 rtldm->is_freeze = 1; 2867 } else { 2868 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; 2869 } 2870 } 2871 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2872 "Dynamic threshold = %d\n", 2873 rtldm->cfo_threshold); 2874 2875 /* 2.Calculate Xtal offset*/ 2876 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) 2877 adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1; 2878 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && 2879 rtlpriv->dm.crystal_cap > 0) 2880 adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1; 2881 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2882 "Crystal cap = 0x%x, Crystal cap offset = %d\n", 2883 rtldm->crystal_cap, adjust_xtal); 2884 2885 /*3.Adjudt Crystal Cap.*/ 2886 if (adjust_xtal != 0) { 2887 rtldm->is_freeze = 0; 2888 rtldm->crystal_cap += adjust_xtal; 2889 2890 if (rtldm->crystal_cap > 0x3f) 2891 rtldm->crystal_cap = 0x3f; 2892 else if (rtldm->crystal_cap < 0) 2893 rtldm->crystal_cap = 0; 2894 2895 crystal_cap = rtldm->crystal_cap & 0x3f; 2896 crystal_cap = crystal_cap & 0x3f; 2897 if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) 2898 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 2899 0x7ff80000, (crystal_cap | 2900 (crystal_cap << 6))); 2901 else 2902 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 2903 0xfff000, (crystal_cap | 2904 (crystal_cap << 6))); 2905 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, 2906 "New crystal cap = 0x%x\n", 2907 rtldm->crystal_cap); 2908 } 2909 } 2910 } 2911 2912 void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw) 2913 { 2914 struct rtl_priv *rtlpriv = rtl_priv(hw); 2915 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 2916 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2917 bool fw_current_inpsmode = false; 2918 bool fw_ps_awake = true; 2919 2920 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, 2921 (u8 *)(&fw_current_inpsmode)); 2922 2923 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, 2924 (u8 *)(&fw_ps_awake)); 2925 2926 if (ppsc->p2p_ps_info.p2p_ps_mode) 2927 fw_ps_awake = false; 2928 2929 spin_lock(&rtlpriv->locks.rf_ps_lock); 2930 if ((ppsc->rfpwr_state == ERFON) && 2931 ((!fw_current_inpsmode) && fw_ps_awake) && 2932 (!ppsc->rfchange_inprogress)) { 2933 rtl8821ae_dm_common_info_self_update(hw); 2934 rtl8821ae_dm_false_alarm_counter_statistics(hw); 2935 rtl8821ae_dm_check_rssi_monitor(hw); 2936 rtl8821ae_dm_dig(hw); 2937 rtl8821ae_dm_cck_packet_detection_thresh(hw); 2938 rtl8821ae_dm_refresh_rate_adaptive_mask(hw); 2939 rtl8821ae_dm_refresh_basic_rate_mask(hw); 2940 rtl8821ae_dm_check_edca_turbo(hw); 2941 rtl8821ae_dm_dynamic_atc_switch(hw); 2942 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 2943 rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw); 2944 else 2945 rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw); 2946 rtl8821ae_dm_iq_calibrate(hw); 2947 } 2948 spin_unlock(&rtlpriv->locks.rf_ps_lock); 2949 2950 rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; 2951 RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n"); 2952 } 2953 2954 void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, 2955 u8 *pdesc, u32 mac_id) 2956 { 2957 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 2958 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 2959 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 2960 struct fast_ant_training *pfat_table = &rtldm->fat_table; 2961 2962 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE) 2963 return; 2964 2965 if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) 2966 SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]); 2967 } 2968