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