]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
xfrm: dst_entries_init() per-net dst_ops
[karo-tx-linux.git] / drivers / net / wireless / 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);