Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[deliverable/linux.git] / drivers / net / wireless / realtek / rtlwifi / rtl8192c / dm_common.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2009-2012 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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
25 *
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *
28 *****************************************************************************/
29
30 #include <linux/export.h>
31 #include "dm_common.h"
32 #include "phy_common.h"
33 #include "../pci.h"
34 #include "../base.h"
35 #include "../core.h"
36
37 #define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1)
38 #define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1)
39 #define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1)
40 #define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1)
41 #define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1)
42 #define BT_MASK 0x00ffffff
43
44 #define RTLPRIV (struct rtl_priv *)
45 #define GET_UNDECORATED_AVERAGE_RSSI(_priv) \
46 ((RTLPRIV(_priv))->mac80211.opmode == \
47 NL80211_IFTYPE_ADHOC) ? \
48 ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
49 ((RTLPRIV(_priv))->dm.undec_sm_pwdb)
50
51 static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
52 0x7f8001fe,
53 0x788001e2,
54 0x71c001c7,
55 0x6b8001ae,
56 0x65400195,
57 0x5fc0017f,
58 0x5a400169,
59 0x55400155,
60 0x50800142,
61 0x4c000130,
62 0x47c0011f,
63 0x43c0010f,
64 0x40000100,
65 0x3c8000f2,
66 0x390000e4,
67 0x35c000d7,
68 0x32c000cb,
69 0x300000c0,
70 0x2d4000b5,
71 0x2ac000ab,
72 0x288000a2,
73 0x26000098,
74 0x24000090,
75 0x22000088,
76 0x20000080,
77 0x1e400079,
78 0x1c800072,
79 0x1b00006c,
80 0x19800066,
81 0x18000060,
82 0x16c0005b,
83 0x15800056,
84 0x14400051,
85 0x1300004c,
86 0x12000048,
87 0x11000044,
88 0x10000040,
89 };
90
91 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
92 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
93 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
94 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
95 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
96 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
97 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
98 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
99 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
100 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
101 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
102 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
103 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
104 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
105 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
106 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
107 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
108 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
109 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
110 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
111 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
112 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
113 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
114 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
115 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
116 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
117 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
118 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
119 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
120 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
121 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
122 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
123 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
124 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
125 };
126
127 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
128 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
129 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
130 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
131 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
132 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
133 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
134 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
135 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
136 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
137 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
138 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
139 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
140 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
141 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
142 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
143 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
144 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
145 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
146 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
147 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
148 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
149 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
150 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
151 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
152 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
153 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
154 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
155 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
156 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
157 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
158 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
159 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
160 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
161 };
162
163 static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
164
165 void dm_restorepowerindex(struct ieee80211_hw *hw)
166 {
167 struct rtl_priv *rtlpriv = rtl_priv(hw);
168 u8 index;
169
170 for (index = 0; index < 6; index++)
171 rtl_write_byte(rtlpriv, power_index_reg[index],
172 rtlpriv->dm.powerindex_backup[index]);
173 }
174 EXPORT_SYMBOL_GPL(dm_restorepowerindex);
175
176 void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)
177 {
178 struct rtl_priv *rtlpriv = rtl_priv(hw);
179 u8 index;
180
181 for (index = 0; index < 6; index++)
182 rtl_write_byte(rtlpriv, power_index_reg[index], value);
183 }
184 EXPORT_SYMBOL_GPL(dm_writepowerindex);
185
186 void dm_savepowerindex(struct ieee80211_hw *hw)
187 {
188 struct rtl_priv *rtlpriv = rtl_priv(hw);
189 u8 index;
190 u8 tmp;
191
192 for (index = 0; index < 6; index++) {
193 tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);
194 rtlpriv->dm.powerindex_backup[index] = tmp;
195 }
196 }
197 EXPORT_SYMBOL_GPL(dm_savepowerindex);
198
199 static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
200 {
201 struct rtl_priv *rtlpriv = rtl_priv(hw);
202 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
203 long rssi_val_min = 0;
204
205 if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
206 (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
207 if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
208 rssi_val_min =
209 (rtlpriv->dm.entry_min_undec_sm_pwdb >
210 rtlpriv->dm.undec_sm_pwdb) ?
211 rtlpriv->dm.undec_sm_pwdb :
212 rtlpriv->dm.entry_min_undec_sm_pwdb;
213 else
214 rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
215 } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
216 dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
217 rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
218 } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
219 rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
220 }
221
222 if (rssi_val_min > 100)
223 rssi_val_min = 100;
224 return (u8)rssi_val_min;
225 }
226
227 static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
228 {
229 u32 ret_value;
230 struct rtl_priv *rtlpriv = rtl_priv(hw);
231 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
232
233 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
234 falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
235
236 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
237 falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
238 falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
239
240 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
241 falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
242
243 ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
244 falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
245 falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
246
247 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
248 falsealm_cnt->cnt_rate_illegal +
249 falsealm_cnt->cnt_crc8_fail +
250 falsealm_cnt->cnt_mcs_fail +
251 falsealm_cnt->cnt_fast_fsync_fail +
252 falsealm_cnt->cnt_sb_search_fail;
253
254 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
255 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
256 falsealm_cnt->cnt_cck_fail = ret_value;
257
258 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
259 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
260 falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
261 falsealm_cnt->cnt_rate_illegal +
262 falsealm_cnt->cnt_crc8_fail +
263 falsealm_cnt->cnt_mcs_fail +
264 falsealm_cnt->cnt_cck_fail);
265
266 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
267 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
268 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
269 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
270
271 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
272 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
273 falsealm_cnt->cnt_parity_fail,
274 falsealm_cnt->cnt_rate_illegal,
275 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
276
277 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
278 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
279 falsealm_cnt->cnt_ofdm_fail,
280 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
281 }
282
283 static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
284 {
285 struct rtl_priv *rtlpriv = rtl_priv(hw);
286 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
287 u8 value_igi = dm_digtable->cur_igvalue;
288
289 if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
290 value_igi--;
291 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
292 value_igi += 0;
293 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
294 value_igi++;
295 else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
296 value_igi += 2;
297
298 if (value_igi > DM_DIG_FA_UPPER)
299 value_igi = DM_DIG_FA_UPPER;
300 else if (value_igi < DM_DIG_FA_LOWER)
301 value_igi = DM_DIG_FA_LOWER;
302
303 if (rtlpriv->falsealm_cnt.cnt_all > 10000)
304 value_igi = DM_DIG_FA_UPPER;
305
306 dm_digtable->cur_igvalue = value_igi;
307 rtl92c_dm_write_dig(hw);
308 }
309
310 static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
311 {
312 struct rtl_priv *rtlpriv = rtl_priv(hw);
313 struct dig_t *digtable = &rtlpriv->dm_digtable;
314 u32 isbt;
315
316 /* modify DIG lower bound, deal with abnormally large false alarm */
317 if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
318 digtable->large_fa_hit++;
319 if (digtable->forbidden_igi < digtable->cur_igvalue) {
320 digtable->forbidden_igi = digtable->cur_igvalue;
321 digtable->large_fa_hit = 1;
322 }
323
324 if (digtable->large_fa_hit >= 3) {
325 if ((digtable->forbidden_igi + 1) >
326 digtable->rx_gain_max)
327 digtable->rx_gain_min = digtable->rx_gain_max;
328 else
329 digtable->rx_gain_min = (digtable->forbidden_igi + 1);
330 digtable->recover_cnt = 3600; /* 3600=2hr */
331 }
332 } else {
333 /* Recovery mechanism for IGI lower bound */
334 if (digtable->recover_cnt != 0) {
335 digtable->recover_cnt--;
336 } else {
337 if (digtable->large_fa_hit == 0) {
338 if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
339 digtable->forbidden_igi = DM_DIG_MIN;
340 digtable->rx_gain_min = DM_DIG_MIN;
341 } else {
342 digtable->forbidden_igi--;
343 digtable->rx_gain_min = digtable->forbidden_igi + 1;
344 }
345 } else if (digtable->large_fa_hit == 3) {
346 digtable->large_fa_hit = 0;
347 }
348 }
349 }
350 if (rtlpriv->falsealm_cnt.cnt_all < 250) {
351 isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;
352
353 if (!isbt) {
354 if (rtlpriv->falsealm_cnt.cnt_all >
355 digtable->fa_lowthresh) {
356 if ((digtable->back_val - 2) <
357 digtable->back_range_min)
358 digtable->back_val = digtable->back_range_min;
359 else
360 digtable->back_val -= 2;
361 } else if (rtlpriv->falsealm_cnt.cnt_all <
362 digtable->fa_lowthresh) {
363 if ((digtable->back_val + 2) >
364 digtable->back_range_max)
365 digtable->back_val = digtable->back_range_max;
366 else
367 digtable->back_val += 2;
368 }
369 } else {
370 digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
371 }
372 } else {
373 /* Adjust initial gain by false alarm */
374 if (rtlpriv->falsealm_cnt.cnt_all > 1000)
375 digtable->cur_igvalue = digtable->pre_igvalue + 2;
376 else if (rtlpriv->falsealm_cnt.cnt_all > 750)
377 digtable->cur_igvalue = digtable->pre_igvalue + 1;
378 else if (rtlpriv->falsealm_cnt.cnt_all < 500)
379 digtable->cur_igvalue = digtable->pre_igvalue - 1;
380 }
381
382 /* Check initial gain by upper/lower bound */
383 if (digtable->cur_igvalue > digtable->rx_gain_max)
384 digtable->cur_igvalue = digtable->rx_gain_max;
385
386 if (digtable->cur_igvalue < digtable->rx_gain_min)
387 digtable->cur_igvalue = digtable->rx_gain_min;
388
389 rtl92c_dm_write_dig(hw);
390 }
391
392 static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
393 {
394 static u8 initialized; /* initialized to false */
395 struct rtl_priv *rtlpriv = rtl_priv(hw);
396 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
397 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
398 long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
399 bool multi_sta = false;
400
401 if (mac->opmode == NL80211_IFTYPE_ADHOC)
402 multi_sta = true;
403
404 if (!multi_sta ||
405 dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {
406 initialized = false;
407 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
408 return;
409 } else if (initialized == false) {
410 initialized = true;
411 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
412 dm_digtable->cur_igvalue = 0x20;
413 rtl92c_dm_write_dig(hw);
414 }
415
416 if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
417 if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
418 (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
419
420 if (dm_digtable->dig_ext_port_stage ==
421 DIG_EXT_PORT_STAGE_2) {
422 dm_digtable->cur_igvalue = 0x20;
423 rtl92c_dm_write_dig(hw);
424 }
425
426 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
427 } else if (rssi_strength > dm_digtable->rssi_highthresh) {
428 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
429 rtl92c_dm_ctrl_initgain_by_fa(hw);
430 }
431 } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
432 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
433 dm_digtable->cur_igvalue = 0x20;
434 rtl92c_dm_write_dig(hw);
435 }
436
437 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
438 "curmultista_cstate = %x dig_ext_port_stage %x\n",
439 dm_digtable->curmultista_cstate,
440 dm_digtable->dig_ext_port_stage);
441 }
442
443 static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
444 {
445 struct rtl_priv *rtlpriv = rtl_priv(hw);
446 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
447
448 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
449 "presta_cstate = %x, cursta_cstate = %x\n",
450 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
451 if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
452 dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
453 dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
454
455 if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
456 dm_digtable->rssi_val_min =
457 rtl92c_dm_initial_gain_min_pwdb(hw);
458 if (dm_digtable->rssi_val_min > 100)
459 dm_digtable->rssi_val_min = 100;
460 rtl92c_dm_ctrl_initgain_by_rssi(hw);
461 }
462 } else {
463 dm_digtable->rssi_val_min = 0;
464 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
465 dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
466 dm_digtable->cur_igvalue = 0x20;
467 dm_digtable->pre_igvalue = 0;
468 rtl92c_dm_write_dig(hw);
469 }
470 }
471
472 static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
473 {
474 struct rtl_priv *rtlpriv = rtl_priv(hw);
475 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
476
477 if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
478 dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
479 if (dm_digtable->rssi_val_min > 100)
480 dm_digtable->rssi_val_min = 100;
481
482 if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
483 if (dm_digtable->rssi_val_min <= 25)
484 dm_digtable->cur_cck_pd_state =
485 CCK_PD_STAGE_LOWRSSI;
486 else
487 dm_digtable->cur_cck_pd_state =
488 CCK_PD_STAGE_HIGHRSSI;
489 } else {
490 if (dm_digtable->rssi_val_min <= 20)
491 dm_digtable->cur_cck_pd_state =
492 CCK_PD_STAGE_LOWRSSI;
493 else
494 dm_digtable->cur_cck_pd_state =
495 CCK_PD_STAGE_HIGHRSSI;
496 }
497 } else {
498 dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
499 }
500
501 if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
502 if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) ||
503 (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))
504 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
505 else
506 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
507
508 dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
509 }
510 }
511
512 static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
513 {
514 struct rtl_priv *rtlpriv = rtl_priv(hw);
515 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
516 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
517
518 if (mac->act_scanning)
519 return;
520
521 if (mac->link_state >= MAC80211_LINKED)
522 dm_digtable->cursta_cstate = DIG_STA_CONNECT;
523 else
524 dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
525
526 dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
527
528 rtl92c_dm_initial_gain_sta(hw);
529 rtl92c_dm_initial_gain_multi_sta(hw);
530 rtl92c_dm_cck_packet_detection_thresh(hw);
531
532 dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
533
534 }
535
536 static void rtl92c_dm_dig(struct ieee80211_hw *hw)
537 {
538 struct rtl_priv *rtlpriv = rtl_priv(hw);
539
540 if (rtlpriv->dm.dm_initialgain_enable == false)
541 return;
542 if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
543 return;
544
545 rtl92c_dm_ctrl_initgain_by_twoport(hw);
546 }
547
548 static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
549 {
550 struct rtl_priv *rtlpriv = rtl_priv(hw);
551
552 if (rtlpriv->rtlhal.interface == INTF_USB &&
553 rtlpriv->rtlhal.board_type & 0x1) {
554 dm_savepowerindex(hw);
555 rtlpriv->dm.dynamic_txpower_enable = true;
556 } else {
557 rtlpriv->dm.dynamic_txpower_enable = false;
558 }
559 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
560 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
561 }
562
563 void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
564 {
565 struct rtl_priv *rtlpriv = rtl_priv(hw);
566 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
567
568 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
569 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
570 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
571 dm_digtable->back_val);
572
573 if (rtlpriv->rtlhal.interface == INTF_USB &&
574 !dm_digtable->dig_enable_flag) {
575 dm_digtable->pre_igvalue = 0x17;
576 return;
577 }
578 dm_digtable->cur_igvalue -= 1;
579 if (dm_digtable->cur_igvalue < DM_DIG_MIN)
580 dm_digtable->cur_igvalue = DM_DIG_MIN;
581
582 if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
583 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
584 dm_digtable->cur_igvalue);
585 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
586 dm_digtable->cur_igvalue);
587
588 dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
589 }
590 RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING,
591 "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
592 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
593 dm_digtable->rssi_val_min, dm_digtable->back_val,
594 dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,
595 dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);
596 }
597 EXPORT_SYMBOL(rtl92c_dm_write_dig);
598
599 static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
600 {
601 struct rtl_priv *rtlpriv = rtl_priv(hw);
602 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
603 long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
604
605 if (mac->link_state != MAC80211_LINKED)
606 return;
607
608 if (mac->opmode == NL80211_IFTYPE_ADHOC ||
609 mac->opmode == NL80211_IFTYPE_AP) {
610 /* TODO: Handle ADHOC and AP Mode */
611 }
612
613 if (tmpentry_max_pwdb != 0)
614 rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
615 else
616 rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
617
618 if (tmpentry_min_pwdb != 0xff)
619 rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
620 else
621 rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
622
623 /* TODO:
624 * if (mac->opmode == NL80211_IFTYPE_STATION) {
625 * if (rtlpriv->rtlhal.fw_ready) {
626 * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);
627 * rtl8192c_set_rssi_cmd(hw, param);
628 * }
629 * }
630 */
631 }
632
633 void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
634 {
635 struct rtl_priv *rtlpriv = rtl_priv(hw);
636 rtlpriv->dm.current_turbo_edca = false;
637 rtlpriv->dm.is_any_nonbepkts = false;
638 rtlpriv->dm.is_cur_rdlstate = false;
639 }
640 EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
641
642 static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
643 {
644 struct rtl_priv *rtlpriv = rtl_priv(hw);
645 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
646 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
647
648 static u64 last_txok_cnt;
649 static u64 last_rxok_cnt;
650 static u32 last_bt_edca_ul;
651 static u32 last_bt_edca_dl;
652 u64 cur_txok_cnt = 0;
653 u64 cur_rxok_cnt = 0;
654 u32 edca_be_ul = 0x5ea42b;
655 u32 edca_be_dl = 0x5ea42b;
656 bool bt_change_edca = false;
657
658 if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
659 (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
660 rtlpriv->dm.current_turbo_edca = false;
661 last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
662 last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
663 }
664
665 if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
666 edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
667 bt_change_edca = true;
668 }
669
670 if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
671 edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
672 bt_change_edca = true;
673 }
674
675 if (mac->link_state != MAC80211_LINKED) {
676 rtlpriv->dm.current_turbo_edca = false;
677 return;
678 }
679
680 if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
681 if (!(edca_be_ul & 0xffff0000))
682 edca_be_ul |= 0x005e0000;
683
684 if (!(edca_be_dl & 0xffff0000))
685 edca_be_dl |= 0x005e0000;
686 }
687
688 if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
689 (!rtlpriv->dm.disable_framebursting))) {
690
691 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
692 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
693
694 if (cur_rxok_cnt > 4 * cur_txok_cnt) {
695 if (!rtlpriv->dm.is_cur_rdlstate ||
696 !rtlpriv->dm.current_turbo_edca) {
697 rtl_write_dword(rtlpriv,
698 REG_EDCA_BE_PARAM,
699 edca_be_dl);
700 rtlpriv->dm.is_cur_rdlstate = true;
701 }
702 } else {
703 if (rtlpriv->dm.is_cur_rdlstate ||
704 !rtlpriv->dm.current_turbo_edca) {
705 rtl_write_dword(rtlpriv,
706 REG_EDCA_BE_PARAM,
707 edca_be_ul);
708 rtlpriv->dm.is_cur_rdlstate = false;
709 }
710 }
711 rtlpriv->dm.current_turbo_edca = true;
712 } else {
713 if (rtlpriv->dm.current_turbo_edca) {
714 u8 tmp = AC0_BE;
715 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
716 &tmp);
717 rtlpriv->dm.current_turbo_edca = false;
718 }
719 }
720
721 rtlpriv->dm.is_any_nonbepkts = false;
722 last_txok_cnt = rtlpriv->stats.txbytesunicast;
723 last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
724 }
725
726 static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
727 *hw)
728 {
729 struct rtl_priv *rtlpriv = rtl_priv(hw);
730 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
731 struct rtl_phy *rtlphy = &(rtlpriv->phy);
732 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
733 u8 thermalvalue, delta, delta_lck, delta_iqk;
734 long ele_a, ele_d, temp_cck, val_x, value32;
735 long val_y, ele_c = 0;
736 u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
737 s8 cck_index = 0;
738 int i;
739 bool is2t = IS_92C_SERIAL(rtlhal->version);
740 s8 txpwr_level[3] = {0, 0, 0};
741 u8 ofdm_min_index = 6, rf;
742
743 rtlpriv->dm.txpower_trackinginit = true;
744 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
745 "rtl92c_dm_txpower_tracking_callback_thermalmeter\n");
746
747 thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
748
749 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
750 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
751 thermalvalue, rtlpriv->dm.thermalvalue,
752 rtlefuse->eeprom_thermalmeter);
753
754 rtl92c_phy_ap_calibrate(hw, (thermalvalue -
755 rtlefuse->eeprom_thermalmeter));
756 if (is2t)
757 rf = 2;
758 else
759 rf = 1;
760
761 if (thermalvalue) {
762 ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
763 MASKDWORD) & MASKOFDM_D;
764
765 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
766 if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
767 ofdm_index_old[0] = (u8) i;
768
769 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
770 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
771 ROFDM0_XATXIQIMBALANCE,
772 ele_d, ofdm_index_old[0]);
773 break;
774 }
775 }
776
777 if (is2t) {
778 ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
779 MASKDWORD) & MASKOFDM_D;
780
781 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
782 if (ele_d == (ofdmswing_table[i] &
783 MASKOFDM_D)) {
784 ofdm_index_old[1] = (u8) i;
785 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
786 DBG_LOUD,
787 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
788 ROFDM0_XBTXIQIMBALANCE, ele_d,
789 ofdm_index_old[1]);
790 break;
791 }
792 }
793 }
794
795 temp_cck =
796 rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
797
798 for (i = 0; i < CCK_TABLE_LENGTH; i++) {
799 if (rtlpriv->dm.cck_inch14) {
800 if (memcmp((void *)&temp_cck,
801 (void *)&cckswing_table_ch14[i][2],
802 4) == 0) {
803 cck_index_old = (u8) i;
804
805 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
806 DBG_LOUD,
807 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",
808 RCCK0_TXFILTER2, temp_cck,
809 cck_index_old,
810 rtlpriv->dm.cck_inch14);
811 break;
812 }
813 } else {
814 if (memcmp((void *)&temp_cck,
815 (void *)
816 &cckswing_table_ch1ch13[i][2],
817 4) == 0) {
818 cck_index_old = (u8) i;
819
820 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
821 DBG_LOUD,
822 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",
823 RCCK0_TXFILTER2, temp_cck,
824 cck_index_old,
825 rtlpriv->dm.cck_inch14);
826 break;
827 }
828 }
829 }
830
831 if (!rtlpriv->dm.thermalvalue) {
832 rtlpriv->dm.thermalvalue =
833 rtlefuse->eeprom_thermalmeter;
834 rtlpriv->dm.thermalvalue_lck = thermalvalue;
835 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
836 for (i = 0; i < rf; i++)
837 rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
838 rtlpriv->dm.cck_index = cck_index_old;
839 }
840 /* Handle USB High PA boards */
841
842 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
843 (thermalvalue - rtlpriv->dm.thermalvalue) :
844 (rtlpriv->dm.thermalvalue - thermalvalue);
845
846 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
847 (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
848 (rtlpriv->dm.thermalvalue_lck - thermalvalue);
849
850 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
851 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
852 (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
853
854 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
855 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n",
856 thermalvalue, rtlpriv->dm.thermalvalue,
857 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
858 delta_iqk);
859
860 if (delta_lck > 1) {
861 rtlpriv->dm.thermalvalue_lck = thermalvalue;
862 rtl92c_phy_lc_calibrate(hw);
863 }
864
865 if (delta > 0 && rtlpriv->dm.txpower_track_control) {
866 if (thermalvalue > rtlpriv->dm.thermalvalue) {
867 for (i = 0; i < rf; i++)
868 rtlpriv->dm.ofdm_index[i] -= delta;
869 rtlpriv->dm.cck_index -= delta;
870 } else {
871 for (i = 0; i < rf; i++)
872 rtlpriv->dm.ofdm_index[i] += delta;
873 rtlpriv->dm.cck_index += delta;
874 }
875
876 if (is2t) {
877 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
878 "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
879 rtlpriv->dm.ofdm_index[0],
880 rtlpriv->dm.ofdm_index[1],
881 rtlpriv->dm.cck_index);
882 } else {
883 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
884 "temp OFDM_A_index=0x%x, cck_index=0x%x\n",
885 rtlpriv->dm.ofdm_index[0],
886 rtlpriv->dm.cck_index);
887 }
888
889 if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
890 for (i = 0; i < rf; i++)
891 ofdm_index[i] =
892 rtlpriv->dm.ofdm_index[i]
893 + 1;
894 cck_index = rtlpriv->dm.cck_index + 1;
895 } else {
896 for (i = 0; i < rf; i++)
897 ofdm_index[i] =
898 rtlpriv->dm.ofdm_index[i];
899 cck_index = rtlpriv->dm.cck_index;
900 }
901
902 for (i = 0; i < rf; i++) {
903 if (txpwr_level[i] >= 0 &&
904 txpwr_level[i] <= 26) {
905 if (thermalvalue >
906 rtlefuse->eeprom_thermalmeter) {
907 if (delta < 5)
908 ofdm_index[i] -= 1;
909
910 else
911 ofdm_index[i] -= 2;
912 } else if (delta > 5 && thermalvalue <
913 rtlefuse->
914 eeprom_thermalmeter) {
915 ofdm_index[i] += 1;
916 }
917 } else if (txpwr_level[i] >= 27 &&
918 txpwr_level[i] <= 32
919 && thermalvalue >
920 rtlefuse->eeprom_thermalmeter) {
921 if (delta < 5)
922 ofdm_index[i] -= 1;
923
924 else
925 ofdm_index[i] -= 2;
926 } else if (txpwr_level[i] >= 32 &&
927 txpwr_level[i] <= 38 &&
928 thermalvalue >
929 rtlefuse->eeprom_thermalmeter
930 && delta > 5) {
931 ofdm_index[i] -= 1;
932 }
933 }
934
935 if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
936 if (thermalvalue >
937 rtlefuse->eeprom_thermalmeter) {
938 if (delta < 5)
939 cck_index -= 1;
940
941 else
942 cck_index -= 2;
943 } else if (delta > 5 && thermalvalue <
944 rtlefuse->eeprom_thermalmeter) {
945 cck_index += 1;
946 }
947 } else if (txpwr_level[i] >= 27 &&
948 txpwr_level[i] <= 32 &&
949 thermalvalue >
950 rtlefuse->eeprom_thermalmeter) {
951 if (delta < 5)
952 cck_index -= 1;
953
954 else
955 cck_index -= 2;
956 } else if (txpwr_level[i] >= 32 &&
957 txpwr_level[i] <= 38 &&
958 thermalvalue > rtlefuse->eeprom_thermalmeter
959 && delta > 5) {
960 cck_index -= 1;
961 }
962
963 for (i = 0; i < rf; i++) {
964 if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
965 ofdm_index[i] = OFDM_TABLE_SIZE - 1;
966
967 else if (ofdm_index[i] < ofdm_min_index)
968 ofdm_index[i] = ofdm_min_index;
969 }
970
971 if (cck_index > CCK_TABLE_SIZE - 1)
972 cck_index = CCK_TABLE_SIZE - 1;
973 else if (cck_index < 0)
974 cck_index = 0;
975
976 if (is2t) {
977 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
978 "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
979 ofdm_index[0], ofdm_index[1],
980 cck_index);
981 } else {
982 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
983 "new OFDM_A_index=0x%x, cck_index=0x%x\n",
984 ofdm_index[0], cck_index);
985 }
986 }
987
988 if (rtlpriv->dm.txpower_track_control && delta != 0) {
989 ele_d =
990 (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
991 val_x = rtlphy->reg_e94;
992 val_y = rtlphy->reg_e9c;
993
994 if (val_x != 0) {
995 if ((val_x & 0x00000200) != 0)
996 val_x = val_x | 0xFFFFFC00;
997 ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
998
999 if ((val_y & 0x00000200) != 0)
1000 val_y = val_y | 0xFFFFFC00;
1001 ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
1002
1003 value32 = (ele_d << 22) |
1004 ((ele_c & 0x3F) << 16) | ele_a;
1005
1006 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1007 MASKDWORD, value32);
1008
1009 value32 = (ele_c & 0x000003C0) >> 6;
1010 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1011 value32);
1012
1013 value32 = ((val_x * ele_d) >> 7) & 0x01;
1014 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1015 BIT(31), value32);
1016
1017 value32 = ((val_y * ele_d) >> 7) & 0x01;
1018 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1019 BIT(29), value32);
1020 } else {
1021 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1022 MASKDWORD,
1023 ofdmswing_table[ofdm_index[0]]);
1024
1025 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1026 0x00);
1027 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1028 BIT(31) | BIT(29), 0x00);
1029 }
1030
1031 if (!rtlpriv->dm.cck_inch14) {
1032 rtl_write_byte(rtlpriv, 0xa22,
1033 cckswing_table_ch1ch13[cck_index]
1034 [0]);
1035 rtl_write_byte(rtlpriv, 0xa23,
1036 cckswing_table_ch1ch13[cck_index]
1037 [1]);
1038 rtl_write_byte(rtlpriv, 0xa24,
1039 cckswing_table_ch1ch13[cck_index]
1040 [2]);
1041 rtl_write_byte(rtlpriv, 0xa25,
1042 cckswing_table_ch1ch13[cck_index]
1043 [3]);
1044 rtl_write_byte(rtlpriv, 0xa26,
1045 cckswing_table_ch1ch13[cck_index]
1046 [4]);
1047 rtl_write_byte(rtlpriv, 0xa27,
1048 cckswing_table_ch1ch13[cck_index]
1049 [5]);
1050 rtl_write_byte(rtlpriv, 0xa28,
1051 cckswing_table_ch1ch13[cck_index]
1052 [6]);
1053 rtl_write_byte(rtlpriv, 0xa29,
1054 cckswing_table_ch1ch13[cck_index]
1055 [7]);
1056 } else {
1057 rtl_write_byte(rtlpriv, 0xa22,
1058 cckswing_table_ch14[cck_index]
1059 [0]);
1060 rtl_write_byte(rtlpriv, 0xa23,
1061 cckswing_table_ch14[cck_index]
1062 [1]);
1063 rtl_write_byte(rtlpriv, 0xa24,
1064 cckswing_table_ch14[cck_index]
1065 [2]);
1066 rtl_write_byte(rtlpriv, 0xa25,
1067 cckswing_table_ch14[cck_index]
1068 [3]);
1069 rtl_write_byte(rtlpriv, 0xa26,
1070 cckswing_table_ch14[cck_index]
1071 [4]);
1072 rtl_write_byte(rtlpriv, 0xa27,
1073 cckswing_table_ch14[cck_index]
1074 [5]);
1075 rtl_write_byte(rtlpriv, 0xa28,
1076 cckswing_table_ch14[cck_index]
1077 [6]);
1078 rtl_write_byte(rtlpriv, 0xa29,
1079 cckswing_table_ch14[cck_index]
1080 [7]);
1081 }
1082
1083 if (is2t) {
1084 ele_d = (ofdmswing_table[ofdm_index[1]] &
1085 0xFFC00000) >> 22;
1086
1087 val_x = rtlphy->reg_eb4;
1088 val_y = rtlphy->reg_ebc;
1089
1090 if (val_x != 0) {
1091 if ((val_x & 0x00000200) != 0)
1092 val_x = val_x | 0xFFFFFC00;
1093 ele_a = ((val_x * ele_d) >> 8) &
1094 0x000003FF;
1095
1096 if ((val_y & 0x00000200) != 0)
1097 val_y = val_y | 0xFFFFFC00;
1098 ele_c = ((val_y * ele_d) >> 8) &
1099 0x00003FF;
1100
1101 value32 = (ele_d << 22) |
1102 ((ele_c & 0x3F) << 16) | ele_a;
1103 rtl_set_bbreg(hw,
1104 ROFDM0_XBTXIQIMBALANCE,
1105 MASKDWORD, value32);
1106
1107 value32 = (ele_c & 0x000003C0) >> 6;
1108 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1109 MASKH4BITS, value32);
1110
1111 value32 = ((val_x * ele_d) >> 7) & 0x01;
1112 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1113 BIT(27), value32);
1114
1115 value32 = ((val_y * ele_d) >> 7) & 0x01;
1116 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1117 BIT(25), value32);
1118 } else {
1119 rtl_set_bbreg(hw,
1120 ROFDM0_XBTXIQIMBALANCE,
1121 MASKDWORD,
1122 ofdmswing_table[ofdm_index
1123 [1]]);
1124 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1125 MASKH4BITS, 0x00);
1126 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1127 BIT(27) | BIT(25), 0x00);
1128 }
1129
1130 }
1131 }
1132
1133 if (delta_iqk > 3) {
1134 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1135 rtl92c_phy_iq_calibrate(hw, false);
1136 }
1137
1138 if (rtlpriv->dm.txpower_track_control)
1139 rtlpriv->dm.thermalvalue = thermalvalue;
1140 }
1141
1142 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
1143
1144 }
1145
1146 static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
1147 struct ieee80211_hw *hw)
1148 {
1149 struct rtl_priv *rtlpriv = rtl_priv(hw);
1150
1151 rtlpriv->dm.txpower_tracking = true;
1152 rtlpriv->dm.txpower_trackinginit = false;
1153
1154 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1155 "pMgntInfo->txpower_tracking = %d\n",
1156 rtlpriv->dm.txpower_tracking);
1157 }
1158
1159 static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
1160 {
1161 rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
1162 }
1163
1164 static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
1165 {
1166 rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
1167 }
1168
1169 static void rtl92c_dm_check_txpower_tracking_thermal_meter(
1170 struct ieee80211_hw *hw)
1171 {
1172 struct rtl_priv *rtlpriv = rtl_priv(hw);
1173
1174 if (!rtlpriv->dm.txpower_tracking)
1175 return;
1176
1177 if (!rtlpriv->dm.tm_trigger) {
1178 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
1179 0x60);
1180 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1181 "Trigger 92S Thermal Meter!!\n");
1182 rtlpriv->dm.tm_trigger = 1;
1183 return;
1184 } else {
1185 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1186 "Schedule TxPowerTracking direct call!!\n");
1187 rtl92c_dm_txpower_tracking_directcall(hw);
1188 rtlpriv->dm.tm_trigger = 0;
1189 }
1190 }
1191
1192 void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1193 {
1194 rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
1195 }
1196 EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
1197
1198 void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1199 {
1200 struct rtl_priv *rtlpriv = rtl_priv(hw);
1201 struct rate_adaptive *p_ra = &(rtlpriv->ra);
1202
1203 p_ra->ratr_state = DM_RATR_STA_INIT;
1204 p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1205
1206 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1207 rtlpriv->dm.useramask = true;
1208 else
1209 rtlpriv->dm.useramask = false;
1210
1211 }
1212 EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
1213
1214 static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1215 {
1216 struct rtl_priv *rtlpriv = rtl_priv(hw);
1217 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1218
1219 dm_pstable->pre_ccastate = CCA_MAX;
1220 dm_pstable->cur_ccasate = CCA_MAX;
1221 dm_pstable->pre_rfstate = RF_MAX;
1222 dm_pstable->cur_rfstate = RF_MAX;
1223 dm_pstable->rssi_val_min = 0;
1224 }
1225
1226 void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
1227 {
1228 struct rtl_priv *rtlpriv = rtl_priv(hw);
1229 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1230
1231 if (!rtlpriv->reg_init) {
1232 rtlpriv->reg_874 = (rtl_get_bbreg(hw,
1233 RFPGA0_XCD_RFINTERFACESW,
1234 MASKDWORD) & 0x1CC000) >> 14;
1235
1236 rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
1237 MASKDWORD) & BIT(3)) >> 3;
1238
1239 rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1240 MASKDWORD) & 0xFF000000) >> 24;
1241
1242 rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
1243 0xF000) >> 12;
1244
1245 rtlpriv->reg_init = true;
1246 }
1247
1248 if (!bforce_in_normal) {
1249 if (dm_pstable->rssi_val_min != 0) {
1250 if (dm_pstable->pre_rfstate == RF_NORMAL) {
1251 if (dm_pstable->rssi_val_min >= 30)
1252 dm_pstable->cur_rfstate = RF_SAVE;
1253 else
1254 dm_pstable->cur_rfstate = RF_NORMAL;
1255 } else {
1256 if (dm_pstable->rssi_val_min <= 25)
1257 dm_pstable->cur_rfstate = RF_NORMAL;
1258 else
1259 dm_pstable->cur_rfstate = RF_SAVE;
1260 }
1261 } else {
1262 dm_pstable->cur_rfstate = RF_MAX;
1263 }
1264 } else {
1265 dm_pstable->cur_rfstate = RF_NORMAL;
1266 }
1267
1268 if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
1269 if (dm_pstable->cur_rfstate == RF_SAVE) {
1270 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1271 0x1C0000, 0x2);
1272 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
1273 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1274 0xFF000000, 0x63);
1275 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1276 0xC000, 0x2);
1277 rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
1278 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1279 rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
1280 } else {
1281 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1282 0x1CC000, rtlpriv->reg_874);
1283 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
1284 rtlpriv->reg_c70);
1285 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
1286 rtlpriv->reg_85c);
1287 rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
1288 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1289 }
1290
1291 dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
1292 }
1293 }
1294 EXPORT_SYMBOL(rtl92c_dm_rf_saving);
1295
1296 static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1297 {
1298 struct rtl_priv *rtlpriv = rtl_priv(hw);
1299 struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1300 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1301 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1302
1303 /* Determine the minimum RSSI */
1304 if (((mac->link_state == MAC80211_NOLINK)) &&
1305 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1306 dm_pstable->rssi_val_min = 0;
1307 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
1308 }
1309
1310 if (mac->link_state == MAC80211_LINKED) {
1311 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1312 dm_pstable->rssi_val_min =
1313 rtlpriv->dm.entry_min_undec_sm_pwdb;
1314 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1315 "AP Client PWDB = 0x%lx\n",
1316 dm_pstable->rssi_val_min);
1317 } else {
1318 dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
1319 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1320 "STA Default Port PWDB = 0x%lx\n",
1321 dm_pstable->rssi_val_min);
1322 }
1323 } else {
1324 dm_pstable->rssi_val_min =
1325 rtlpriv->dm.entry_min_undec_sm_pwdb;
1326
1327 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1328 "AP Ext Port PWDB = 0x%lx\n",
1329 dm_pstable->rssi_val_min);
1330 }
1331
1332 /* Power Saving for 92C */
1333 if (IS_92C_SERIAL(rtlhal->version))
1334 ;/* rtl92c_dm_1r_cca(hw); */
1335 else
1336 rtl92c_dm_rf_saving(hw, false);
1337 }
1338
1339 void rtl92c_dm_init(struct ieee80211_hw *hw)
1340 {
1341 struct rtl_priv *rtlpriv = rtl_priv(hw);
1342
1343 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1344 rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;
1345 rtlpriv->dm.undec_sm_pwdb = -1;
1346 rtlpriv->dm.undec_sm_cck = -1;
1347 rtlpriv->dm.dm_initialgain_enable = true;
1348 rtl_dm_diginit(hw, 0x20);
1349
1350 rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;
1351 rtl92c_dm_init_dynamic_txpower(hw);
1352
1353 rtl92c_dm_init_edca_turbo(hw);
1354 rtl92c_dm_init_rate_adaptive_mask(hw);
1355 rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;
1356 rtl92c_dm_initialize_txpower_tracking(hw);
1357 rtl92c_dm_init_dynamic_bb_powersaving(hw);
1358
1359 rtlpriv->dm.ofdm_pkt_cnt = 0;
1360 rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;
1361 }
1362 EXPORT_SYMBOL(rtl92c_dm_init);
1363
1364 void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
1365 {
1366 struct rtl_priv *rtlpriv = rtl_priv(hw);
1367 struct rtl_phy *rtlphy = &(rtlpriv->phy);
1368 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1369 long undec_sm_pwdb;
1370
1371 if (!rtlpriv->dm.dynamic_txpower_enable)
1372 return;
1373
1374 if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
1375 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1376 return;
1377 }
1378
1379 if ((mac->link_state < MAC80211_LINKED) &&
1380 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1381 RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
1382 "Not connected to any\n");
1383
1384 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1385
1386 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
1387 return;
1388 }
1389
1390 if (mac->link_state >= MAC80211_LINKED) {
1391 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1392 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1393 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1394 "AP Client PWDB = 0x%lx\n",
1395 undec_sm_pwdb);
1396 } else {
1397 undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
1398 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1399 "STA Default Port PWDB = 0x%lx\n",
1400 undec_sm_pwdb);
1401 }
1402 } else {
1403 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1404
1405 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1406 "AP Ext Port PWDB = 0x%lx\n",
1407 undec_sm_pwdb);
1408 }
1409
1410 if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
1411 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;
1412 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1413 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
1414 } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
1415 (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
1416
1417 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1418 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1419 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
1420 } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
1421 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1422 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1423 "TXHIGHPWRLEVEL_NORMAL\n");
1424 }
1425
1426 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
1427 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1428 "PHY_SetTxPowerLevel8192S() Channel = %d\n",
1429 rtlphy->current_channel);
1430 rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
1431 if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1432 TXHIGHPWRLEVEL_NORMAL)
1433 dm_restorepowerindex(hw);
1434 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1435 TXHIGHPWRLEVEL_LEVEL1)
1436 dm_writepowerindex(hw, 0x14);
1437 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1438 TXHIGHPWRLEVEL_LEVEL2)
1439 dm_writepowerindex(hw, 0x10);
1440 }
1441 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
1442 }
1443
1444 void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
1445 {
1446 struct rtl_priv *rtlpriv = rtl_priv(hw);
1447 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1448 bool fw_current_inpsmode = false;
1449 bool fw_ps_awake = true;
1450
1451 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1452 (u8 *) (&fw_current_inpsmode));
1453 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1454 (u8 *) (&fw_ps_awake));
1455
1456 if (ppsc->p2p_ps_info.p2p_ps_mode)
1457 fw_ps_awake = false;
1458
1459 if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
1460 fw_ps_awake)
1461 && (!ppsc->rfchange_inprogress)) {
1462 rtl92c_dm_pwdb_monitor(hw);
1463 rtl92c_dm_dig(hw);
1464 rtl92c_dm_false_alarm_counter_statistics(hw);
1465 rtl92c_dm_dynamic_bb_powersaving(hw);
1466 rtl92c_dm_dynamic_txpower(hw);
1467 rtl92c_dm_check_txpower_tracking(hw);
1468 /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
1469 rtl92c_dm_bt_coexist(hw);
1470 rtl92c_dm_check_edca_turbo(hw);
1471 }
1472 }
1473 EXPORT_SYMBOL(rtl92c_dm_watchdog);
1474
1475 u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
1476 {
1477 struct rtl_priv *rtlpriv = rtl_priv(hw);
1478 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1479 long undec_sm_pwdb;
1480 u8 curr_bt_rssi_state = 0x00;
1481
1482 if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1483 undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
1484 } else {
1485 if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
1486 undec_sm_pwdb = 100;
1487 else
1488 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1489 }
1490
1491 /* Check RSSI to determine HighPower/NormalPower state for
1492 * BT coexistence. */
1493 if (undec_sm_pwdb >= 67)
1494 curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
1495 else if (undec_sm_pwdb < 62)
1496 curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
1497
1498 /* Check RSSI to determine AMPDU setting for BT coexistence. */
1499 if (undec_sm_pwdb >= 40)
1500 curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
1501 else if (undec_sm_pwdb <= 32)
1502 curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
1503
1504 /* Marked RSSI state. It will be used to determine BT coexistence
1505 * setting later. */
1506 if (undec_sm_pwdb < 35)
1507 curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW;
1508 else
1509 curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
1510
1511 /* Check BT state related to BT_Idle in B/G mode. */
1512 if (undec_sm_pwdb < 15)
1513 curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW;
1514 else
1515 curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
1516
1517 if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) {
1518 rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state;
1519 return true;
1520 } else {
1521 return false;
1522 }
1523 }
1524 EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
1525
1526 static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
1527 {
1528 struct rtl_priv *rtlpriv = rtl_priv(hw);
1529 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1530
1531 u32 polling, ratio_tx, ratio_pri;
1532 u32 bt_tx, bt_pri;
1533 u8 bt_state;
1534 u8 cur_service_type;
1535
1536 if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
1537 return false;
1538
1539 bt_state = rtl_read_byte(rtlpriv, 0x4fd);
1540 bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK;
1541 bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK;
1542 polling = rtl_read_dword(rtlpriv, 0x490);
1543
1544 if (bt_tx == BT_MASK && bt_pri == BT_MASK &&
1545 polling == 0xffffffff && bt_state == 0xff)
1546 return false;
1547
1548 bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1);
1549 if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) {
1550 rtlpcipriv->bt_coexist.bt_cur_state = bt_state;
1551
1552 if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1553 rtlpcipriv->bt_coexist.bt_service = BT_IDLE;
1554
1555 bt_state = bt_state |
1556 ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1557 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1558 BIT_OFFSET_LEN_MASK_32(2, 1);
1559 rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1560 }
1561 return true;
1562 }
1563
1564 ratio_tx = bt_tx * 1000 / polling;
1565 ratio_pri = bt_pri * 1000 / polling;
1566 rtlpcipriv->bt_coexist.ratio_tx = ratio_tx;
1567 rtlpcipriv->bt_coexist.ratio_pri = ratio_pri;
1568
1569 if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1570
1571 if ((ratio_tx < 30) && (ratio_pri < 30))
1572 cur_service_type = BT_IDLE;
1573 else if ((ratio_pri > 110) && (ratio_pri < 250))
1574 cur_service_type = BT_SCO;
1575 else if ((ratio_tx >= 200) && (ratio_pri >= 200))
1576 cur_service_type = BT_BUSY;
1577 else if ((ratio_tx >= 350) && (ratio_tx < 500))
1578 cur_service_type = BT_OTHERBUSY;
1579 else if (ratio_tx >= 500)
1580 cur_service_type = BT_PAN;
1581 else
1582 cur_service_type = BT_OTHER_ACTION;
1583
1584 if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) {
1585 rtlpcipriv->bt_coexist.bt_service = cur_service_type;
1586 bt_state = bt_state |
1587 ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1588 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1589 ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ?
1590 0 : BIT_OFFSET_LEN_MASK_32(2, 1));
1591
1592 /* Add interrupt migration when bt is not ini
1593 * idle state (no traffic). */
1594 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1595 rtl_write_word(rtlpriv, 0x504, 0x0ccc);
1596 rtl_write_byte(rtlpriv, 0x506, 0x54);
1597 rtl_write_byte(rtlpriv, 0x507, 0x54);
1598 } else {
1599 rtl_write_byte(rtlpriv, 0x506, 0x00);
1600 rtl_write_byte(rtlpriv, 0x507, 0x00);
1601 }
1602
1603 rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1604 return true;
1605 }
1606 }
1607
1608 return false;
1609
1610 }
1611
1612 static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
1613 {
1614 struct rtl_priv *rtlpriv = rtl_priv(hw);
1615 static bool media_connect;
1616
1617 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1618 media_connect = false;
1619 } else {
1620 if (!media_connect) {
1621 media_connect = true;
1622 return true;
1623 }
1624 media_connect = true;
1625 }
1626
1627 return false;
1628 }
1629
1630 static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
1631 {
1632 struct rtl_priv *rtlpriv = rtl_priv(hw);
1633 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1634
1635
1636 if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) {
1637 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b;
1638 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b;
1639 } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) {
1640 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f;
1641 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f;
1642 } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) {
1643 if (rtlpcipriv->bt_coexist.ratio_tx > 160) {
1644 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f;
1645 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f;
1646 } else {
1647 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b;
1648 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b;
1649 }
1650 } else {
1651 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1652 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1653 }
1654
1655 if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) &&
1656 (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
1657 (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
1658 (rtlpcipriv->bt_coexist.bt_rssi_state &
1659 BT_RSSI_STATE_BG_EDCA_LOW)) {
1660 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b;
1661 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b;
1662 }
1663 }
1664
1665 static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
1666 {
1667 struct rtl_priv *rtlpriv = rtl_priv(hw);
1668 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1669
1670
1671 /* Only enable HW BT coexist when BT in "Busy" state. */
1672 if (rtlpriv->mac80211.vendor == PEER_CISCO &&
1673 rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) {
1674 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1675 } else {
1676 if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) &&
1677 (rtlpcipriv->bt_coexist.bt_rssi_state &
1678 BT_RSSI_STATE_NORMAL_POWER)) {
1679 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1680 } else if ((rtlpcipriv->bt_coexist.bt_service ==
1681 BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
1682 WIRELESS_MODE_N_24G) &&
1683 (rtlpcipriv->bt_coexist.bt_rssi_state &
1684 BT_RSSI_STATE_SPECIAL_LOW)) {
1685 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1686 } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) {
1687 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1688 } else {
1689 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1690 }
1691 }
1692
1693 if (rtlpcipriv->bt_coexist.bt_service == BT_PAN)
1694 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
1695 else
1696 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
1697
1698 if (rtlpcipriv->bt_coexist.bt_rssi_state &
1699 BT_RSSI_STATE_NORMAL_POWER) {
1700 rtl92c_bt_set_normal(hw);
1701 } else {
1702 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1703 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1704 }
1705
1706 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1707 rtlpriv->cfg->ops->set_rfreg(hw,
1708 RF90_PATH_A,
1709 0x1e,
1710 0xf0, 0xf);
1711 } else {
1712 rtlpriv->cfg->ops->set_rfreg(hw,
1713 RF90_PATH_A, 0x1e, 0xf0,
1714 rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1715 }
1716
1717 if (!rtlpriv->dm.dynamic_txpower_enable) {
1718 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1719 if (rtlpcipriv->bt_coexist.bt_rssi_state &
1720 BT_RSSI_STATE_TXPOWER_LOW) {
1721 rtlpriv->dm.dynamic_txhighpower_lvl =
1722 TXHIGHPWRLEVEL_BT2;
1723 } else {
1724 rtlpriv->dm.dynamic_txhighpower_lvl =
1725 TXHIGHPWRLEVEL_BT1;
1726 }
1727 } else {
1728 rtlpriv->dm.dynamic_txhighpower_lvl =
1729 TXHIGHPWRLEVEL_NORMAL;
1730 }
1731 rtl92c_phy_set_txpower_level(hw,
1732 rtlpriv->phy.current_channel);
1733 }
1734 }
1735
1736 static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
1737 {
1738 struct rtl_priv *rtlpriv = rtl_priv(hw);
1739 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1740 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1741 u8 tmp1byte = 0;
1742
1743 if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&
1744 rtlpcipriv->bt_coexist.bt_coexistence)
1745 tmp1byte |= BIT(5);
1746 if (rtlpcipriv->bt_coexist.bt_cur_state) {
1747 if (rtlpcipriv->bt_coexist.bt_ant_isolation)
1748 rtl92c_bt_ant_isolation(hw, tmp1byte);
1749 } else {
1750 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1751 rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
1752 rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1753
1754 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1755 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1756 }
1757 }
1758
1759 void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
1760 {
1761 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1762
1763 bool wifi_connect_change;
1764 bool bt_state_change;
1765 bool rssi_state_change;
1766
1767 if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
1768 (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
1769
1770 wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
1771 bt_state_change = rtl92c_bt_state_change(hw);
1772 rssi_state_change = rtl92c_bt_rssi_state_change(hw);
1773
1774 if (wifi_connect_change || bt_state_change || rssi_state_change)
1775 rtl92c_check_bt_change(hw);
1776 }
1777 }
1778 EXPORT_SYMBOL(rtl92c_dm_bt_coexist);
This page took 0.107918 seconds and 5 git commands to generate.