1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2013  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 #include "../wifi.h"
26 #include <linux/vmalloc.h>
27 #include <linux/module.h>
28 
29 #include "rtl_btc.h"
30 #include "halbt_precomp.h"
31 
32 static struct rtl_btc_ops rtl_btc_operation = {
33 	.btc_init_variables = rtl_btc_init_variables,
34 	.btc_init_hal_vars = rtl_btc_init_hal_vars,
35 	.btc_init_hw_config = rtl_btc_init_hw_config,
36 	.btc_ips_notify = rtl_btc_ips_notify,
37 	.btc_lps_notify = rtl_btc_lps_notify,
38 	.btc_scan_notify = rtl_btc_scan_notify,
39 	.btc_connect_notify = rtl_btc_connect_notify,
40 	.btc_mediastatus_notify = rtl_btc_mediastatus_notify,
41 	.btc_periodical = rtl_btc_periodical,
42 	.btc_halt_notify = rtl_btc_halt_notify,
43 	.btc_btinfo_notify = rtl_btc_btinfo_notify,
44 	.btc_btmpinfo_notify = rtl_btc_btmpinfo_notify,
45 	.btc_is_limited_dig = rtl_btc_is_limited_dig,
46 	.btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
47 	.btc_is_bt_disabled = rtl_btc_is_bt_disabled,
48 	.btc_special_packet_notify = rtl_btc_special_packet_notify,
49 	.btc_record_pwr_mode = rtl_btc_record_pwr_mode,
50 	.btc_get_lps_val = rtl_btc_get_lps_val,
51 	.btc_get_rpwm_val = rtl_btc_get_rpwm_val,
52 	.btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
53 	.btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
54 	.btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
55 };
56 
57 void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
58 {
59 	u8 safe_len;
60 
61 	safe_len = sizeof(gl_bt_coexist.pwr_mode_val);
62 
63 	if (safe_len > len)
64 		safe_len = len;
65 
66 	memcpy(gl_bt_coexist.pwr_mode_val, buf, safe_len);
67 }
68 
69 u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
70 {
71 	return gl_bt_coexist.bt_info.lps_val;
72 }
73 
74 u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
75 {
76 	return gl_bt_coexist.bt_info.rpwm_val;
77 }
78 
79 bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
80 {
81 	return gl_bt_coexist.bt_info.bt_ctrl_lps;
82 }
83 
84 bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
85 {
86 	return gl_bt_coexist.bt_info.bt_lps_on;
87 }
88 
89 void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
90 			   u8 *ctrl_agg_size, u8 *agg_size)
91 {
92 	if (reject_agg)
93 		*reject_agg = gl_bt_coexist.bt_info.reject_agg_pkt;
94 	if (ctrl_agg_size)
95 		*ctrl_agg_size = gl_bt_coexist.bt_info.bt_ctrl_agg_buf_size;
96 	if (agg_size)
97 		*agg_size = gl_bt_coexist.bt_info.agg_buf_size;
98 }
99 
100 void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
101 {
102 	exhalbtc_initlize_variables();
103 	exhalbtc_bind_bt_coex_withadapter(rtlpriv);
104 }
105 
106 void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
107 {
108 	/* move ant_num, bt_type and single_ant_path to
109 	 * exhalbtc_bind_bt_coex_withadapter()
110 	 */
111 }
112 
113 void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
114 {
115 	u8 bt_exist;
116 
117 	bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
118 	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
119 		"%s, bt_exist is %d\n", __func__, bt_exist);
120 
121 	exhalbtc_init_hw_config(&gl_bt_coexist, !bt_exist);
122 	exhalbtc_init_coex_dm(&gl_bt_coexist);
123 }
124 
125 void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
126 {
127 	exhalbtc_ips_notify(&gl_bt_coexist, type);
128 }
129 
130 void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
131 {
132 	exhalbtc_lps_notify(&gl_bt_coexist, type);
133 }
134 
135 void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
136 {
137 	exhalbtc_scan_notify(&gl_bt_coexist, scantype);
138 }
139 
140 void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
141 {
142 	exhalbtc_connect_notify(&gl_bt_coexist, action);
143 }
144 
145 void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
146 				enum rt_media_status mstatus)
147 {
148 	exhalbtc_mediastatus_notify(&gl_bt_coexist, mstatus);
149 }
150 
151 void rtl_btc_periodical(struct rtl_priv *rtlpriv)
152 {
153 	/*rtl_bt_dm_monitor();*/
154 	exhalbtc_periodical(&gl_bt_coexist);
155 }
156 
157 void rtl_btc_halt_notify(void)
158 {
159 	struct btc_coexist *btcoexist = &gl_bt_coexist;
160 
161 	exhalbtc_halt_notify(btcoexist);
162 }
163 
164 void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
165 {
166 	exhalbtc_bt_info_notify(&gl_bt_coexist, tmp_buf, length);
167 }
168 
169 void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
170 {
171 	u8 extid, seq, len;
172 	u16 bt_real_fw_ver;
173 	u8 bt_fw_ver;
174 
175 	if ((length < 4) || (!tmp_buf))
176 		return;
177 
178 	extid = tmp_buf[0];
179 	/* not response from BT FW then exit*/
180 	if (extid != 1) /* C2H_TRIG_BY_BT_FW = 1 */
181 		return;
182 
183 	len = tmp_buf[1] >> 4;
184 	seq = tmp_buf[2] >> 4;
185 
186 	/* BT Firmware version response */
187 	if (seq == 0x0E) {
188 		bt_real_fw_ver = tmp_buf[3] | (tmp_buf[4] << 8);
189 		bt_fw_ver = tmp_buf[5];
190 
191 		gl_bt_coexist.bt_info.bt_real_fw_ver = bt_real_fw_ver;
192 		gl_bt_coexist.bt_info.bt_fw_ver = bt_fw_ver;
193 	}
194 }
195 
196 bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv)
197 {
198 	return gl_bt_coexist.bt_info.limited_dig;
199 }
200 
201 bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
202 {
203 	bool bt_change_edca = false;
204 	u32 cur_edca_val;
205 	u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b;
206 	u32 edca_hs;
207 	u32 edca_addr = 0x504;
208 
209 	cur_edca_val = rtl_read_dword(rtlpriv, edca_addr);
210 	if (halbtc_is_wifi_uplink(rtlpriv)) {
211 		if (cur_edca_val != edca_bt_hs_uplink) {
212 			edca_hs = edca_bt_hs_uplink;
213 			bt_change_edca = true;
214 		}
215 	} else {
216 		if (cur_edca_val != edca_bt_hs_downlink) {
217 			edca_hs = edca_bt_hs_downlink;
218 			bt_change_edca = true;
219 		}
220 	}
221 
222 	if (bt_change_edca)
223 		rtl_write_dword(rtlpriv, edca_addr, edca_hs);
224 
225 	return true;
226 }
227 
228 bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
229 {
230 	/* It seems 'bt_disabled' is never be initialized or set. */
231 	if (gl_bt_coexist.bt_info.bt_disabled)
232 		return true;
233 	else
234 		return false;
235 }
236 
237 void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
238 {
239 	return exhalbtc_special_packet_notify(&gl_bt_coexist, pkt_type);
240 }
241 
242 struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
243 {
244 	return &rtl_btc_operation;
245 }
246 EXPORT_SYMBOL(rtl_btc_get_ops_pointer);
247 
248 
249 enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw)
250 {
251 	struct rtl_priv *rtlpriv = rtl_priv(hw);
252 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
253 	enum rt_media_status    m_status = RT_MEDIA_DISCONNECT;
254 
255 	u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
256 
257 	if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
258 		m_status = RT_MEDIA_CONNECT;
259 
260 	return m_status;
261 }
262 
263 u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)
264 {
265 	return rtlpriv->btcoexist.btc_info.btcoexist;
266 }
267 
268 MODULE_AUTHOR("Page He	<page_he@realsil.com.cn>");
269 MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
270 MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");
271 MODULE_LICENSE("GPL");
272 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
273 
274 static int __init rtl_btcoexist_module_init(void)
275 {
276 	return 0;
277 }
278 
279 static void __exit rtl_btcoexist_module_exit(void)
280 {
281 	return;
282 }
283 
284 module_init(rtl_btcoexist_module_init);
285 module_exit(rtl_btcoexist_module_exit);
286