blob: 2efd03dc75f90d8b446a1e1317e64a9f31cff794 [file] [log] [blame]
Larry Finger8c96fcf2011-02-11 14:33:58 -06001/******************************************************************************
2 *
Larry Fingerfc616852012-01-07 20:46:43 -06003 * Copyright(c) 2009-2012 Realtek Corporation.
Larry Finger8c96fcf2011-02-11 14:33:58 -06004 *
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
Paul Gortmakeree40fa02011-05-27 16:14:23 -040030#include <linux/export.h>
Larry Finger1472d3a2011-02-23 10:24:58 -060031#include "dm_common.h"
Chaoming_Libeb5bc42011-04-25 12:53:35 -050032#include "phy_common.h"
33#include "../pci.h"
34#include "../base.h"
Larry Finger1472d3a2011-02-23 10:24:58 -060035
Larry Finger8c96fcf2011-02-11 14:33:58 -060036static struct ps_t dm_pstable;
37
Chaoming_Libeb5bc42011-04-25 12:53:35 -050038#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1)
39#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1)
40#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1)
41#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1)
42#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1)
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_undecoratedsmoothed_pwdb) : \
49 ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb)
50
Larry Finger8c96fcf2011-02-11 14:33:58 -060051static 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
91static 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
127static 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
163static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
164{
Larry Finger40332e52012-04-19 16:32:41 -0500165 struct rtl_priv *rtlpriv = rtl_priv(hw);
166 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
167
168 dm_digtable->dig_enable_flag = true;
169 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
170 dm_digtable->cur_igvalue = 0x20;
171 dm_digtable->pre_igvalue = 0x0;
172 dm_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
173 dm_digtable->presta_connectstate = DIG_STA_DISCONNECT;
174 dm_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
175 dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
176 dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
177 dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
178 dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
179 dm_digtable->rx_gain_range_max = DM_DIG_MAX;
180 dm_digtable->rx_gain_range_min = DM_DIG_MIN;
181 dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
182 dm_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX;
183 dm_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN;
184 dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
185 dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600186}
187
188static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
189{
190 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500191 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600192 long rssi_val_min = 0;
193
Larry Finger40332e52012-04-19 16:32:41 -0500194 if ((dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
195 (dm_digtable->cursta_connectctate == DIG_STA_CONNECT)) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600196 if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
197 rssi_val_min =
198 (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
199 rtlpriv->dm.undecorated_smoothed_pwdb) ?
200 rtlpriv->dm.undecorated_smoothed_pwdb :
201 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
202 else
203 rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
Larry Finger40332e52012-04-19 16:32:41 -0500204 } else if (dm_digtable->cursta_connectctate == DIG_STA_CONNECT ||
205 dm_digtable->cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600206 rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
Larry Finger40332e52012-04-19 16:32:41 -0500207 } else if (dm_digtable->curmultista_connectstate ==
Larry Finger8c96fcf2011-02-11 14:33:58 -0600208 DIG_MULTISTA_CONNECT) {
209 rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
210 }
211
212 return (u8) rssi_val_min;
213}
214
215static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
216{
217 u32 ret_value;
218 struct rtl_priv *rtlpriv = rtl_priv(hw);
219 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
220
221 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
222 falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
223
224 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
225 falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
226 falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
227
228 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
229 falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
230 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
231 falsealm_cnt->cnt_rate_illegal +
232 falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
233
234 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
235 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
236 falsealm_cnt->cnt_cck_fail = ret_value;
237
238 ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
239 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
240 falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
241 falsealm_cnt->cnt_rate_illegal +
242 falsealm_cnt->cnt_crc8_fail +
243 falsealm_cnt->cnt_mcs_fail +
244 falsealm_cnt->cnt_cck_fail);
245
246 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
247 rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
248 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
249 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
250
251 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800252 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
253 falsealm_cnt->cnt_parity_fail,
254 falsealm_cnt->cnt_rate_illegal,
255 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600256
257 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800258 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
259 falsealm_cnt->cnt_ofdm_fail,
260 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600261}
262
263static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
264{
265 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500266 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
267 u8 value_igi = dm_digtable->cur_igvalue;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600268
269 if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
270 value_igi--;
271 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
272 value_igi += 0;
273 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
274 value_igi++;
275 else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
276 value_igi += 2;
277 if (value_igi > DM_DIG_FA_UPPER)
278 value_igi = DM_DIG_FA_UPPER;
279 else if (value_igi < DM_DIG_FA_LOWER)
280 value_igi = DM_DIG_FA_LOWER;
281 if (rtlpriv->falsealm_cnt.cnt_all > 10000)
282 value_igi = 0x32;
283
Larry Finger40332e52012-04-19 16:32:41 -0500284 dm_digtable->cur_igvalue = value_igi;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600285 rtl92c_dm_write_dig(hw);
286}
287
288static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
289{
290 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500291 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600292
Larry Finger40332e52012-04-19 16:32:41 -0500293 if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) {
294 if ((dm_digtable->backoff_val - 2) <
295 dm_digtable->backoff_val_range_min)
296 dm_digtable->backoff_val =
297 dm_digtable->backoff_val_range_min;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600298 else
Larry Finger40332e52012-04-19 16:32:41 -0500299 dm_digtable->backoff_val -= 2;
300 } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) {
301 if ((dm_digtable->backoff_val + 2) >
302 dm_digtable->backoff_val_range_max)
303 dm_digtable->backoff_val =
304 dm_digtable->backoff_val_range_max;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600305 else
Larry Finger40332e52012-04-19 16:32:41 -0500306 dm_digtable->backoff_val += 2;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600307 }
308
Larry Finger40332e52012-04-19 16:32:41 -0500309 if ((dm_digtable->rssi_val_min + 10 - dm_digtable->backoff_val) >
310 dm_digtable->rx_gain_range_max)
311 dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_max;
312 else if ((dm_digtable->rssi_val_min + 10 -
313 dm_digtable->backoff_val) < dm_digtable->rx_gain_range_min)
314 dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_min;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600315 else
Larry Finger40332e52012-04-19 16:32:41 -0500316 dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 -
317 dm_digtable->backoff_val;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600318
319 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800320 "rssi_val_min = %x backoff_val %x\n",
Larry Finger40332e52012-04-19 16:32:41 -0500321 dm_digtable->rssi_val_min, dm_digtable->backoff_val);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600322
323 rtl92c_dm_write_dig(hw);
324}
325
326static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
327{
Chaoming_Li2b8359f2011-04-25 12:53:55 -0500328 static u8 initialized; /* initialized to false */
Larry Finger8c96fcf2011-02-11 14:33:58 -0600329 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500330 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600331 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
332 long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
Larry Finger7ea47242011-02-19 16:28:57 -0600333 bool multi_sta = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600334
335 if (mac->opmode == NL80211_IFTYPE_ADHOC)
Larry Finger7ea47242011-02-19 16:28:57 -0600336 multi_sta = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600337
Joe Perches23677ce2012-02-09 11:17:23 +0000338 if (!multi_sta ||
Larry Finger40332e52012-04-19 16:32:41 -0500339 dm_digtable->cursta_connectctate != DIG_STA_DISCONNECT) {
Chaoming_Li2b8359f2011-04-25 12:53:55 -0500340 initialized = false;
Larry Finger40332e52012-04-19 16:32:41 -0500341 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600342 return;
Chaoming_Li2b8359f2011-04-25 12:53:55 -0500343 } else if (initialized == false) {
344 initialized = true;
Larry Finger40332e52012-04-19 16:32:41 -0500345 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
346 dm_digtable->cur_igvalue = 0x20;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600347 rtl92c_dm_write_dig(hw);
348 }
349
Larry Finger40332e52012-04-19 16:32:41 -0500350 if (dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) {
351 if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
352 (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600353
Larry Finger40332e52012-04-19 16:32:41 -0500354 if (dm_digtable->dig_ext_port_stage ==
Larry Finger8c96fcf2011-02-11 14:33:58 -0600355 DIG_EXT_PORT_STAGE_2) {
Larry Finger40332e52012-04-19 16:32:41 -0500356 dm_digtable->cur_igvalue = 0x20;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600357 rtl92c_dm_write_dig(hw);
358 }
359
Larry Finger40332e52012-04-19 16:32:41 -0500360 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
361 } else if (rssi_strength > dm_digtable->rssi_highthresh) {
362 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600363 rtl92c_dm_ctrl_initgain_by_fa(hw);
364 }
Larry Finger40332e52012-04-19 16:32:41 -0500365 } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
366 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
367 dm_digtable->cur_igvalue = 0x20;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600368 rtl92c_dm_write_dig(hw);
369 }
370
371 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800372 "curmultista_connectstate = %x dig_ext_port_stage %x\n",
Larry Finger40332e52012-04-19 16:32:41 -0500373 dm_digtable->curmultista_connectstate,
374 dm_digtable->dig_ext_port_stage);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600375}
376
377static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
378{
379 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500380 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600381
382 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800383 "presta_connectstate = %x, cursta_connectctate = %x\n",
Larry Finger40332e52012-04-19 16:32:41 -0500384 dm_digtable->presta_connectstate,
385 dm_digtable->cursta_connectctate);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600386
Larry Finger40332e52012-04-19 16:32:41 -0500387 if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectctate
388 || dm_digtable->cursta_connectctate == DIG_STA_BEFORE_CONNECT
389 || dm_digtable->cursta_connectctate == DIG_STA_CONNECT) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600390
Larry Finger40332e52012-04-19 16:32:41 -0500391 if (dm_digtable->cursta_connectctate != DIG_STA_DISCONNECT) {
392 dm_digtable->rssi_val_min =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600393 rtl92c_dm_initial_gain_min_pwdb(hw);
394 rtl92c_dm_ctrl_initgain_by_rssi(hw);
395 }
396 } else {
Larry Finger40332e52012-04-19 16:32:41 -0500397 dm_digtable->rssi_val_min = 0;
398 dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
399 dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
400 dm_digtable->cur_igvalue = 0x20;
401 dm_digtable->pre_igvalue = 0;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600402 rtl92c_dm_write_dig(hw);
403 }
404}
405
406static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
407{
408 struct rtl_priv *rtlpriv = rtl_priv(hw);
409 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Finger40332e52012-04-19 16:32:41 -0500410 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600411
Larry Finger40332e52012-04-19 16:32:41 -0500412 if (dm_digtable->cursta_connectctate == DIG_STA_CONNECT) {
413 dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600414
Larry Finger40332e52012-04-19 16:32:41 -0500415 if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
416 if (dm_digtable->rssi_val_min <= 25)
417 dm_digtable->cur_cck_pd_state =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600418 CCK_PD_STAGE_LowRssi;
419 else
Larry Finger40332e52012-04-19 16:32:41 -0500420 dm_digtable->cur_cck_pd_state =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600421 CCK_PD_STAGE_HighRssi;
422 } else {
Larry Finger40332e52012-04-19 16:32:41 -0500423 if (dm_digtable->rssi_val_min <= 20)
424 dm_digtable->cur_cck_pd_state =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600425 CCK_PD_STAGE_LowRssi;
426 else
Larry Finger40332e52012-04-19 16:32:41 -0500427 dm_digtable->cur_cck_pd_state =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600428 CCK_PD_STAGE_HighRssi;
429 }
430 } else {
Larry Finger40332e52012-04-19 16:32:41 -0500431 dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600432 }
433
Larry Finger40332e52012-04-19 16:32:41 -0500434 if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
435 if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600436 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
Larry Finger40332e52012-04-19 16:32:41 -0500437 dm_digtable->cur_cck_fa_state =
Larry Finger8c96fcf2011-02-11 14:33:58 -0600438 CCK_FA_STAGE_High;
439 else
Larry Finger40332e52012-04-19 16:32:41 -0500440 dm_digtable->cur_cck_fa_state = CCK_FA_STAGE_Low;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600441
Larry Finger40332e52012-04-19 16:32:41 -0500442 if (dm_digtable->pre_cck_fa_state !=
443 dm_digtable->cur_cck_fa_state) {
444 if (dm_digtable->cur_cck_fa_state ==
Larry Finger8c96fcf2011-02-11 14:33:58 -0600445 CCK_FA_STAGE_Low)
446 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
447 0x83);
448 else
449 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
450 0xcd);
451
Larry Finger40332e52012-04-19 16:32:41 -0500452 dm_digtable->pre_cck_fa_state =
453 dm_digtable->cur_cck_fa_state;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600454 }
455
456 rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
457
458 if (IS_92C_SERIAL(rtlhal->version))
459 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
460 MASKBYTE2, 0xd7);
461 } else {
462 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
463 rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
464
465 if (IS_92C_SERIAL(rtlhal->version))
466 rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
467 MASKBYTE2, 0xd3);
468 }
Larry Finger40332e52012-04-19 16:32:41 -0500469 dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600470 }
471
Joe Perchesf30d7502012-01-04 19:40:41 -0800472 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "CCKPDStage=%x\n",
Larry Finger40332e52012-04-19 16:32:41 -0500473 dm_digtable->cur_cck_pd_state);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600474
Joe Perchesf30d7502012-01-04 19:40:41 -0800475 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "is92C=%x\n",
476 IS_92C_SERIAL(rtlhal->version));
Larry Finger8c96fcf2011-02-11 14:33:58 -0600477}
478
479static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
480{
Larry Finger40332e52012-04-19 16:32:41 -0500481 struct rtl_priv *rtlpriv = rtl_priv(hw);
482 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600483 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
484
Mike McCormacke10542c2011-06-20 10:47:51 +0900485 if (mac->act_scanning)
Larry Finger8c96fcf2011-02-11 14:33:58 -0600486 return;
487
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500488 if (mac->link_state >= MAC80211_LINKED)
Larry Finger40332e52012-04-19 16:32:41 -0500489 dm_digtable->cursta_connectctate = DIG_STA_CONNECT;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600490 else
Larry Finger40332e52012-04-19 16:32:41 -0500491 dm_digtable->cursta_connectctate = DIG_STA_DISCONNECT;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600492
493 rtl92c_dm_initial_gain_sta(hw);
494 rtl92c_dm_initial_gain_multi_sta(hw);
495 rtl92c_dm_cck_packet_detection_thresh(hw);
496
Larry Finger40332e52012-04-19 16:32:41 -0500497 dm_digtable->presta_connectstate = dm_digtable->cursta_connectctate;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600498
499}
500
501static void rtl92c_dm_dig(struct ieee80211_hw *hw)
502{
503 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500504 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600505
Larry Finger7ea47242011-02-19 16:28:57 -0600506 if (rtlpriv->dm.dm_initialgain_enable == false)
Larry Finger8c96fcf2011-02-11 14:33:58 -0600507 return;
Larry Finger40332e52012-04-19 16:32:41 -0500508 if (dm_digtable->dig_enable_flag == false)
Larry Finger8c96fcf2011-02-11 14:33:58 -0600509 return;
510
511 rtl92c_dm_ctrl_initgain_by_twoport(hw);
512
513}
514
515static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
516{
517 struct rtl_priv *rtlpriv = rtl_priv(hw);
518
Larry Finger7ea47242011-02-19 16:28:57 -0600519 rtlpriv->dm.dynamic_txpower_enable = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600520
521 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
522 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
523}
524
525void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
526{
527 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger40332e52012-04-19 16:32:41 -0500528 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600529
530 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800531 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n",
Larry Finger40332e52012-04-19 16:32:41 -0500532 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
533 dm_digtable->backoff_val);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600534
Larry Finger40332e52012-04-19 16:32:41 -0500535 dm_digtable->cur_igvalue += 2;
536 if (dm_digtable->cur_igvalue > 0x3f)
537 dm_digtable->cur_igvalue = 0x3f;
Jingjun Wua9b89e22012-03-02 20:52:14 -0600538
Larry Finger40332e52012-04-19 16:32:41 -0500539 if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600540 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
Larry Finger40332e52012-04-19 16:32:41 -0500541 dm_digtable->cur_igvalue);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600542 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
Larry Finger40332e52012-04-19 16:32:41 -0500543 dm_digtable->cur_igvalue);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600544
Larry Finger40332e52012-04-19 16:32:41 -0500545 dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600546 }
547}
Larry Finger1472d3a2011-02-23 10:24:58 -0600548EXPORT_SYMBOL(rtl92c_dm_write_dig);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600549
550static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
551{
552 struct rtl_priv *rtlpriv = rtl_priv(hw);
553 long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
554
555 u8 h2c_parameter[3] = { 0 };
556
557 return;
558
559 if (tmpentry_max_pwdb != 0) {
560 rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
561 tmpentry_max_pwdb;
562 } else {
563 rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
564 }
565
566 if (tmpentry_min_pwdb != 0xff) {
567 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
568 tmpentry_min_pwdb;
569 } else {
570 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
571 }
572
573 h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
574 h2c_parameter[0] = 0;
575
576 rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
577}
578
579void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
580{
581 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger7ea47242011-02-19 16:28:57 -0600582 rtlpriv->dm.current_turbo_edca = false;
583 rtlpriv->dm.is_any_nonbepkts = false;
584 rtlpriv->dm.is_cur_rdlstate = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600585}
Larry Finger1472d3a2011-02-23 10:24:58 -0600586EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600587
588static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
589{
590 struct rtl_priv *rtlpriv = rtl_priv(hw);
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500591 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600592 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500593
Larry Finger8c96fcf2011-02-11 14:33:58 -0600594 static u64 last_txok_cnt;
595 static u64 last_rxok_cnt;
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500596 static u32 last_bt_edca_ul;
597 static u32 last_bt_edca_dl;
598 u64 cur_txok_cnt = 0;
599 u64 cur_rxok_cnt = 0;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600600 u32 edca_be_ul = 0x5ea42b;
601 u32 edca_be_dl = 0x5ea42b;
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500602 bool bt_change_edca = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600603
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500604 if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
605 (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
606 rtlpriv->dm.current_turbo_edca = false;
607 last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
608 last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
609 }
610
611 if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
612 edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
613 bt_change_edca = true;
614 }
615
616 if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
617 edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
618 bt_change_edca = true;
619 }
Larry Finger8c96fcf2011-02-11 14:33:58 -0600620
621 if (mac->link_state != MAC80211_LINKED) {
Larry Finger7ea47242011-02-19 16:28:57 -0600622 rtlpriv->dm.current_turbo_edca = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600623 return;
624 }
625
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500626 if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600627 if (!(edca_be_ul & 0xffff0000))
628 edca_be_ul |= 0x005e0000;
629
630 if (!(edca_be_dl & 0xffff0000))
631 edca_be_dl |= 0x005e0000;
632 }
633
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500634 if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
635 (!rtlpriv->dm.disable_framebursting))) {
636
Larry Finger8c96fcf2011-02-11 14:33:58 -0600637 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
638 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500639
Larry Finger8c96fcf2011-02-11 14:33:58 -0600640 if (cur_rxok_cnt > 4 * cur_txok_cnt) {
Larry Finger7ea47242011-02-19 16:28:57 -0600641 if (!rtlpriv->dm.is_cur_rdlstate ||
642 !rtlpriv->dm.current_turbo_edca) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600643 rtl_write_dword(rtlpriv,
644 REG_EDCA_BE_PARAM,
645 edca_be_dl);
Larry Finger7ea47242011-02-19 16:28:57 -0600646 rtlpriv->dm.is_cur_rdlstate = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600647 }
648 } else {
Larry Finger7ea47242011-02-19 16:28:57 -0600649 if (rtlpriv->dm.is_cur_rdlstate ||
650 !rtlpriv->dm.current_turbo_edca) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600651 rtl_write_dword(rtlpriv,
652 REG_EDCA_BE_PARAM,
653 edca_be_ul);
Larry Finger7ea47242011-02-19 16:28:57 -0600654 rtlpriv->dm.is_cur_rdlstate = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600655 }
656 }
Larry Finger7ea47242011-02-19 16:28:57 -0600657 rtlpriv->dm.current_turbo_edca = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600658 } else {
Larry Finger7ea47242011-02-19 16:28:57 -0600659 if (rtlpriv->dm.current_turbo_edca) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600660 u8 tmp = AC0_BE;
661 rtlpriv->cfg->ops->set_hw_reg(hw,
662 HW_VAR_AC_PARAM,
663 (u8 *) (&tmp));
Larry Finger7ea47242011-02-19 16:28:57 -0600664 rtlpriv->dm.current_turbo_edca = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600665 }
666 }
667
Larry Finger7ea47242011-02-19 16:28:57 -0600668 rtlpriv->dm.is_any_nonbepkts = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600669 last_txok_cnt = rtlpriv->stats.txbytesunicast;
670 last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
671}
672
673static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
674 *hw)
675{
676 struct rtl_priv *rtlpriv = rtl_priv(hw);
677 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
678 struct rtl_phy *rtlphy = &(rtlpriv->phy);
679 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
680 u8 thermalvalue, delta, delta_lck, delta_iqk;
681 long ele_a, ele_d, temp_cck, val_x, value32;
Chaoming_Libeb5bc42011-04-25 12:53:35 -0500682 long val_y, ele_c = 0;
Larry Finger9f219bd2011-04-13 21:00:02 -0500683 u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600684 int i;
685 bool is2t = IS_92C_SERIAL(rtlhal->version);
Larry Finger7101f402011-06-10 11:05:23 -0500686 s8 txpwr_level[2] = {0, 0};
Larry Finger8c96fcf2011-02-11 14:33:58 -0600687 u8 ofdm_min_index = 6, rf;
688
Chaoming_Li3dad6182011-04-25 12:52:49 -0500689 rtlpriv->dm.txpower_trackinginit = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -0600690 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800691 "rtl92c_dm_txpower_tracking_callback_thermalmeter\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -0600692
693 thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
694
695 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800696 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
697 thermalvalue, rtlpriv->dm.thermalvalue,
698 rtlefuse->eeprom_thermalmeter);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600699
700 rtl92c_phy_ap_calibrate(hw, (thermalvalue -
701 rtlefuse->eeprom_thermalmeter));
702 if (is2t)
703 rf = 2;
704 else
705 rf = 1;
706
707 if (thermalvalue) {
708 ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
709 MASKDWORD) & MASKOFDM_D;
710
711 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
712 if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
713 ofdm_index_old[0] = (u8) i;
714
715 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800716 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
Larry Finger8c96fcf2011-02-11 14:33:58 -0600717 ROFDM0_XATXIQIMBALANCE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800718 ele_d, ofdm_index_old[0]);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600719 break;
720 }
721 }
722
723 if (is2t) {
724 ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
725 MASKDWORD) & MASKOFDM_D;
726
727 for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
728 if (ele_d == (ofdmswing_table[i] &
729 MASKOFDM_D)) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600730
731 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
Joe Perchesf30d7502012-01-04 19:40:41 -0800732 DBG_LOUD,
733 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
734 ROFDM0_XBTXIQIMBALANCE, ele_d,
735 ofdm_index_old[1]);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600736 break;
737 }
738 }
739 }
740
741 temp_cck =
742 rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
743
744 for (i = 0; i < CCK_TABLE_LENGTH; i++) {
Larry Finger7ea47242011-02-19 16:28:57 -0600745 if (rtlpriv->dm.cck_inch14) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600746 if (memcmp((void *)&temp_cck,
747 (void *)&cckswing_table_ch14[i][2],
748 4) == 0) {
749 cck_index_old = (u8) i;
750
751 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
752 DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800753 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",
754 RCCK0_TXFILTER2, temp_cck,
755 cck_index_old,
756 rtlpriv->dm.cck_inch14);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600757 break;
758 }
759 } else {
760 if (memcmp((void *)&temp_cck,
761 (void *)
762 &cckswing_table_ch1ch13[i][2],
763 4) == 0) {
764 cck_index_old = (u8) i;
765
766 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
767 DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800768 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",
769 RCCK0_TXFILTER2, temp_cck,
770 cck_index_old,
771 rtlpriv->dm.cck_inch14);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600772 break;
773 }
774 }
775 }
776
777 if (!rtlpriv->dm.thermalvalue) {
778 rtlpriv->dm.thermalvalue =
779 rtlefuse->eeprom_thermalmeter;
780 rtlpriv->dm.thermalvalue_lck = thermalvalue;
781 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
782 for (i = 0; i < rf; i++)
783 rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
784 rtlpriv->dm.cck_index = cck_index_old;
785 }
786
787 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
788 (thermalvalue - rtlpriv->dm.thermalvalue) :
789 (rtlpriv->dm.thermalvalue - thermalvalue);
790
791 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
792 (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
793 (rtlpriv->dm.thermalvalue_lck - thermalvalue);
794
795 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
796 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
797 (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
798
799 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800800 "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",
Larry Finger8c96fcf2011-02-11 14:33:58 -0600801 thermalvalue, rtlpriv->dm.thermalvalue,
802 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
Joe Perchesf30d7502012-01-04 19:40:41 -0800803 delta_iqk);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600804
805 if (delta_lck > 1) {
806 rtlpriv->dm.thermalvalue_lck = thermalvalue;
807 rtl92c_phy_lc_calibrate(hw);
808 }
809
810 if (delta > 0 && rtlpriv->dm.txpower_track_control) {
811 if (thermalvalue > rtlpriv->dm.thermalvalue) {
812 for (i = 0; i < rf; i++)
813 rtlpriv->dm.ofdm_index[i] -= delta;
814 rtlpriv->dm.cck_index -= delta;
815 } else {
816 for (i = 0; i < rf; i++)
817 rtlpriv->dm.ofdm_index[i] += delta;
818 rtlpriv->dm.cck_index += delta;
819 }
820
821 if (is2t) {
822 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800823 "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
824 rtlpriv->dm.ofdm_index[0],
825 rtlpriv->dm.ofdm_index[1],
826 rtlpriv->dm.cck_index);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600827 } else {
828 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800829 "temp OFDM_A_index=0x%x, cck_index=0x%x\n",
830 rtlpriv->dm.ofdm_index[0],
831 rtlpriv->dm.cck_index);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600832 }
833
834 if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
835 for (i = 0; i < rf; i++)
836 ofdm_index[i] =
837 rtlpriv->dm.ofdm_index[i]
838 + 1;
839 cck_index = rtlpriv->dm.cck_index + 1;
840 } else {
841 for (i = 0; i < rf; i++)
842 ofdm_index[i] =
843 rtlpriv->dm.ofdm_index[i];
844 cck_index = rtlpriv->dm.cck_index;
845 }
846
847 for (i = 0; i < rf; i++) {
848 if (txpwr_level[i] >= 0 &&
849 txpwr_level[i] <= 26) {
850 if (thermalvalue >
851 rtlefuse->eeprom_thermalmeter) {
852 if (delta < 5)
853 ofdm_index[i] -= 1;
854
855 else
856 ofdm_index[i] -= 2;
857 } else if (delta > 5 && thermalvalue <
858 rtlefuse->
859 eeprom_thermalmeter) {
860 ofdm_index[i] += 1;
861 }
862 } else if (txpwr_level[i] >= 27 &&
863 txpwr_level[i] <= 32
864 && thermalvalue >
865 rtlefuse->eeprom_thermalmeter) {
866 if (delta < 5)
867 ofdm_index[i] -= 1;
868
869 else
870 ofdm_index[i] -= 2;
871 } else if (txpwr_level[i] >= 32 &&
872 txpwr_level[i] <= 38 &&
873 thermalvalue >
874 rtlefuse->eeprom_thermalmeter
875 && delta > 5) {
876 ofdm_index[i] -= 1;
877 }
878 }
879
880 if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
881 if (thermalvalue >
882 rtlefuse->eeprom_thermalmeter) {
883 if (delta < 5)
884 cck_index -= 1;
885
886 else
887 cck_index -= 2;
888 } else if (delta > 5 && thermalvalue <
889 rtlefuse->eeprom_thermalmeter) {
890 cck_index += 1;
891 }
892 } else if (txpwr_level[i] >= 27 &&
893 txpwr_level[i] <= 32 &&
894 thermalvalue >
895 rtlefuse->eeprom_thermalmeter) {
896 if (delta < 5)
897 cck_index -= 1;
898
899 else
900 cck_index -= 2;
901 } else if (txpwr_level[i] >= 32 &&
902 txpwr_level[i] <= 38 &&
903 thermalvalue > rtlefuse->eeprom_thermalmeter
904 && delta > 5) {
905 cck_index -= 1;
906 }
907
908 for (i = 0; i < rf; i++) {
909 if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
910 ofdm_index[i] = OFDM_TABLE_SIZE - 1;
911
912 else if (ofdm_index[i] < ofdm_min_index)
913 ofdm_index[i] = ofdm_min_index;
914 }
915
916 if (cck_index > CCK_TABLE_SIZE - 1)
917 cck_index = CCK_TABLE_SIZE - 1;
918 else if (cck_index < 0)
919 cck_index = 0;
920
921 if (is2t) {
922 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800923 "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
924 ofdm_index[0], ofdm_index[1],
925 cck_index);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600926 } else {
927 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800928 "new OFDM_A_index=0x%x, cck_index=0x%x\n",
929 ofdm_index[0], cck_index);
Larry Finger8c96fcf2011-02-11 14:33:58 -0600930 }
931 }
932
933 if (rtlpriv->dm.txpower_track_control && delta != 0) {
934 ele_d =
935 (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
936 val_x = rtlphy->reg_e94;
937 val_y = rtlphy->reg_e9c;
938
939 if (val_x != 0) {
940 if ((val_x & 0x00000200) != 0)
941 val_x = val_x | 0xFFFFFC00;
942 ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
943
944 if ((val_y & 0x00000200) != 0)
945 val_y = val_y | 0xFFFFFC00;
946 ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
947
948 value32 = (ele_d << 22) |
949 ((ele_c & 0x3F) << 16) | ele_a;
950
951 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
952 MASKDWORD, value32);
953
954 value32 = (ele_c & 0x000003C0) >> 6;
955 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
956 value32);
957
958 value32 = ((val_x * ele_d) >> 7) & 0x01;
959 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
960 BIT(31), value32);
961
962 value32 = ((val_y * ele_d) >> 7) & 0x01;
963 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
964 BIT(29), value32);
965 } else {
966 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
967 MASKDWORD,
968 ofdmswing_table[ofdm_index[0]]);
969
970 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
971 0x00);
972 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
973 BIT(31) | BIT(29), 0x00);
974 }
975
Larry Finger7ea47242011-02-19 16:28:57 -0600976 if (!rtlpriv->dm.cck_inch14) {
Larry Finger8c96fcf2011-02-11 14:33:58 -0600977 rtl_write_byte(rtlpriv, 0xa22,
978 cckswing_table_ch1ch13[cck_index]
979 [0]);
980 rtl_write_byte(rtlpriv, 0xa23,
981 cckswing_table_ch1ch13[cck_index]
982 [1]);
983 rtl_write_byte(rtlpriv, 0xa24,
984 cckswing_table_ch1ch13[cck_index]
985 [2]);
986 rtl_write_byte(rtlpriv, 0xa25,
987 cckswing_table_ch1ch13[cck_index]
988 [3]);
989 rtl_write_byte(rtlpriv, 0xa26,
990 cckswing_table_ch1ch13[cck_index]
991 [4]);
992 rtl_write_byte(rtlpriv, 0xa27,
993 cckswing_table_ch1ch13[cck_index]
994 [5]);
995 rtl_write_byte(rtlpriv, 0xa28,
996 cckswing_table_ch1ch13[cck_index]
997 [6]);
998 rtl_write_byte(rtlpriv, 0xa29,
999 cckswing_table_ch1ch13[cck_index]
1000 [7]);
1001 } else {
1002 rtl_write_byte(rtlpriv, 0xa22,
1003 cckswing_table_ch14[cck_index]
1004 [0]);
1005 rtl_write_byte(rtlpriv, 0xa23,
1006 cckswing_table_ch14[cck_index]
1007 [1]);
1008 rtl_write_byte(rtlpriv, 0xa24,
1009 cckswing_table_ch14[cck_index]
1010 [2]);
1011 rtl_write_byte(rtlpriv, 0xa25,
1012 cckswing_table_ch14[cck_index]
1013 [3]);
1014 rtl_write_byte(rtlpriv, 0xa26,
1015 cckswing_table_ch14[cck_index]
1016 [4]);
1017 rtl_write_byte(rtlpriv, 0xa27,
1018 cckswing_table_ch14[cck_index]
1019 [5]);
1020 rtl_write_byte(rtlpriv, 0xa28,
1021 cckswing_table_ch14[cck_index]
1022 [6]);
1023 rtl_write_byte(rtlpriv, 0xa29,
1024 cckswing_table_ch14[cck_index]
1025 [7]);
1026 }
1027
1028 if (is2t) {
1029 ele_d = (ofdmswing_table[ofdm_index[1]] &
1030 0xFFC00000) >> 22;
1031
1032 val_x = rtlphy->reg_eb4;
1033 val_y = rtlphy->reg_ebc;
1034
1035 if (val_x != 0) {
1036 if ((val_x & 0x00000200) != 0)
1037 val_x = val_x | 0xFFFFFC00;
1038 ele_a = ((val_x * ele_d) >> 8) &
1039 0x000003FF;
1040
1041 if ((val_y & 0x00000200) != 0)
1042 val_y = val_y | 0xFFFFFC00;
1043 ele_c = ((val_y * ele_d) >> 8) &
1044 0x00003FF;
1045
1046 value32 = (ele_d << 22) |
1047 ((ele_c & 0x3F) << 16) | ele_a;
1048 rtl_set_bbreg(hw,
1049 ROFDM0_XBTXIQIMBALANCE,
1050 MASKDWORD, value32);
1051
1052 value32 = (ele_c & 0x000003C0) >> 6;
1053 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1054 MASKH4BITS, value32);
1055
1056 value32 = ((val_x * ele_d) >> 7) & 0x01;
1057 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1058 BIT(27), value32);
1059
1060 value32 = ((val_y * ele_d) >> 7) & 0x01;
1061 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1062 BIT(25), value32);
1063 } else {
1064 rtl_set_bbreg(hw,
1065 ROFDM0_XBTXIQIMBALANCE,
1066 MASKDWORD,
1067 ofdmswing_table[ofdm_index
1068 [1]]);
1069 rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1070 MASKH4BITS, 0x00);
1071 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1072 BIT(27) | BIT(25), 0x00);
1073 }
1074
1075 }
1076 }
1077
1078 if (delta_iqk > 3) {
1079 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1080 rtl92c_phy_iq_calibrate(hw, false);
1081 }
1082
1083 if (rtlpriv->dm.txpower_track_control)
1084 rtlpriv->dm.thermalvalue = thermalvalue;
1085 }
1086
Joe Perchesf30d7502012-01-04 19:40:41 -08001087 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001088
1089}
1090
1091static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
1092 struct ieee80211_hw *hw)
1093{
1094 struct rtl_priv *rtlpriv = rtl_priv(hw);
1095
Larry Finger7ea47242011-02-19 16:28:57 -06001096 rtlpriv->dm.txpower_tracking = true;
Chaoming_Li3dad6182011-04-25 12:52:49 -05001097 rtlpriv->dm.txpower_trackinginit = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -06001098
1099 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001100 "pMgntInfo->txpower_tracking = %d\n",
1101 rtlpriv->dm.txpower_tracking);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001102}
1103
1104static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
1105{
1106 rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
1107}
1108
1109static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
1110{
1111 rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
1112}
1113
1114static void rtl92c_dm_check_txpower_tracking_thermal_meter(
1115 struct ieee80211_hw *hw)
1116{
1117 struct rtl_priv *rtlpriv = rtl_priv(hw);
1118 static u8 tm_trigger;
1119
Larry Finger7ea47242011-02-19 16:28:57 -06001120 if (!rtlpriv->dm.txpower_tracking)
Larry Finger8c96fcf2011-02-11 14:33:58 -06001121 return;
1122
1123 if (!tm_trigger) {
1124 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
1125 0x60);
1126 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001127 "Trigger 92S Thermal Meter!!\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001128 tm_trigger = 1;
1129 return;
1130 } else {
1131 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001132 "Schedule TxPowerTracking direct call!!\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001133 rtl92c_dm_txpower_tracking_directcall(hw);
1134 tm_trigger = 0;
1135 }
1136}
1137
1138void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1139{
1140 rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
1141}
Larry Finger1472d3a2011-02-23 10:24:58 -06001142EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001143
1144void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1145{
1146 struct rtl_priv *rtlpriv = rtl_priv(hw);
1147 struct rate_adaptive *p_ra = &(rtlpriv->ra);
1148
1149 p_ra->ratr_state = DM_RATR_STA_INIT;
1150 p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1151
1152 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
Larry Finger7ea47242011-02-19 16:28:57 -06001153 rtlpriv->dm.useramask = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -06001154 else
Larry Finger7ea47242011-02-19 16:28:57 -06001155 rtlpriv->dm.useramask = false;
Larry Finger8c96fcf2011-02-11 14:33:58 -06001156
1157}
Larry Finger1472d3a2011-02-23 10:24:58 -06001158EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001159
1160static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
1161{
1162 struct rtl_priv *rtlpriv = rtl_priv(hw);
1163 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1164 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1165 struct rate_adaptive *p_ra = &(rtlpriv->ra);
1166 u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001167 struct ieee80211_sta *sta = NULL;
Larry Finger8c96fcf2011-02-11 14:33:58 -06001168
1169 if (is_hal_stop(rtlhal)) {
1170 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001171 "<---- driver is going to unload\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001172 return;
1173 }
1174
Larry Finger7ea47242011-02-19 16:28:57 -06001175 if (!rtlpriv->dm.useramask) {
Larry Finger8c96fcf2011-02-11 14:33:58 -06001176 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001177 "<---- driver does not control rate adaptive mask\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001178 return;
1179 }
1180
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001181 if (mac->link_state == MAC80211_LINKED &&
1182 mac->opmode == NL80211_IFTYPE_STATION) {
Larry Finger8c96fcf2011-02-11 14:33:58 -06001183 switch (p_ra->pre_ratr_state) {
1184 case DM_RATR_STA_HIGH:
1185 high_rssithresh_for_ra = 50;
1186 low_rssithresh_for_ra = 20;
1187 break;
1188 case DM_RATR_STA_MIDDLE:
1189 high_rssithresh_for_ra = 55;
1190 low_rssithresh_for_ra = 20;
1191 break;
1192 case DM_RATR_STA_LOW:
1193 high_rssithresh_for_ra = 50;
1194 low_rssithresh_for_ra = 25;
1195 break;
1196 default:
1197 high_rssithresh_for_ra = 50;
1198 low_rssithresh_for_ra = 20;
1199 break;
1200 }
1201
1202 if (rtlpriv->dm.undecorated_smoothed_pwdb >
1203 (long)high_rssithresh_for_ra)
1204 p_ra->ratr_state = DM_RATR_STA_HIGH;
1205 else if (rtlpriv->dm.undecorated_smoothed_pwdb >
1206 (long)low_rssithresh_for_ra)
1207 p_ra->ratr_state = DM_RATR_STA_MIDDLE;
1208 else
1209 p_ra->ratr_state = DM_RATR_STA_LOW;
1210
1211 if (p_ra->pre_ratr_state != p_ra->ratr_state) {
Joe Perchesf30d7502012-01-04 19:40:41 -08001212 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n",
1213 rtlpriv->dm.undecorated_smoothed_pwdb);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001214 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001215 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001216 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001217 "PreState = %d, CurState = %d\n",
1218 p_ra->pre_ratr_state, p_ra->ratr_state);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001219
Larry Fingerebecdcc2012-03-02 15:23:36 -06001220 /* Only the PCI card uses sta in the update rate table
1221 * callback routine */
1222 if (rtlhal->interface == INTF_PCI) {
1223 rcu_read_lock();
1224 sta = ieee80211_find_sta(mac->vif, mac->bssid);
1225 }
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001226 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
Larry Finger8c96fcf2011-02-11 14:33:58 -06001227 p_ra->ratr_state);
1228
1229 p_ra->pre_ratr_state = p_ra->ratr_state;
Larry Fingerebecdcc2012-03-02 15:23:36 -06001230 if (rtlhal->interface == INTF_PCI)
1231 rcu_read_unlock();
Larry Finger8c96fcf2011-02-11 14:33:58 -06001232 }
1233 }
1234}
1235
1236static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1237{
1238 dm_pstable.pre_ccastate = CCA_MAX;
1239 dm_pstable.cur_ccasate = CCA_MAX;
1240 dm_pstable.pre_rfstate = RF_MAX;
1241 dm_pstable.cur_rfstate = RF_MAX;
1242 dm_pstable.rssi_val_min = 0;
1243}
1244
Larry Finger8c96fcf2011-02-11 14:33:58 -06001245void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
1246{
1247 static u8 initialize;
1248 static u32 reg_874, reg_c70, reg_85c, reg_a74;
1249
1250 if (initialize == 0) {
1251 reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1252 MASKDWORD) & 0x1CC000) >> 14;
1253
1254 reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
1255 MASKDWORD) & BIT(3)) >> 3;
1256
1257 reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1258 MASKDWORD) & 0xFF000000) >> 24;
1259
1260 reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
1261
1262 initialize = 1;
1263 }
1264
1265 if (!bforce_in_normal) {
1266 if (dm_pstable.rssi_val_min != 0) {
1267 if (dm_pstable.pre_rfstate == RF_NORMAL) {
1268 if (dm_pstable.rssi_val_min >= 30)
1269 dm_pstable.cur_rfstate = RF_SAVE;
1270 else
1271 dm_pstable.cur_rfstate = RF_NORMAL;
1272 } else {
1273 if (dm_pstable.rssi_val_min <= 25)
1274 dm_pstable.cur_rfstate = RF_NORMAL;
1275 else
1276 dm_pstable.cur_rfstate = RF_SAVE;
1277 }
1278 } else {
1279 dm_pstable.cur_rfstate = RF_MAX;
1280 }
1281 } else {
1282 dm_pstable.cur_rfstate = RF_NORMAL;
1283 }
1284
1285 if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) {
1286 if (dm_pstable.cur_rfstate == RF_SAVE) {
1287 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1288 0x1C0000, 0x2);
1289 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
1290 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1291 0xFF000000, 0x63);
1292 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1293 0xC000, 0x2);
1294 rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
1295 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1296 rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
1297 } else {
1298 rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1299 0x1CC000, reg_874);
1300 rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
1301 reg_c70);
1302 rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
1303 reg_85c);
1304 rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
1305 rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1306 }
1307
1308 dm_pstable.pre_rfstate = dm_pstable.cur_rfstate;
1309 }
1310}
Larry Finger1472d3a2011-02-23 10:24:58 -06001311EXPORT_SYMBOL(rtl92c_dm_rf_saving);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001312
1313static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1314{
1315 struct rtl_priv *rtlpriv = rtl_priv(hw);
1316 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1317 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1318
1319 if (((mac->link_state == MAC80211_NOLINK)) &&
1320 (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
1321 dm_pstable.rssi_val_min = 0;
Joe Perchesf30d7502012-01-04 19:40:41 -08001322 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
Larry Finger8c96fcf2011-02-11 14:33:58 -06001323 }
1324
1325 if (mac->link_state == MAC80211_LINKED) {
1326 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1327 dm_pstable.rssi_val_min =
1328 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
1329 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001330 "AP Client PWDB = 0x%lx\n",
1331 dm_pstable.rssi_val_min);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001332 } else {
1333 dm_pstable.rssi_val_min =
1334 rtlpriv->dm.undecorated_smoothed_pwdb;
1335 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001336 "STA Default Port PWDB = 0x%lx\n",
1337 dm_pstable.rssi_val_min);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001338 }
1339 } else {
1340 dm_pstable.rssi_val_min =
1341 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
1342
1343 RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001344 "AP Ext Port PWDB = 0x%lx\n",
1345 dm_pstable.rssi_val_min);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001346 }
1347
1348 if (IS_92C_SERIAL(rtlhal->version))
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001349 ;/* rtl92c_dm_1r_cca(hw); */
1350 else
1351 rtl92c_dm_rf_saving(hw, false);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001352}
1353
1354void rtl92c_dm_init(struct ieee80211_hw *hw)
1355{
1356 struct rtl_priv *rtlpriv = rtl_priv(hw);
1357
1358 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1359 rtl92c_dm_diginit(hw);
1360 rtl92c_dm_init_dynamic_txpower(hw);
1361 rtl92c_dm_init_edca_turbo(hw);
1362 rtl92c_dm_init_rate_adaptive_mask(hw);
1363 rtl92c_dm_initialize_txpower_tracking(hw);
1364 rtl92c_dm_init_dynamic_bb_powersaving(hw);
1365}
Larry Finger1472d3a2011-02-23 10:24:58 -06001366EXPORT_SYMBOL(rtl92c_dm_init);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001367
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001368void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
1369{
1370 struct rtl_priv *rtlpriv = rtl_priv(hw);
1371 struct rtl_phy *rtlphy = &(rtlpriv->phy);
1372 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1373 long undecorated_smoothed_pwdb;
1374
1375 if (!rtlpriv->dm.dynamic_txpower_enable)
1376 return;
1377
1378 if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
1379 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1380 return;
1381 }
1382
1383 if ((mac->link_state < MAC80211_LINKED) &&
1384 (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
1385 RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -08001386 "Not connected to any\n");
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001387
1388 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1389
1390 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
1391 return;
1392 }
1393
1394 if (mac->link_state >= MAC80211_LINKED) {
1395 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1396 undecorated_smoothed_pwdb =
1397 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
1398 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001399 "AP Client PWDB = 0x%lx\n",
1400 undecorated_smoothed_pwdb);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001401 } else {
1402 undecorated_smoothed_pwdb =
1403 rtlpriv->dm.undecorated_smoothed_pwdb;
1404 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001405 "STA Default Port PWDB = 0x%lx\n",
1406 undecorated_smoothed_pwdb);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001407 }
1408 } else {
1409 undecorated_smoothed_pwdb =
1410 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
1411
1412 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001413 "AP Ext Port PWDB = 0x%lx\n",
1414 undecorated_smoothed_pwdb);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001415 }
1416
1417 if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
1418 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1419 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001420 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001421 } else if ((undecorated_smoothed_pwdb <
1422 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
1423 (undecorated_smoothed_pwdb >=
1424 TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
1425
1426 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1427 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001428 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001429 } else if (undecorated_smoothed_pwdb <
1430 (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
1431 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1432 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001433 "TXHIGHPWRLEVEL_NORMAL\n");
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001434 }
1435
1436 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
1437 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -08001438 "PHY_SetTxPowerLevel8192S() Channel = %d\n",
1439 rtlphy->current_channel);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001440 rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
1441 }
1442
1443 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
1444}
1445
Larry Finger8c96fcf2011-02-11 14:33:58 -06001446void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
1447{
1448 struct rtl_priv *rtlpriv = rtl_priv(hw);
1449 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
Larry Finger7ea47242011-02-19 16:28:57 -06001450 bool fw_current_inpsmode = false;
1451 bool fw_ps_awake = true;
Larry Finger8c96fcf2011-02-11 14:33:58 -06001452
1453 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
Larry Finger7ea47242011-02-19 16:28:57 -06001454 (u8 *) (&fw_current_inpsmode));
Larry Finger8c96fcf2011-02-11 14:33:58 -06001455 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
Larry Finger7ea47242011-02-19 16:28:57 -06001456 (u8 *) (&fw_ps_awake));
Larry Finger8c96fcf2011-02-11 14:33:58 -06001457
Larry Finger7ea47242011-02-19 16:28:57 -06001458 if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
1459 fw_ps_awake)
Larry Finger8c96fcf2011-02-11 14:33:58 -06001460 && (!ppsc->rfchange_inprogress)) {
1461 rtl92c_dm_pwdb_monitor(hw);
1462 rtl92c_dm_dig(hw);
1463 rtl92c_dm_false_alarm_counter_statistics(hw);
1464 rtl92c_dm_dynamic_bb_powersaving(hw);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001465 rtl92c_dm_dynamic_txpower(hw);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001466 rtl92c_dm_check_txpower_tracking(hw);
1467 rtl92c_dm_refresh_rate_adaptive_mask(hw);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001468 rtl92c_dm_bt_coexist(hw);
Larry Finger8c96fcf2011-02-11 14:33:58 -06001469 rtl92c_dm_check_edca_turbo(hw);
1470 }
1471}
Larry Finger1472d3a2011-02-23 10:24:58 -06001472EXPORT_SYMBOL(rtl92c_dm_watchdog);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001473
Chaoming_Li2b8359f2011-04-25 12:53:55 -05001474u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001475{
1476 struct rtl_priv *rtlpriv = rtl_priv(hw);
1477 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1478 long undecorated_smoothed_pwdb;
1479 u8 curr_bt_rssi_state = 0x00;
1480
1481 if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1482 undecorated_smoothed_pwdb =
1483 GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
1484 } else {
1485 if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)
1486 undecorated_smoothed_pwdb = 100;
1487 else
1488 undecorated_smoothed_pwdb =
1489 rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
1490 }
1491
1492 /* Check RSSI to determine HighPower/NormalPower state for
1493 * BT coexistence. */
1494 if (undecorated_smoothed_pwdb >= 67)
1495 curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
1496 else if (undecorated_smoothed_pwdb < 62)
1497 curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
1498
1499 /* Check RSSI to determine AMPDU setting for BT coexistence. */
1500 if (undecorated_smoothed_pwdb >= 40)
1501 curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
1502 else if (undecorated_smoothed_pwdb <= 32)
1503 curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
1504
1505 /* Marked RSSI state. It will be used to determine BT coexistence
1506 * setting later. */
1507 if (undecorated_smoothed_pwdb < 35)
1508 curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW;
1509 else
1510 curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
1511
1512 /* Set Tx Power according to BT status. */
1513 if (undecorated_smoothed_pwdb >= 30)
1514 curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW;
1515 else if (undecorated_smoothed_pwdb < 25)
1516 curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW);
1517
1518 /* Check BT state related to BT_Idle in B/G mode. */
1519 if (undecorated_smoothed_pwdb < 15)
1520 curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW;
1521 else
1522 curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
1523
1524 if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) {
1525 rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state;
1526 return true;
1527 } else {
1528 return false;
1529 }
1530}
Chaoming_Li2b8359f2011-04-25 12:53:55 -05001531EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
Chaoming_Libeb5bc42011-04-25 12:53:35 -05001532
1533static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
1534{
1535 struct rtl_priv *rtlpriv = rtl_priv(hw);
1536 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1537
1538 u32 polling, ratio_tx, ratio_pri;
1539 u32 bt_tx, bt_pri;
1540 u8 bt_state;
1541 u8 cur_service_type;
1542
1543 if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
1544 return false;
1545
1546 bt_state = rtl_read_byte(rtlpriv, 0x4fd);
1547 bt_tx = rtl_read_dword(rtlpriv, 0x488);
1548 bt_tx = bt_tx & 0x00ffffff;
1549 bt_pri = rtl_read_dword(rtlpriv, 0x48c);
1550 bt_pri = bt_pri & 0x00ffffff;
1551 polling = rtl_read_dword(rtlpriv, 0x490);
1552
1553 if (bt_tx == 0xffffffff && bt_pri == 0xffffffff &&
1554 polling == 0xffffffff && bt_state == 0xff)
1555 return false;
1556
1557 bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1);
1558 if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) {
1559 rtlpcipriv->bt_coexist.bt_cur_state = bt_state;
1560
1561 if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1562 rtlpcipriv->bt_coexist.bt_service = BT_IDLE;
1563
1564 bt_state = bt_state |
1565 ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1566 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1567 BIT_OFFSET_LEN_MASK_32(2, 1);
1568 rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1569 }
1570 return true;
1571 }
1572
1573 ratio_tx = bt_tx * 1000 / polling;
1574 ratio_pri = bt_pri * 1000 / polling;
1575 rtlpcipriv->bt_coexist.ratio_tx = ratio_tx;
1576 rtlpcipriv->bt_coexist.ratio_pri = ratio_pri;
1577
1578 if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1579
1580 if ((ratio_tx < 30) && (ratio_pri < 30))
1581 cur_service_type = BT_IDLE;
1582 else if ((ratio_pri > 110) && (ratio_pri < 250))
1583 cur_service_type = BT_SCO;
1584 else if ((ratio_tx >= 200) && (ratio_pri >= 200))
1585 cur_service_type = BT_BUSY;
1586 else if ((ratio_tx >= 350) && (ratio_tx < 500))
1587 cur_service_type = BT_OTHERBUSY;
1588 else if (ratio_tx >= 500)
1589 cur_service_type = BT_PAN;
1590 else
1591 cur_service_type = BT_OTHER_ACTION;
1592
1593 if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) {
1594 rtlpcipriv->bt_coexist.bt_service = cur_service_type;
1595 bt_state = bt_state |
1596 ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1597 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1598 ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ?
1599 0 : BIT_OFFSET_LEN_MASK_32(2, 1));
1600
1601 /* Add interrupt migration when bt is not ini
1602 * idle state (no traffic). */
1603 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1604 rtl_write_word(rtlpriv, 0x504, 0x0ccc);
1605 rtl_write_byte(rtlpriv, 0x506, 0x54);
1606 rtl_write_byte(rtlpriv, 0x507, 0x54);
1607 } else {
1608 rtl_write_byte(rtlpriv, 0x506, 0x00);
1609 rtl_write_byte(rtlpriv, 0x507, 0x00);
1610 }
1611
1612 rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1613 return true;
1614 }
1615 }
1616
1617 return false;
1618
1619}
1620
1621static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
1622{
1623 struct rtl_priv *rtlpriv = rtl_priv(hw);
1624 static bool media_connect;
1625
1626 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1627 media_connect = false;
1628 } else {
1629 if (!media_connect) {
1630 media_connect = true;
1631 return true;
1632 }
1633 media_connect = true;
1634 }
1635
1636 return false;
1637}
1638
1639static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
1640{
1641 struct rtl_priv *rtlpriv = rtl_priv(hw);
1642 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1643
1644
1645 if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) {
1646 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b;
1647 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b;
1648 } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) {
1649 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f;
1650 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f;
1651 } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) {
1652 if (rtlpcipriv->bt_coexist.ratio_tx > 160) {
1653 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f;
1654 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f;
1655 } else {
1656 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b;
1657 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b;
1658 }
1659 } else {
1660 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1661 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1662 }
1663
1664 if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) &&
1665 (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
1666 (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
1667 (rtlpcipriv->bt_coexist.bt_rssi_state &
1668 BT_RSSI_STATE_BG_EDCA_LOW)) {
1669 rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b;
1670 rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b;
1671 }
1672}
1673
1674static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw)
1675{
1676 struct rtl_priv *rtlpriv = rtl_priv(hw);
1677 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1678
1679
1680 /* Only enable HW BT coexist when BT in "Busy" state. */
1681 if (rtlpriv->mac80211.vendor == PEER_CISCO &&
1682 rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) {
1683 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1684 } else {
1685 if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) &&
1686 (rtlpcipriv->bt_coexist.bt_rssi_state &
1687 BT_RSSI_STATE_NORMAL_POWER)) {
1688 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1689 } else if ((rtlpcipriv->bt_coexist.bt_service ==
1690 BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
1691 WIRELESS_MODE_N_24G) &&
1692 (rtlpcipriv->bt_coexist.bt_rssi_state &
1693 BT_RSSI_STATE_SPECIAL_LOW)) {
1694 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1695 } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) {
1696 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
1697 } else {
1698 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
1699 }
1700 }
1701
1702 if (rtlpcipriv->bt_coexist.bt_service == BT_PAN)
1703 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
1704 else
1705 rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
1706
1707 if (rtlpcipriv->bt_coexist.bt_rssi_state &
1708 BT_RSSI_STATE_NORMAL_POWER) {
1709 rtl92c_bt_set_normal(hw);
1710 } else {
1711 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1712 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1713 }
1714
1715 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1716 rtlpriv->cfg->ops->set_rfreg(hw,
1717 RF90_PATH_A,
1718 0x1e,
1719 0xf0, 0xf);
1720 } else {
1721 rtlpriv->cfg->ops->set_rfreg(hw,
1722 RF90_PATH_A, 0x1e, 0xf0,
1723 rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1724 }
1725
1726 if (!rtlpriv->dm.dynamic_txpower_enable) {
1727 if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1728 if (rtlpcipriv->bt_coexist.bt_rssi_state &
1729 BT_RSSI_STATE_TXPOWER_LOW) {
1730 rtlpriv->dm.dynamic_txhighpower_lvl =
1731 TXHIGHPWRLEVEL_BT2;
1732 } else {
1733 rtlpriv->dm.dynamic_txhighpower_lvl =
1734 TXHIGHPWRLEVEL_BT1;
1735 }
1736 } else {
1737 rtlpriv->dm.dynamic_txhighpower_lvl =
1738 TXHIGHPWRLEVEL_NORMAL;
1739 }
1740 rtl92c_phy_set_txpower_level(hw,
1741 rtlpriv->phy.current_channel);
1742 }
1743}
1744
1745static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
1746{
1747 struct rtl_priv *rtlpriv = rtl_priv(hw);
1748 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1749
1750 if (rtlpcipriv->bt_coexist.bt_cur_state) {
1751 if (rtlpcipriv->bt_coexist.bt_ant_isolation)
1752 rtl92c_bt_ant_isolation(hw);
1753 } else {
1754 rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
1755 rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
1756 rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1757
1758 rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1759 rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1760 }
1761}
1762
1763void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
1764{
1765 struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1766
1767 bool wifi_connect_change;
1768 bool bt_state_change;
1769 bool rssi_state_change;
1770
1771 if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
1772 (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
1773
1774 wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
1775 bt_state_change = rtl92c_bt_state_change(hw);
1776 rssi_state_change = rtl92c_bt_rssi_state_change(hw);
1777
1778 if (wifi_connect_change || bt_state_change || rssi_state_change)
1779 rtl92c_check_bt_change(hw);
1780 }
1781}
Chaoming_Li2b8359f2011-04-25 12:53:55 -05001782EXPORT_SYMBOL(rtl92c_dm_bt_coexist);