net: wireless: rockchip_wlan: add rtl8723cs support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723cs / hal / phydm / phydm_pathdiv.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20
21 /* ************************************************************
22  * include files
23  * ************************************************************ */
24 #include "mp_precomp.h"
25 #include "phydm_precomp.h"
26
27 #if (defined(CONFIG_PATH_DIVERSITY))
28 #if RTL8814A_SUPPORT
29
30 void
31 phydm_dtp_fix_tx_path(
32         void    *p_dm_void,
33         u8      path
34 )
35 {
36         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
37         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div = &p_dm_odm->dm_path_div;
38         u8                      i, num_enable_path = 0;
39
40         if (path == p_dm_path_div->pre_tx_path)
41                 return;
42         else
43                 p_dm_path_div->pre_tx_path = path;
44
45         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(18) | BIT(19), 3);
46
47         for (i = 0; i < 4; i++) {
48                 if (path & BIT(i))
49                         num_enable_path++;
50         }
51         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" number of trun-on path : (( %d ))\n", num_enable_path));
52
53         if (num_enable_path == 1) {
54                 odm_set_bb_reg(p_dm_odm, 0x93c, 0xf00000, path);
55
56                 if (path == PHYDM_A) { /* 1-1 */
57                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A ))\n"));
58                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
59                 } else  if (path == PHYDM_B) { /* 1-2 */
60                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( B ))\n"));
61                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 0);
62                 } else  if (path == PHYDM_C) { /* 1-3 */
63                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( C ))\n"));
64                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 0);
65
66                 } else  if (path == PHYDM_D) { /* 1-4 */
67                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( D ))\n"));
68                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 0);
69                 }
70
71         } else  if (num_enable_path == 2) {
72                 odm_set_bb_reg(p_dm_odm, 0x93c, 0xf00000, path);
73                 odm_set_bb_reg(p_dm_odm, 0x940, 0xf0, path);
74
75                 if (path == PHYDM_AB) { /* 2-1 */
76                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A B ))\n"));
77                         /* set for 1ss */
78                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
79                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 1);
80                         /* set for 2ss */
81                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
82                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 1);
83                 } else  if (path == PHYDM_AC) { /* 2-2 */
84                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A C ))\n"));
85                         /* set for 1ss */
86                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
87                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 1);
88                         /* set for 2ss */
89                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
90                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 1);
91                 } else  if (path == PHYDM_AD) { /* 2-3 */
92                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A D ))\n"));
93                         /* set for 1ss */
94                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
95                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 1);
96                         /* set for 2ss */
97                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
98                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 1);
99                 } else  if (path == PHYDM_BC) { /* 2-4 */
100                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( B C ))\n"));
101                         /* set for 1ss */
102                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 0);
103                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 1);
104                         /* set for 2ss */
105                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 0);
106                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 1);
107                 } else  if (path == PHYDM_BD) { /* 2-5 */
108                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( B D ))\n"));
109                         /* set for 1ss */
110                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 0);
111                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 1);
112                         /* set for 2ss */
113                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 0);
114                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 1);
115                 } else  if (path == PHYDM_CD) { /* 2-6 */
116                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( C D ))\n"));
117                         /* set for 1ss */
118                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 0);
119                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 1);
120                         /* set for 2ss */
121                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 0);
122                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 1);
123                 }
124
125         } else  if (num_enable_path == 3) {
126                 odm_set_bb_reg(p_dm_odm, 0x93c, 0xf00000, path);
127                 odm_set_bb_reg(p_dm_odm, 0x940, 0xf0, path);
128                 odm_set_bb_reg(p_dm_odm, 0x940, 0xf0000, path);
129
130                 if (path == PHYDM_ABC) { /* 3-1 */
131                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A B C))\n"));
132                         /* set for 1ss */
133                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
134                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 1);
135                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 2);
136                         /* set for 2ss */
137                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
138                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 1);
139                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 2);
140                         /* set for 3ss */
141                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(21) | BIT(20), 0);
142                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(23) | BIT(22), 1);
143                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(25) | BIT(24), 2);
144                 } else  if (path == PHYDM_ABD) { /* 3-2 */
145                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A B D ))\n"));
146                         /* set for 1ss */
147                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
148                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 1);
149                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 2);
150                         /* set for 2ss */
151                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
152                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 1);
153                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 2);
154                         /* set for 3ss */
155                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(21) | BIT(20), 0);
156                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(23) | BIT(22), 1);
157                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(27) | BIT(26), 2);
158
159                 } else  if (path == PHYDM_ACD) { /* 3-3 */
160                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( A C D ))\n"));
161                         /* set for 1ss */
162                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(25) | BIT(24), 0);
163                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 1);
164                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 2);
165                         /* set for 2ss */
166                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(9) | BIT(8), 0);
167                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 1);
168                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 2);
169                         /* set for 3ss */
170                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(21) | BIT(20), 0);
171                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(25) | BIT(24), 1);
172                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(27) | BIT(26), 2);
173                 } else  if (path == PHYDM_BCD) { /* 3-4 */
174                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path (( B C D))\n"));
175                         /* set for 1ss */
176                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(27) | BIT(26), 0);
177                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(29) | BIT(28), 1);
178                         odm_set_bb_reg(p_dm_odm, 0x93c, BIT(31) | BIT(30), 2);
179                         /* set for 2ss */
180                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(11) | BIT(10), 0);
181                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(13) | BIT(12), 1);
182                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(15) | BIT(14), 2);
183                         /* set for 3ss */
184                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(23) | BIT(22), 0);
185                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(25) | BIT(24), 1);
186                         odm_set_bb_reg(p_dm_odm, 0x940, BIT(27) | BIT(26), 2);
187                 }
188         } else  if (num_enable_path == 4)
189                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" Trun on path ((A  B C D))\n"));
190
191 }
192
193 void
194 phydm_find_default_path(
195         void    *p_dm_void
196 )
197 {
198         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
199         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div = &p_dm_odm->dm_path_div;
200         u32     rssi_avg_a = 0, rssi_avg_b = 0, rssi_avg_c = 0, rssi_avg_d = 0, rssi_avg_bcd = 0;
201         u32     rssi_total_a = 0, rssi_total_b = 0, rssi_total_c = 0, rssi_total_d = 0;
202
203         /* 2 Default path Selection By RSSI */
204
205         rssi_avg_a = (p_dm_path_div->path_a_cnt_all > 0) ? (p_dm_path_div->path_a_sum_all / p_dm_path_div->path_a_cnt_all) : 0 ;
206         rssi_avg_b = (p_dm_path_div->path_b_cnt_all > 0) ? (p_dm_path_div->path_b_sum_all / p_dm_path_div->path_b_cnt_all) : 0 ;
207         rssi_avg_c = (p_dm_path_div->path_c_cnt_all > 0) ? (p_dm_path_div->path_c_sum_all / p_dm_path_div->path_c_cnt_all) : 0 ;
208         rssi_avg_d = (p_dm_path_div->path_d_cnt_all > 0) ? (p_dm_path_div->path_d_sum_all / p_dm_path_div->path_d_cnt_all) : 0 ;
209
210
211         p_dm_path_div->path_a_sum_all = 0;
212         p_dm_path_div->path_a_cnt_all = 0;
213         p_dm_path_div->path_b_sum_all = 0;
214         p_dm_path_div->path_b_cnt_all = 0;
215         p_dm_path_div->path_c_sum_all = 0;
216         p_dm_path_div->path_c_cnt_all = 0;
217         p_dm_path_div->path_d_sum_all = 0;
218         p_dm_path_div->path_d_cnt_all = 0;
219
220         if (p_dm_path_div->use_path_a_as_default_ant == 1) {
221                 rssi_avg_bcd = (rssi_avg_b + rssi_avg_c + rssi_avg_d) / 3;
222
223                 if ((rssi_avg_a + ANT_DECT_RSSI_TH) > rssi_avg_bcd) {
224                         p_dm_path_div->is_path_a_exist = true;
225                         p_dm_path_div->default_path = PATH_A;
226                 } else
227                         p_dm_path_div->is_path_a_exist = false;
228         } else {
229                 if ((rssi_avg_a >= rssi_avg_b) && (rssi_avg_a >= rssi_avg_c) && (rssi_avg_a >= rssi_avg_d))
230                         p_dm_path_div->default_path = PATH_A;
231                 else if ((rssi_avg_b >= rssi_avg_c) && (rssi_avg_b >= rssi_avg_d))
232                         p_dm_path_div->default_path = PATH_B;
233                 else if (rssi_avg_c >= rssi_avg_d)
234                         p_dm_path_div->default_path = PATH_C;
235                 else
236                         p_dm_path_div->default_path = PATH_D;
237         }
238
239
240 }
241
242
243 void
244 phydm_candidate_dtp_update(
245         void    *p_dm_void
246 )
247 {
248         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
249         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div = &p_dm_odm->dm_path_div;
250
251         p_dm_path_div->num_candidate = 3;
252
253         if (p_dm_path_div->use_path_a_as_default_ant == 1) {
254                 if (p_dm_path_div->num_tx_path == 3) {
255                         if (p_dm_path_div->is_path_a_exist) {
256                                 p_dm_path_div->ant_candidate_1 =  PHYDM_ABC;
257                                 p_dm_path_div->ant_candidate_2 =  PHYDM_ABD;
258                                 p_dm_path_div->ant_candidate_3 =  PHYDM_ACD;
259                         } else { /* use path BCD */
260                                 p_dm_path_div->num_candidate = 1;
261                                 phydm_dtp_fix_tx_path(p_dm_odm, PHYDM_BCD);
262                                 return;
263                         }
264                 } else  if (p_dm_path_div->num_tx_path == 2) {
265                         if (p_dm_path_div->is_path_a_exist) {
266                                 p_dm_path_div->ant_candidate_1 =  PHYDM_AB;
267                                 p_dm_path_div->ant_candidate_2 =  PHYDM_AC;
268                                 p_dm_path_div->ant_candidate_3 =  PHYDM_AD;
269                         } else {
270                                 p_dm_path_div->ant_candidate_1 =  PHYDM_BC;
271                                 p_dm_path_div->ant_candidate_2 =  PHYDM_BD;
272                                 p_dm_path_div->ant_candidate_3 =  PHYDM_CD;
273                         }
274                 }
275         } else {
276                 /* 2 3 TX mode */
277                 if (p_dm_path_div->num_tx_path == 3) { /* choose 3 ant form 4 */
278                         if (p_dm_path_div->default_path == PATH_A) { /* choose 2 ant form 3 */
279                                 p_dm_path_div->ant_candidate_1 =  PHYDM_ABC;
280                                 p_dm_path_div->ant_candidate_2 =  PHYDM_ABD;
281                                 p_dm_path_div->ant_candidate_3 =  PHYDM_ACD;
282                         } else if (p_dm_path_div->default_path == PATH_B) {
283                                 p_dm_path_div->ant_candidate_1 =  PHYDM_ABC;
284                                 p_dm_path_div->ant_candidate_2 =  PHYDM_ABD;
285                                 p_dm_path_div->ant_candidate_3 =  PHYDM_BCD;
286                         } else if (p_dm_path_div->default_path == PATH_C) {
287                                 p_dm_path_div->ant_candidate_1 =  PHYDM_ABC;
288                                 p_dm_path_div->ant_candidate_2 =  PHYDM_ACD;
289                                 p_dm_path_div->ant_candidate_3 =  PHYDM_BCD;
290                         } else if (p_dm_path_div->default_path == PATH_D) {
291                                 p_dm_path_div->ant_candidate_1 =  PHYDM_ABD;
292                                 p_dm_path_div->ant_candidate_2 =  PHYDM_ACD;
293                                 p_dm_path_div->ant_candidate_3 =  PHYDM_BCD;
294                         }
295                 }
296
297                 /* 2 2 TX mode */
298                 else if (p_dm_path_div->num_tx_path == 2) { /* choose 2 ant form 4 */
299                         if (p_dm_path_div->default_path == PATH_A) { /* choose 2 ant form 3 */
300                                 p_dm_path_div->ant_candidate_1 =  PHYDM_AB;
301                                 p_dm_path_div->ant_candidate_2 =  PHYDM_AC;
302                                 p_dm_path_div->ant_candidate_3 =  PHYDM_AD;
303                         } else if (p_dm_path_div->default_path == PATH_B) {
304                                 p_dm_path_div->ant_candidate_1 =  PHYDM_AB;
305                                 p_dm_path_div->ant_candidate_2 =  PHYDM_BC;
306                                 p_dm_path_div->ant_candidate_3 =  PHYDM_BD;
307                         } else if (p_dm_path_div->default_path == PATH_C) {
308                                 p_dm_path_div->ant_candidate_1 =  PHYDM_AC;
309                                 p_dm_path_div->ant_candidate_2 =  PHYDM_BC;
310                                 p_dm_path_div->ant_candidate_3 =  PHYDM_CD;
311                         } else if (p_dm_path_div->default_path == PATH_D) {
312                                 p_dm_path_div->ant_candidate_1 =  PHYDM_AD;
313                                 p_dm_path_div->ant_candidate_2 =  PHYDM_BD;
314                                 p_dm_path_div->ant_candidate_3 =  PHYDM_CD;
315                         }
316                 }
317         }
318 }
319
320
321 void
322 phydm_dynamic_tx_path(
323         void    *p_dm_void
324 )
325 {
326         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
327         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div = &p_dm_odm->dm_path_div;
328
329         struct sta_info *p_entry;
330         u32     i;
331         u8      num_client = 0;
332         u8      h2c_parameter[6] = {0};
333
334
335         if (!p_dm_odm->is_linked) { /* is_linked==False */
336                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("DTP_8814 [No Link!!!]\n"));
337
338                 if (p_dm_path_div->is_become_linked == true) {
339                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" [Be disconnected]----->\n"));
340                         p_dm_path_div->is_become_linked = p_dm_odm->is_linked;
341                 }
342                 return;
343         } else {
344                 if (p_dm_path_div->is_become_linked == false) {
345                         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, (" [Be Linked !!!]----->\n"));
346                         p_dm_path_div->is_become_linked = p_dm_odm->is_linked;
347                 }
348         }
349
350         /* 2 [period CTRL] */
351         if (p_dm_path_div->dtp_period >= 2)
352                 p_dm_path_div->dtp_period = 0;
353         else {
354                 /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Phydm_Dynamic_Tx_Path_8814A()  Stay = (( %d ))\n",p_dm_path_div->dtp_period)); */
355                 p_dm_path_div->dtp_period++;
356                 return;
357         }
358
359
360         /* 2 [Fix path] */
361         if (p_dm_odm->path_select != PHYDM_AUTO_PATH)
362                 return;
363
364         /* 2 [Check Bfer] */
365 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
366 #if (BEAMFORMING_SUPPORT == 1)
367         {
368                 enum beamforming_cap            beamform_cap = (p_dm_odm->beamforming_info.beamform_cap);
369
370                 if (beamform_cap & BEAMFORMER_CAP) { /* BFmer On  &&   Div On->Div Off */
371                         if (p_dm_path_div->fix_path_bfer == 0) {
372                                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("[ PathDiv : OFF ]   BFmer ==1\n"));
373                                 p_dm_path_div->fix_path_bfer = 1 ;
374                         }
375                         return;
376                 } else { /* BFmer Off   &&   Div Off->Div On */
377                         if (p_dm_path_div->fix_path_bfer == 1) {
378                                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("[ PathDiv : ON ]   BFmer ==0\n"));
379                                 p_dm_path_div->fix_path_bfer = 0;
380                         }
381                 }
382         }
383 #endif
384 #endif
385
386         if (p_dm_path_div->use_path_a_as_default_ant == 1) {
387                 phydm_find_default_path(p_dm_odm);
388                 phydm_candidate_dtp_update(p_dm_odm);
389         } else {
390                 if (p_dm_path_div->phydm_dtp_state == PHYDM_DTP_INIT) {
391                         phydm_find_default_path(p_dm_odm);
392                         phydm_candidate_dtp_update(p_dm_odm);
393                         p_dm_path_div->phydm_dtp_state = PHYDM_DTP_RUNNING_1;
394                 }
395
396                 else    if (p_dm_path_div->phydm_dtp_state == PHYDM_DTP_RUNNING_1) {
397                         p_dm_path_div->dtp_check_patha_counter++;
398
399                         if (p_dm_path_div->dtp_check_patha_counter >= NUM_RESET_DTP_PERIOD) {
400                                 p_dm_path_div->dtp_check_patha_counter = 0;
401                                 p_dm_path_div->phydm_dtp_state = PHYDM_DTP_INIT;
402                         }
403                         /* 2 Search space update */
404                         else {
405                                 /* 1.  find the worst candidate */
406
407
408                                 /* 2. repalce the worst candidate */
409                         }
410                 }
411         }
412
413         /* 2 Dynamic path Selection H2C */
414
415         if (p_dm_path_div->num_candidate == 1)
416                 return;
417         else {
418                 h2c_parameter[0] =  p_dm_path_div->num_candidate;
419                 h2c_parameter[1] =  p_dm_path_div->num_tx_path;
420                 h2c_parameter[2] =  p_dm_path_div->ant_candidate_1;
421                 h2c_parameter[3] =  p_dm_path_div->ant_candidate_2;
422                 h2c_parameter[4] =  p_dm_path_div->ant_candidate_3;
423
424                 odm_fill_h2c_cmd(p_dm_odm, PHYDM_H2C_DYNAMIC_TX_PATH, 6, h2c_parameter);
425         }
426
427 }
428
429
430
431 void
432 phydm_dynamic_tx_path_init(
433         void    *p_dm_void
434 )
435 {
436         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
437         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div  = &(p_dm_odm->dm_path_div);
438         struct _ADAPTER         *p_adapter = p_dm_odm->adapter;
439 #if ((DM_ODM_SUPPORT_TYPE == ODM_WIN) && USB_SWITCH_SUPPORT)
440         USB_MODE_MECH   *p_usb_mode_mech = &p_adapter->usb_mode_mechanism;
441 #endif
442         u8                      search_space_2[NUM_CHOOSE2_FROM4] = {PHYDM_AB, PHYDM_AC, PHYDM_AD, PHYDM_BC, PHYDM_BD, PHYDM_CD };
443         u8                      search_space_3[NUM_CHOOSE3_FROM4] = {PHYDM_BCD, PHYDM_ACD,  PHYDM_ABD, PHYDM_ABC};
444
445 #if ((DM_ODM_SUPPORT_TYPE == ODM_WIN) && USB_SWITCH_SUPPORT)
446         p_dm_path_div->is_u3_mode = (p_usb_mode_mech->cur_usb_mode == USB_MODE_U3) ? 1 : 0 ;
447 #else
448         p_dm_path_div->is_u3_mode = 1;
449 #endif
450         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Dynamic TX path Init 8814\n"));
451         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("is_u3_mode = (( %d ))\n", p_dm_path_div->is_u3_mode));
452
453         memcpy(&(p_dm_path_div->search_space_2[0]), &(search_space_2[0]), NUM_CHOOSE2_FROM4);
454         memcpy(&(p_dm_path_div->search_space_3[0]), &(search_space_3[0]), NUM_CHOOSE3_FROM4);
455
456         p_dm_path_div->use_path_a_as_default_ant = 1;
457         p_dm_path_div->phydm_dtp_state = PHYDM_DTP_INIT;
458         p_dm_odm->path_select = PHYDM_AUTO_PATH;
459         p_dm_path_div->phydm_path_div_type = PHYDM_4R_PATH_DIV;
460
461
462         if (p_dm_path_div->is_u3_mode) {
463                 p_dm_path_div->num_tx_path = 3;
464                 phydm_dtp_fix_tx_path(p_dm_odm, PHYDM_BCD);/* 3TX  Set Init TX path*/
465
466         } else {
467                 p_dm_path_div->num_tx_path = 2;
468                 phydm_dtp_fix_tx_path(p_dm_odm, PHYDM_BC);/* 2TX // Set Init TX path*/
469         }
470
471 }
472
473
474 void
475 phydm_process_rssi_for_path_div(
476         void                    *p_dm_void,
477         void                    *p_phy_info_void,
478         void                    *p_pkt_info_void
479 )
480 {
481         struct PHY_DM_STRUCT                    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
482         struct _odm_phy_status_info_            *p_phy_info = (struct _odm_phy_status_info_ *)p_phy_info_void;
483         struct _odm_per_pkt_info_       *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pkt_info_void;
484         struct _ODM_PATH_DIVERSITY_                     *p_dm_path_div  = &(p_dm_odm->dm_path_div);
485
486         if (p_pktinfo->is_packet_to_self || p_pktinfo->is_packet_match_bssid) {
487                 if (p_pktinfo->data_rate > ODM_RATE11M) {
488                         if (p_dm_path_div->phydm_path_div_type == PHYDM_4R_PATH_DIV) {
489 #if RTL8814A_SUPPORT
490                                 if (p_dm_odm->support_ic_type & ODM_RTL8814A) {
491                                         p_dm_path_div->path_a_sum_all += p_phy_info->rx_mimo_signal_strength[0];
492                                         p_dm_path_div->path_a_cnt_all++;
493
494                                         p_dm_path_div->path_b_sum_all += p_phy_info->rx_mimo_signal_strength[1];
495                                         p_dm_path_div->path_b_cnt_all++;
496
497                                         p_dm_path_div->path_c_sum_all += p_phy_info->rx_mimo_signal_strength[2];
498                                         p_dm_path_div->path_c_cnt_all++;
499
500                                         p_dm_path_div->path_d_sum_all += p_phy_info->rx_mimo_signal_strength[3];
501                                         p_dm_path_div->path_d_cnt_all++;
502                                 }
503 #endif
504                         } else {
505                                 p_dm_path_div->path_a_sum[p_pktinfo->station_id] += p_phy_info->rx_mimo_signal_strength[0];
506                                 p_dm_path_div->path_a_cnt[p_pktinfo->station_id]++;
507
508                                 p_dm_path_div->path_b_sum[p_pktinfo->station_id] += p_phy_info->rx_mimo_signal_strength[1];
509                                 p_dm_path_div->path_b_cnt[p_pktinfo->station_id]++;
510                         }
511                 }
512         }
513
514
515 }
516
517 #endif /* #if RTL8814A_SUPPORT */
518
519 void
520 odm_pathdiv_debug(
521         void            *p_dm_void,
522         u32             *const dm_value,
523         u32             *_used,
524         char                    *output,
525         u32             *_out_len
526 )
527 {
528         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
529         struct _ODM_PATH_DIVERSITY_                     *p_dm_path_div  = &(p_dm_odm->dm_path_div);
530         u32 used = *_used;
531         u32 out_len = *_out_len;
532
533         p_dm_odm->path_select = (dm_value[0] & 0xf);
534         PHYDM_SNPRINTF((output + used, out_len - used, "Path_select = (( 0x%x ))\n", p_dm_odm->path_select));
535
536         /* 2 [Fix path] */
537         if (p_dm_odm->path_select != PHYDM_AUTO_PATH) {
538                 PHYDM_SNPRINTF((output + used, out_len - used, "Trun on path  [%s%s%s%s]\n",
539                                 ((p_dm_odm->path_select) & 0x1) ? "A" : "",
540                                 ((p_dm_odm->path_select) & 0x2) ? "B" : "",
541                                 ((p_dm_odm->path_select) & 0x4) ? "C" : "",
542                                 ((p_dm_odm->path_select) & 0x8) ? "D" : ""));
543
544                 phydm_dtp_fix_tx_path(p_dm_odm, p_dm_odm->path_select);
545         } else
546                 PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "Auto path"));
547 }
548
549 #endif /*  #if(defined(CONFIG_PATH_DIVERSITY)) */
550
551 void
552 phydm_c2h_dtp_handler(
553         void    *p_dm_void,
554         u8   *cmd_buf,
555         u8      cmd_len
556 )
557 {
558 #if (defined(CONFIG_PATH_DIVERSITY))
559         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
560         struct _ODM_PATH_DIVERSITY_             *p_dm_path_div  = &(p_dm_odm->dm_path_div);
561
562         u8  macid = cmd_buf[0];
563         u8  target = cmd_buf[1];
564         u8  nsc_1 = cmd_buf[2];
565         u8  nsc_2 = cmd_buf[3];
566         u8  nsc_3 = cmd_buf[4];
567
568         ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Target_candidate = (( %d ))\n", target));
569         /*
570         if( (nsc_1 >= nsc_2) &&  (nsc_1 >= nsc_3))
571         {
572                 phydm_dtp_fix_tx_path(p_dm_odm, p_dm_path_div->ant_candidate_1);
573         }
574         else    if( nsc_2 >= nsc_3)
575         {
576                 phydm_dtp_fix_tx_path(p_dm_odm, p_dm_path_div->ant_candidate_2);
577         }
578         else
579         {
580                 phydm_dtp_fix_tx_path(p_dm_odm, p_dm_path_div->ant_candidate_3);
581         }
582         */
583 #endif
584 }
585
586 void
587 odm_path_diversity(
588         void    *p_dm_void
589 )
590 {
591 #if (defined(CONFIG_PATH_DIVERSITY))
592         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
593         if (!(p_dm_odm->support_ability & ODM_BB_PATH_DIV)) {
594                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Return: Not Support PathDiv\n"));
595                 return;
596         }
597
598 #if RTL8812A_SUPPORT
599
600         if (p_dm_odm->support_ic_type & ODM_RTL8812)
601                 odm_path_diversity_8812a(p_dm_odm);
602         else
603 #endif
604
605 #if RTL8814A_SUPPORT
606                 if (p_dm_odm->support_ic_type & ODM_RTL8814A)
607                         phydm_dynamic_tx_path(p_dm_odm);
608                 else
609 #endif
610                 {}
611 #endif
612 }
613
614 void
615 odm_path_diversity_init(
616         void    *p_dm_void
617 )
618 {
619 #if (defined(CONFIG_PATH_DIVERSITY))
620         struct PHY_DM_STRUCT            *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
621
622         /*p_dm_odm->support_ability |= ODM_BB_PATH_DIV;*/
623
624         if (p_dm_odm->mp_mode == true)
625                 return;
626
627         if (!(p_dm_odm->support_ability & ODM_BB_PATH_DIV)) {
628                 ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Return: Not Support PathDiv\n"));
629                 return;
630         }
631
632 #if RTL8812A_SUPPORT
633         if (p_dm_odm->support_ic_type & ODM_RTL8812)
634                 odm_path_diversity_init_8812a(p_dm_odm);
635         else
636 #endif
637
638 #if RTL8814A_SUPPORT
639                 if (p_dm_odm->support_ic_type & ODM_RTL8814A)
640                         phydm_dynamic_tx_path_init(p_dm_odm);
641                 else
642 #endif
643                 {}
644 #endif
645 }
646
647
648
649 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
650 /*
651  * 2011/12/02 MH Copy from MP oursrc for temporarily test.
652  *   */
653
654 void
655 odm_path_div_chk_ant_switch_callback(
656         struct timer_list               *p_timer
657 )
658 {
659 }
660
661 void
662 odm_path_div_chk_ant_switch_workitem_callback(
663         void            *p_context
664 )
665 {
666 }
667
668 void
669 odm_cck_tx_path_diversity_callback(
670         struct timer_list               *p_timer
671 )
672 {
673 }
674
675 void
676 odm_cck_tx_path_diversity_work_item_callback(
677         void            *p_context
678 )
679 {
680 }
681 u8
682 odm_sw_ant_div_select_scan_chnl(
683         struct _ADAPTER *adapter
684 )
685 {
686         return  0;
687 }
688 void
689 odm_sw_ant_div_construct_scan_chnl(
690         struct _ADAPTER *adapter,
691         u8              scan_chnl
692 )
693 {
694 }
695
696 #endif  /*  #if (DM_ODM_SUPPORT_TYPE == ODM_WIN) */