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