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