• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 
26 /*************************************************************
27  * include files
28  ************************************************************/
29 #include "mp_precomp.h"
30 #include "phydm_precomp.h"
31 
32 #ifdef CONFIG_PATH_DIVERSITY
33 #if RTL8814A_SUPPORT
phydm_dtp_fix_tx_path(void * dm_void,u8 path)34 void phydm_dtp_fix_tx_path(
35 	void *dm_void,
36 	u8 path)
37 {
38 	struct dm_struct *dm = (struct dm_struct *)dm_void;
39 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
40 	u8 i, num_enable_path = 0;
41 
42 	if (path == p_div->pre_tx_path)
43 		return;
44 	else
45 		p_div->pre_tx_path = path;
46 
47 	odm_set_bb_reg(dm, R_0x93c, BIT(18) | BIT(19), 3);
48 
49 	for (i = 0; i < 4; i++) {
50 		if (path & BIT(i))
51 			num_enable_path++;
52 	}
53 	PHYDM_DBG(dm, DBG_PATH_DIV, " number of turn-on path : (( %d ))\n",
54 		  num_enable_path);
55 
56 	if (num_enable_path == 1) {
57 		odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
58 
59 		if (path == BB_PATH_A) { /* @1-1 */
60 			PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( A ))\n");
61 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
62 		} else if (path == BB_PATH_B) { /* @1-2 */
63 			PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( B ))\n");
64 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
65 		} else if (path == BB_PATH_C) { /* @1-3 */
66 			PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( C ))\n");
67 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 0);
68 
69 		} else if (path == BB_PATH_D) { /* @1-4 */
70 			PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path (( D ))\n");
71 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 0);
72 		}
73 
74 	} else if (num_enable_path == 2) {
75 		odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
76 		odm_set_bb_reg(dm, R_0x940, 0xf0, path);
77 
78 		if (path == (BB_PATH_AB)) { /* @2-1 */
79 			PHYDM_DBG(dm, DBG_PATH_DIV,
80 				  " Turn on path (( A B ))\n");
81 			/* set for 1ss */
82 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
83 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
84 			/* set for 2ss */
85 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
86 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
87 		} else if (path == BB_PATH_AC) { /* @2-2 */
88 			PHYDM_DBG(dm, DBG_PATH_DIV,
89 				  " Turn on path (( A C ))\n");
90 			/* set for 1ss */
91 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
92 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
93 			/* set for 2ss */
94 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
95 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
96 		} else if (path == BB_PATH_AD) { /* @2-3 */
97 			PHYDM_DBG(dm, DBG_PATH_DIV,
98 				  " Turn on path (( A D ))\n");
99 			/* set for 1ss */
100 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
101 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
102 			/* set for 2ss */
103 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
104 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
105 		} else if (path == BB_PATH_BC) { /* @2-4 */
106 			PHYDM_DBG(dm, DBG_PATH_DIV,
107 				  " Turn on path (( B C ))\n");
108 			/* set for 1ss */
109 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
110 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
111 			/* set for 2ss */
112 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
113 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
114 		} else if (path == BB_PATH_BD) { /* @2-5 */
115 			PHYDM_DBG(dm, DBG_PATH_DIV,
116 				  " Turn on path (( B D ))\n");
117 			/* set for 1ss */
118 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
119 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
120 			/* set for 2ss */
121 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
122 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
123 		} else if (path == BB_PATH_CD) { /* @2-6 */
124 			PHYDM_DBG(dm, DBG_PATH_DIV,
125 				  " Turn on path (( C D ))\n");
126 			/* set for 1ss */
127 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 0);
128 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 1);
129 			/* set for 2ss */
130 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 0);
131 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 1);
132 		}
133 
134 	} else if (num_enable_path == 3) {
135 		odm_set_bb_reg(dm, R_0x93c, 0xf00000, path);
136 		odm_set_bb_reg(dm, R_0x940, 0xf0, path);
137 		odm_set_bb_reg(dm, R_0x940, 0xf0000, path);
138 
139 		if (path == BB_PATH_ABC) { /* @3-1 */
140 			PHYDM_DBG(dm, DBG_PATH_DIV,
141 				  " Turn on path (( A B C))\n");
142 			/* set for 1ss */
143 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
144 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
145 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 2);
146 			/* set for 2ss */
147 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
148 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
149 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 2);
150 			/* set for 3ss */
151 			odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
152 			odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 1);
153 			odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 2);
154 		} else if (path == BB_PATH_ABD) { /* @3-2 */
155 			PHYDM_DBG(dm, DBG_PATH_DIV,
156 				  " Turn on path (( A B D ))\n");
157 			/* set for 1ss */
158 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
159 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 1);
160 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
161 			/* set for 2ss */
162 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
163 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 1);
164 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
165 			/* set for 3ss */
166 			odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
167 			odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 1);
168 			odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
169 
170 		} else if (path == BB_PATH_ACD) { /* @3-3 */
171 			PHYDM_DBG(dm, DBG_PATH_DIV,
172 				  " Turn on path (( A C D ))\n");
173 			/* set for 1ss */
174 			odm_set_bb_reg(dm, R_0x93c, BIT(25) | BIT(24), 0);
175 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
176 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
177 			/* set for 2ss */
178 			odm_set_bb_reg(dm, R_0x940, BIT(9) | BIT(8), 0);
179 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
180 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
181 			/* set for 3ss */
182 			odm_set_bb_reg(dm, R_0x940, BIT(21) | BIT(20), 0);
183 			odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 1);
184 			odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
185 		} else if (path == BB_PATH_BCD) { /* @3-4 */
186 			PHYDM_DBG(dm, DBG_PATH_DIV,
187 				  " Turn on path (( B C D))\n");
188 			/* set for 1ss */
189 			odm_set_bb_reg(dm, R_0x93c, BIT(27) | BIT(26), 0);
190 			odm_set_bb_reg(dm, R_0x93c, BIT(29) | BIT(28), 1);
191 			odm_set_bb_reg(dm, R_0x93c, BIT(31) | BIT(30), 2);
192 			/* set for 2ss */
193 			odm_set_bb_reg(dm, R_0x940, BIT(11) | BIT(10), 0);
194 			odm_set_bb_reg(dm, R_0x940, BIT(13) | BIT(12), 1);
195 			odm_set_bb_reg(dm, R_0x940, BIT(15) | BIT(14), 2);
196 			/* set for 3ss */
197 			odm_set_bb_reg(dm, R_0x940, BIT(23) | BIT(22), 0);
198 			odm_set_bb_reg(dm, R_0x940, BIT(25) | BIT(24), 1);
199 			odm_set_bb_reg(dm, R_0x940, BIT(27) | BIT(26), 2);
200 		}
201 	} else if (num_enable_path == 4)
202 		PHYDM_DBG(dm, DBG_PATH_DIV, " Turn on path ((A  B C D))\n");
203 }
204 
phydm_find_default_path(void * dm_void)205 void phydm_find_default_path(
206 	void *dm_void)
207 {
208 	struct dm_struct *dm = (struct dm_struct *)dm_void;
209 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
210 	u32 rssi_a = 0, rssi_b = 0, rssi_c = 0, rssi_d = 0, rssi_bcd = 0;
211 	u32 rssi_total_a = 0, rssi_total_b = 0;
212 	u32 rssi_total_c = 0, rssi_total_d = 0;
213 
214 	/* @2 Default path Selection By RSSI */
215 
216 	rssi_a = (p_div->path_a_cnt_all > 0) ?
217 		 (p_div->path_a_sum_all / p_div->path_a_cnt_all) : 0;
218 	rssi_b = (p_div->path_b_cnt_all > 0) ?
219 		 (p_div->path_b_sum_all / p_div->path_b_cnt_all) : 0;
220 	rssi_c = (p_div->path_c_cnt_all > 0) ?
221 		 (p_div->path_c_sum_all / p_div->path_c_cnt_all) : 0;
222 	rssi_d = (p_div->path_d_cnt_all > 0) ?
223 		 (p_div->path_d_sum_all / p_div->path_d_cnt_all) : 0;
224 
225 	p_div->path_a_sum_all = 0;
226 	p_div->path_a_cnt_all = 0;
227 	p_div->path_b_sum_all = 0;
228 	p_div->path_b_cnt_all = 0;
229 	p_div->path_c_sum_all = 0;
230 	p_div->path_c_cnt_all = 0;
231 	p_div->path_d_sum_all = 0;
232 	p_div->path_d_cnt_all = 0;
233 
234 	if (p_div->use_path_a_as_default_ant == 1) {
235 		rssi_bcd = (rssi_b + rssi_c + rssi_d) / 3;
236 
237 		if ((rssi_a + ANT_DECT_RSSI_TH) > rssi_bcd) {
238 			p_div->is_path_a_exist = true;
239 			p_div->default_path = PATH_A;
240 		} else {
241 			p_div->is_path_a_exist = false;
242 		}
243 	} else {
244 		if (rssi_a >= rssi_b &&
245 		    rssi_a >= rssi_c &&
246 		    rssi_a >= rssi_d)
247 			p_div->default_path = PATH_A;
248 		else if ((rssi_b >= rssi_c) && (rssi_b >= rssi_d))
249 			p_div->default_path = PATH_B;
250 		else if (rssi_c >= rssi_d)
251 			p_div->default_path = PATH_C;
252 		else
253 			p_div->default_path = PATH_D;
254 	}
255 }
256 
phydm_candidate_dtp_update(void * dm_void)257 void phydm_candidate_dtp_update(
258 	void *dm_void)
259 {
260 	struct dm_struct *dm = (struct dm_struct *)dm_void;
261 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
262 
263 	p_div->num_candidate = 3;
264 
265 	if (p_div->use_path_a_as_default_ant == 1) {
266 		if (p_div->num_tx_path == 3) {
267 			if (p_div->is_path_a_exist) {
268 				p_div->ant_candidate_1 = BB_PATH_ABC;
269 				p_div->ant_candidate_2 = BB_PATH_ABD;
270 				p_div->ant_candidate_3 = BB_PATH_ACD;
271 			} else { /* use path BCD */
272 				p_div->num_candidate = 1;
273 				phydm_dtp_fix_tx_path(dm, BB_PATH_BCD);
274 				return;
275 			}
276 		} else if (p_div->num_tx_path == 2) {
277 			if (p_div->is_path_a_exist) {
278 				p_div->ant_candidate_1 = BB_PATH_AB;
279 				p_div->ant_candidate_2 = BB_PATH_AC;
280 				p_div->ant_candidate_3 = BB_PATH_AD;
281 			} else {
282 				p_div->ant_candidate_1 = BB_PATH_BC;
283 				p_div->ant_candidate_2 = BB_PATH_BD;
284 				p_div->ant_candidate_3 = BB_PATH_CD;
285 			}
286 		}
287 	} else {
288 		/* @2 3 TX mode */
289 		if (p_div->num_tx_path == 3) { /* @choose 3 ant form 4 */
290 			if (p_div->default_path == PATH_A) {
291 			/* @choose 2 ant form 3 */
292 				p_div->ant_candidate_1 = BB_PATH_ABC;
293 				p_div->ant_candidate_2 = BB_PATH_ABD;
294 				p_div->ant_candidate_3 = BB_PATH_ACD;
295 			} else if (p_div->default_path == PATH_B) {
296 				p_div->ant_candidate_1 = BB_PATH_ABC;
297 				p_div->ant_candidate_2 = BB_PATH_ABD;
298 				p_div->ant_candidate_3 = BB_PATH_BCD;
299 			} else if (p_div->default_path == PATH_C) {
300 				p_div->ant_candidate_1 = BB_PATH_ABC;
301 				p_div->ant_candidate_2 = BB_PATH_ACD;
302 				p_div->ant_candidate_3 = BB_PATH_BCD;
303 			} else if (p_div->default_path == PATH_D) {
304 				p_div->ant_candidate_1 = BB_PATH_ABD;
305 				p_div->ant_candidate_2 = BB_PATH_ACD;
306 				p_div->ant_candidate_3 = BB_PATH_BCD;
307 			}
308 		}
309 
310 		/* @2 2 TX mode */
311 		else if (p_div->num_tx_path == 2) { /* @choose 2 ant form 4 */
312 			if (p_div->default_path == PATH_A) {
313 			/* @choose 2 ant form 3 */
314 				p_div->ant_candidate_1 = BB_PATH_AB;
315 				p_div->ant_candidate_2 = BB_PATH_AC;
316 				p_div->ant_candidate_3 = BB_PATH_AD;
317 			} else if (p_div->default_path == PATH_B) {
318 				p_div->ant_candidate_1 = BB_PATH_AB;
319 				p_div->ant_candidate_2 = BB_PATH_BC;
320 				p_div->ant_candidate_3 = BB_PATH_BD;
321 			} else if (p_div->default_path == PATH_C) {
322 				p_div->ant_candidate_1 = BB_PATH_AC;
323 				p_div->ant_candidate_2 = BB_PATH_BC;
324 				p_div->ant_candidate_3 = BB_PATH_CD;
325 			} else if (p_div->default_path == PATH_D) {
326 				p_div->ant_candidate_1 = BB_PATH_AD;
327 				p_div->ant_candidate_2 = BB_PATH_BD;
328 				p_div->ant_candidate_3 = BB_PATH_CD;
329 			}
330 		}
331 	}
332 }
333 
phydm_dynamic_tx_path(void * dm_void)334 void phydm_dynamic_tx_path(
335 	void *dm_void)
336 {
337 	struct dm_struct *dm = (struct dm_struct *)dm_void;
338 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
339 
340 	struct sta_info *entry;
341 	u32 i;
342 	u8 num_client = 0;
343 	u8 h2c_parameter[6] = {0};
344 
345 	if (!dm->is_linked) { /* @is_linked==False */
346 		PHYDM_DBG(dm, DBG_PATH_DIV, "DTP_8814 [No Link!!!]\n");
347 
348 		if (p_div->is_become_linked) {
349 			PHYDM_DBG(dm, DBG_PATH_DIV, "[Be disconnected]---->\n");
350 			p_div->is_become_linked = dm->is_linked;
351 		}
352 		return;
353 	} else {
354 		if (!p_div->is_become_linked) {
355 			PHYDM_DBG(dm, DBG_PATH_DIV, " [Be Linked !!!]----->\n");
356 			p_div->is_become_linked = dm->is_linked;
357 		}
358 	}
359 
360 	/* @2 [period CTRL] */
361 	if (p_div->dtp_period >= 2) {
362 		p_div->dtp_period = 0;
363 	} else {
364 		p_div->dtp_period++;
365 		return;
366 	}
367 
368 	/* @2 [Fix path] */
369 	if (dm->path_select != PHYDM_AUTO_PATH)
370 		return;
371 
372 /* @2 [Check Bfer] */
373 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
374 #ifdef PHYDM_BEAMFORMING_SUPPORT
375 	{
376 		enum beamforming_cap beamform_cap = (dm->beamforming_info.beamform_cap);
377 
378 		if (beamform_cap & BEAMFORMER_CAP) { /* @BFmer On  &&   Div On->Div Off */
379 			if (p_div->fix_path_bfer == 0) {
380 				PHYDM_DBG(dm, DBG_PATH_DIV,
381 					  "[ PathDiv : OFF ]   BFmer ==1\n");
382 				p_div->fix_path_bfer = 1;
383 			}
384 			return;
385 		} else { /* @BFmer Off   &&   Div Off->Div On */
386 			if (p_div->fix_path_bfer == 1) {
387 				PHYDM_DBG(dm, DBG_PATH_DIV,
388 					  "[ PathDiv : ON ]   BFmer ==0\n");
389 				p_div->fix_path_bfer = 0;
390 			}
391 		}
392 	}
393 #endif
394 #endif
395 
396 	if (p_div->use_path_a_as_default_ant == 1) {
397 		phydm_find_default_path(dm);
398 		phydm_candidate_dtp_update(dm);
399 	} else {
400 		if (p_div->phydm_dtp_state == PHYDM_DTP_INIT) {
401 			phydm_find_default_path(dm);
402 			phydm_candidate_dtp_update(dm);
403 			p_div->phydm_dtp_state = PHYDM_DTP_RUNNING_1;
404 		}
405 
406 		else if (p_div->phydm_dtp_state == PHYDM_DTP_RUNNING_1) {
407 			p_div->dtp_check_patha_counter++;
408 
409 			if (p_div->dtp_check_patha_counter >=
410 			    NUM_RESET_DTP_PERIOD) {
411 				p_div->dtp_check_patha_counter = 0;
412 				p_div->phydm_dtp_state = PHYDM_DTP_INIT;
413 			}
414 #if 0
415 			/* @2 Search space update */
416 			else {
417 				/* @1.  find the worst candidate */
418 
419 
420 				/* @2. repalce the worst candidate */
421 			}
422 #endif
423 		}
424 	}
425 
426 	/* @2 Dynamic path Selection H2C */
427 
428 	if (p_div->num_candidate == 1) {
429 		return;
430 	} else {
431 		h2c_parameter[0] = p_div->num_candidate;
432 		h2c_parameter[1] = p_div->num_tx_path;
433 		h2c_parameter[2] = p_div->ant_candidate_1;
434 		h2c_parameter[3] = p_div->ant_candidate_2;
435 		h2c_parameter[4] = p_div->ant_candidate_3;
436 
437 		odm_fill_h2c_cmd(dm, PHYDM_H2C_DYNAMIC_TX_PATH, 6, h2c_parameter);
438 	}
439 }
440 
phydm_dynamic_tx_path_init(void * dm_void)441 void phydm_dynamic_tx_path_init(
442 	void *dm_void)
443 {
444 	struct dm_struct *dm = (struct dm_struct *)dm_void;
445 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
446 	void *adapter = dm->adapter;
447 	u8 search_space_2[NUM_CHOOSE2_FROM4] = {BB_PATH_AB, BB_PATH_AC, BB_PATH_AD, BB_PATH_BC, BB_PATH_BD, BB_PATH_CD};
448 	u8 search_space_3[NUM_CHOOSE3_FROM4] = {BB_PATH_BCD, BB_PATH_ACD, BB_PATH_ABD, BB_PATH_ABC};
449 
450 #if ((DM_ODM_SUPPORT_TYPE == ODM_WIN) && USB_SWITCH_SUPPORT)
451 	p_div->is_u3_mode = (*dm->hub_usb_mode == 2) ? 1 : 0;
452 	PHYDM_DBG(dm, DBG_PATH_DIV, "[WIN USB] is_u3_mode = (( %d ))\n",
453 		  p_div->is_u3_mode);
454 #else
455 	p_div->is_u3_mode = 1;
456 #endif
457 	PHYDM_DBG(dm, DBG_PATH_DIV, "Dynamic TX path Init 8814\n");
458 
459 	memcpy(&p_div->search_space_2[0], &search_space_2[0],
460 	       NUM_CHOOSE2_FROM4);
461 	memcpy(&p_div->search_space_3[0], &search_space_3[0],
462 	       NUM_CHOOSE3_FROM4);
463 
464 	p_div->use_path_a_as_default_ant = 1;
465 	p_div->phydm_dtp_state = PHYDM_DTP_INIT;
466 	dm->path_select = PHYDM_AUTO_PATH;
467 	p_div->phydm_path_div_type = PHYDM_4R_PATH_DIV;
468 
469 	if (p_div->is_u3_mode) {
470 		p_div->num_tx_path = 3;
471 		phydm_dtp_fix_tx_path(dm, BB_PATH_BCD); /* @3TX  Set Init TX path*/
472 
473 	} else {
474 		p_div->num_tx_path = 2;
475 		phydm_dtp_fix_tx_path(dm, BB_PATH_BC); /* @2TX // Set Init TX path*/
476 	}
477 }
478 
phydm_process_rssi_for_path_div_8814a(void * dm_void,void * phy_info_void,void * pkt_info_void)479 void phydm_process_rssi_for_path_div_8814a(void *dm_void, void *phy_info_void,
480 					   void *pkt_info_void)
481 {
482 	struct dm_struct *dm = (struct dm_struct *)dm_void;
483 	struct phydm_phyinfo_struct *phy_info = NULL;
484 	struct phydm_perpkt_info_struct *pktinfo = NULL;
485 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
486 
487 	phy_info = (struct phydm_phyinfo_struct *)phy_info_void;
488 	pktinfo = (struct phydm_perpkt_info_struct *)pkt_info_void;
489 
490 	if (!(pktinfo->is_packet_to_self || pktinfo->is_packet_match_bssid))
491 		return;
492 
493 	if (pktinfo->data_rate <= ODM_RATE11M)
494 		return;
495 
496 	if (p_div->phydm_path_div_type == PHYDM_4R_PATH_DIV) {
497 		p_div->path_a_sum_all += phy_info->rx_mimo_signal_strength[0];
498 		p_div->path_a_cnt_all++;
499 
500 		p_div->path_b_sum_all += phy_info->rx_mimo_signal_strength[1];
501 		p_div->path_b_cnt_all++;
502 
503 		p_div->path_c_sum_all += phy_info->rx_mimo_signal_strength[2];
504 		p_div->path_c_cnt_all++;
505 
506 		p_div->path_d_sum_all += phy_info->rx_mimo_signal_strength[3];
507 		p_div->path_d_cnt_all++;
508 	}
509 }
510 
phydm_pathdiv_debug_8814a(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)511 void phydm_pathdiv_debug_8814a(void *dm_void, char input[][16], u32 *_used,
512 			       char *output, u32 *_out_len)
513 {
514 	struct dm_struct *dm = (struct dm_struct *)dm_void;
515 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
516 	u32 used = *_used;
517 	u32 out_len = *_out_len;
518 	u32 dm_value[10] = {0};
519 	u8 i, input_idx = 0;
520 
521 	for (i = 0; i < 5; i++) {
522 		if (input[i + 1]) {
523 			PHYDM_SSCANF(input[i + 1], DCMD_HEX, &dm_value[i]);
524 			input_idx++;
525 		}
526 	}
527 
528 	if (input_idx == 0)
529 		return;
530 
531 	dm->path_select = (u8)(dm_value[0] & 0xf);
532 	PDM_SNPF(out_len, used, output + used, out_len - used,
533 		 "Path_select = (( 0x%x ))\n", dm->path_select);
534 
535 	/* @2 [Fix path] */
536 	if (dm->path_select != PHYDM_AUTO_PATH) {
537 		PDM_SNPF(out_len, used, output + used, out_len - used,
538 			 "Turn on path  [%s%s%s%s]\n",
539 			 ((dm->path_select) & 0x1) ? "A" : "",
540 			 ((dm->path_select) & 0x2) ? "B" : "",
541 			 ((dm->path_select) & 0x4) ? "C" : "",
542 			 ((dm->path_select) & 0x8) ? "D" : "");
543 
544 		phydm_dtp_fix_tx_path(dm, dm->path_select);
545 	} else {
546 		PDM_SNPF(out_len, used, output + used, out_len - used, "%s\n",
547 			 "Auto path");
548 	}
549 
550 	*_used = used;
551 	*_out_len = out_len;
552 }
553 
554 #endif /* @#if RTL8814A_SUPPORT */
555 
556 #if RTL8812A_SUPPORT
phydm_update_tx_path_8812a(void * dm_void,enum bb_path path)557 void phydm_update_tx_path_8812a(void *dm_void, enum bb_path path)
558 {
559 	struct dm_struct *dm = (struct dm_struct *)dm_void;
560 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
561 
562 	if (p_div->default_tx_path != path) {
563 		PHYDM_DBG(dm, DBG_PATH_DIV, "Need to Update Tx path\n");
564 
565 		if (path == BB_PATH_A) {
566 			/*Tx by Reg*/
567 			odm_set_bb_reg(dm, R_0x80c, 0xFFF0, 0x111);
568 			/*Resp Tx by Txinfo*/
569 			odm_set_bb_reg(dm, R_0x6d8, 0xc0, 1);
570 		} else {
571 			/*Tx by Reg*/
572 			odm_set_bb_reg(dm, R_0x80c, 0xFFF0, 0x222);
573 			 /*Resp Tx by Txinfo*/
574 			odm_set_bb_reg(dm, R_0x6d8, 0xc0, 2);
575 		}
576 	}
577 	p_div->default_tx_path = path;
578 
579 	PHYDM_DBG(dm, DBG_PATH_DIV, "path=%s\n",
580 		  (path == BB_PATH_A) ? "A" : "B");
581 }
582 
phydm_path_diversity_init_8812a(void * dm_void)583 void phydm_path_diversity_init_8812a(void *dm_void)
584 {
585 	struct dm_struct *dm = (struct dm_struct *)dm_void;
586 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
587 	u32 i;
588 
589 	odm_set_bb_reg(dm, R_0x80c, BIT(29), 1); /* Tx path from Reg */
590 	odm_set_bb_reg(dm, R_0x80c, 0xFFF0, 0x111); /* Tx by Reg */
591 	odm_set_bb_reg(dm, R_0x6d8, BIT(7) | BIT6, 1); /* Resp Tx by Txinfo */
592 	phydm_set_tx_path_by_bb_reg(dm, RF_PATH_A);
593 
594 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++)
595 		p_div->path_sel[i] = 1; /* TxInfo default at path-A */
596 }
597 #endif
598 
599 #ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
phydm_set_resp_tx_path_by_fw_jgr3(void * dm_void,u8 macid,enum bb_path path,boolean enable)600 void phydm_set_resp_tx_path_by_fw_jgr3(void *dm_void, u8 macid,
601 				       enum bb_path path, boolean enable)
602 {
603 	struct dm_struct *dm = (struct dm_struct *)dm_void;
604 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
605 	u8 h2c_para[7] = {0};
606 	u8 path_map[4] = {0}; /* tx logic map*/
607 	u8 num_enable_path = 0;
608 	u8 n_tx_path_ctrl_map = 0;
609 	u8 i = 0, n_sts = 0;
610 
611 	/*Response TX is controlled in FW ctrl info*/
612 
613 	PHYDM_DBG(dm, DBG_PATH_DIV, "[%s] =====>\n", __func__);
614 
615 	if (enable) {
616 		n_tx_path_ctrl_map = path;
617 
618 		for (i = 0; i < 4; i++) {
619 			path_map[i] = 0;
620 			if (path & BIT(i))
621 				num_enable_path++;
622 		}
623 
624 		for (i = 0; i < 4; i++) {
625 			if (path & BIT(i)) {
626 				path_map[i] = n_sts;
627 				n_sts++;
628 
629 				if (n_sts == num_enable_path)
630 					break;
631 			}
632 		}
633 	}
634 
635 	PHYDM_DBG(dm, DBG_PATH_DIV, "ctrl_map=0x%x Map[D:A]={%d, %d, %d, %d}\n",
636 		  n_tx_path_ctrl_map,
637 		  path_map[3], path_map[2], path_map[1], path_map[0]);
638 
639 	h2c_para[0] = macid;
640 	h2c_para[1] = n_tx_path_ctrl_map;
641 	h2c_para[2] = (path_map[3] << 6) | (path_map[2] << 4) |
642 		      (path_map[1] << 2) | path_map[0];
643 
644 	odm_fill_h2c_cmd(dm, PHYDM_H2C_DYNAMIC_TX_PATH, 7, h2c_para);
645 }
646 
phydm_get_tx_path_txdesc_jgr3(void * dm_void,u8 macid,struct path_txdesc_ctrl * desc)647 void phydm_get_tx_path_txdesc_jgr3(void *dm_void, u8 macid,
648 				   struct path_txdesc_ctrl *desc)
649 {
650 	struct dm_struct *dm = (struct dm_struct *)dm_void;
651 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
652 	u8 ant_map_a = 0, ant_map_b = 0;
653 	u8 ntx_map = 0;
654 
655 	if (p_div->path_sel[macid] == BB_PATH_A) {
656 		desc->ant_map_a = 0; /*offest24[23:22]*/
657 		desc->ant_map_b = 0; /*offest24[25:24]*/
658 		desc->ntx_map = BB_PATH_A; /*offest28[23:20]*/
659 	} else if (p_div->path_sel[macid] == BB_PATH_B) {
660 		desc->ant_map_a = 0; /*offest24[23:22]*/
661 		desc->ant_map_b = 0; /*offest24[25:24]*/
662 		desc->ntx_map = BB_PATH_B; /*offest28[23:20]*/
663 	} else {
664 		desc->ant_map_a = 0; /*offest24[23:22]*/
665 		desc->ant_map_b = 1; /*offest24[25:24]*/
666 		desc->ntx_map = BB_PATH_AB; /*offest28[23:20]*/
667 	}
668 }
669 #endif
670 
phydm_tx_path_by_mac_or_reg(void * dm_void,enum phydm_path_ctrl ctrl)671 void phydm_tx_path_by_mac_or_reg(void *dm_void, enum phydm_path_ctrl ctrl)
672 {
673 	struct dm_struct *dm = (struct dm_struct *)dm_void;
674 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
675 
676 	PHYDM_DBG(dm, DBG_PATH_DIV, "[%s] ctrl=%s\n",
677 		  __func__, (ctrl == TX_PATH_BY_REG) ? "REG" : "DESC");
678 
679 	if (ctrl == p_div->tx_path_ctrl)
680 		return;
681 
682 	p_div->tx_path_ctrl = ctrl;
683 
684 	switch (dm->support_ic_type) {
685 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
686 	case ODM_RTL8822B:
687 	case ODM_RTL8822C:
688 	case ODM_RTL8812F:
689 	case ODM_RTL8197G:
690 		if (ctrl == TX_PATH_BY_REG) {
691 			odm_set_bb_reg(dm, R_0x1e24, BIT(16), 0); /*OFDM*/
692 			odm_set_bb_reg(dm, R_0x1a84, 0xe0, 0); /*CCK*/
693 		} else {
694 			odm_set_bb_reg(dm, R_0x1e24, BIT(16), 1); /*OFDM*/
695 			odm_set_bb_reg(dm, R_0x1a84, 0xe0, 7); /*CCK*/
696 		}
697 
698 		break;
699 	#endif
700 	#if 0 /*(RTL8822B_SUPPORT)*/ /*@ HW Bug*/
701 	case ODM_RTL8822B:
702 		if (ctrl == TX_PATH_BY_REG) {
703 			odm_set_bb_reg(dm, R_0x93c, BIT(18), 0);
704 			odm_set_bb_reg(dm, R_0xa84, 0xe0, 0); /*CCK*/
705 		} else {
706 			odm_set_bb_reg(dm, R_0x93c, BIT(18), 1);
707 			odm_set_bb_reg(dm, R_0xa84, 0xe0, 7); /*CCK*/
708 		}
709 
710 		break;
711 	#endif
712 	default:
713 		break;
714 	}
715 }
716 
phydm_fix_1ss_tx_path_by_bb_reg(void * dm_void,enum bb_path tx_path_sel_1ss,enum bb_path tx_path_sel_cck)717 void phydm_fix_1ss_tx_path_by_bb_reg(void *dm_void,
718 				     enum bb_path tx_path_sel_1ss,
719 				     enum bb_path tx_path_sel_cck)
720 {
721 	struct dm_struct *dm = (struct dm_struct *)dm_void;
722 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
723 
724 	if (tx_path_sel_1ss != BB_PATH_AUTO) {
725 		p_div->ofdm_fix_path_en = true;
726 		p_div->ofdm_fix_path_sel = tx_path_sel_1ss;
727 	} else {
728 		p_div->ofdm_fix_path_en = false;
729 		p_div->ofdm_fix_path_sel = dm->tx_1ss_status;
730 	}
731 
732 	if (tx_path_sel_cck != BB_PATH_AUTO) {
733 		p_div->cck_fix_path_en = true;
734 		p_div->cck_fix_path_sel = tx_path_sel_cck;
735 	} else {
736 		p_div->cck_fix_path_en = false;
737 		p_div->cck_fix_path_sel = dm->tx_1ss_status;
738 	}
739 
740 	p_div->force_update = true;
741 
742 	PHYDM_DBG(dm, DBG_PATH_DIV,
743 		  "{OFDM_fix_en=%d, path=%d} {CCK_fix_en=%d, path=%d}\n",
744 		  p_div->ofdm_fix_path_en, p_div->ofdm_fix_path_sel,
745 		  p_div->cck_fix_path_en, p_div->cck_fix_path_sel);
746 }
747 
phydm_set_tx_path_by_bb_reg(void * dm_void,enum bb_path tx_path_sel_1ss)748 void phydm_set_tx_path_by_bb_reg(void *dm_void, enum bb_path tx_path_sel_1ss)
749 {
750 	struct dm_struct *dm = (struct dm_struct *)dm_void;
751 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
752 	enum bb_path tx_path_sel_cck = tx_path_sel_1ss;
753 
754 	if (!p_div->force_update) {
755 		if (tx_path_sel_1ss == p_div->default_tx_path) {
756 			PHYDM_DBG(dm, DBG_PATH_DIV, "Stay in TX path=%s\n",
757 				  (tx_path_sel_1ss == BB_PATH_A) ? "A" : "B");
758 			return;
759 		}
760 	}
761 	p_div->force_update = false;
762 
763 	p_div->default_tx_path = tx_path_sel_1ss;
764 
765 	PHYDM_DBG(dm, DBG_PATH_DIV, "Switch TX path=%s\n",
766 		  (tx_path_sel_1ss == BB_PATH_A) ? "A" : "B");
767 
768 	/*Adv-ctrl mode*/
769 	if (p_div->cck_fix_path_en) {
770 		PHYDM_DBG(dm, DBG_PATH_DIV, "Fix CCK TX path=%d\n",
771 			  p_div->cck_fix_path_sel);
772 		tx_path_sel_cck = p_div->cck_fix_path_sel;
773 	}
774 
775 	if (p_div->ofdm_fix_path_en) {
776 		PHYDM_DBG(dm, DBG_PATH_DIV, "Fix OFDM TX path=%d\n",
777 			  p_div->ofdm_fix_path_sel);
778 		tx_path_sel_1ss = p_div->ofdm_fix_path_sel;
779 	}
780 
781 	switch (dm->support_ic_type) {
782 	#if RTL8822C_SUPPORT
783 	case ODM_RTL8822C:
784 		phydm_config_tx_path_8822c(dm, dm->tx_2ss_status,
785 					   tx_path_sel_1ss, tx_path_sel_cck);
786 		break;
787 	#endif
788 
789 	#if RTL8822B_SUPPORT
790 	case ODM_RTL8822B:
791 		if (dm->tx_ant_status != BB_PATH_AB)
792 			return;
793 
794 		phydm_config_tx_path_8822b(dm, BB_PATH_AB,
795 					   tx_path_sel_1ss, tx_path_sel_cck);
796 		break;
797 	#endif
798 
799 	#if RTL8192F_SUPPORT
800 	case ODM_RTL8192F:
801 		if (dm->tx_ant_status != BB_PATH_AB)
802 			return;
803 
804 		phydm_config_tx_path_8192f(dm, BB_PATH_AB,
805 					   tx_path_sel_1ss, tx_path_sel_cck);
806 		break;
807 	#endif
808 
809 	#if RTL8812A_SUPPORT
810 	case ODM_RTL8812:
811 		phydm_update_tx_path_8812a(dm, tx_path_sel_1ss);
812 		break;
813 	#endif
814 	default:
815 		break;
816 	}
817 }
818 
phydm_tx_path_diversity_2ss(void * dm_void)819 void phydm_tx_path_diversity_2ss(void *dm_void)
820 {
821 	struct dm_struct *dm = (struct dm_struct *)dm_void;
822 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
823 	struct cmn_sta_info *sta;
824 	enum bb_path default_tx_path = BB_PATH_A, path = BB_PATH_A;
825 	u32 rssi_a = 0, rssi_b = 0;
826 	u32 local_max_rssi, glb_min_rssi = 0xff;
827 	u8 i = 0;
828 
829 	PHYDM_DBG(dm, DBG_PATH_DIV, "[%s] =======>\n", __func__);
830 
831 	if (!dm->is_linked) {
832 		if (dm->first_disconnect)
833 			phydm_tx_path_by_mac_or_reg(dm, TX_PATH_BY_REG);
834 
835 		PHYDM_DBG(dm, DBG_PATH_DIV, "No Link\n");
836 		return;
837 	}
838 
839 	#if 0/*def PHYDM_IC_JGR3_SERIES_SUPPORT*/
840 	if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
841 		if (dm->is_one_entry_only || p_div->cck_fix_path_en ||
842 		    p_div->ofdm_fix_path_en)
843 			phydm_tx_path_by_mac_or_reg(dm, TX_PATH_BY_REG);
844 		else
845 			phydm_tx_path_by_mac_or_reg(dm, TX_PATH_BY_DESC);
846 	}
847 	#endif
848 
849 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
850 		sta = dm->phydm_sta_info[i];
851 		if (!is_sta_active(sta))
852 			continue;
853 
854 		/* 2 Caculate RSSI per path */
855 		rssi_a = PHYDM_DIV(p_div->path_a_sum[i], p_div->path_a_cnt[i]);
856 		rssi_b = PHYDM_DIV(p_div->path_b_sum[i], p_div->path_b_cnt[i]);
857 
858 		if (rssi_a == rssi_b)
859 			path =  p_div->default_tx_path;
860 		else
861 			path = (rssi_a > rssi_b) ? BB_PATH_A : BB_PATH_B;
862 
863 		local_max_rssi = (rssi_a > rssi_b) ? rssi_a : rssi_b;
864 
865 		PHYDM_DBG(dm, DBG_PATH_DIV,
866 			  "[%d]PathA sum=%d, cnt=%d, avg_rssi=%d\n",
867 			  i, p_div->path_a_sum[i],
868 			  p_div->path_a_cnt[i], rssi_a);
869 		PHYDM_DBG(dm, DBG_PATH_DIV,
870 			  "[%d]PathB sum=%d, cnt=%d, avg_rssi=%d\n",
871 			  i, p_div->path_b_sum[i],
872 			  p_div->path_b_cnt[i], rssi_b);
873 
874 		/*Select default Tx path */
875 		if (local_max_rssi < glb_min_rssi) {
876 			glb_min_rssi = local_max_rssi;
877 			default_tx_path = path;
878 		}
879 
880 		if (p_div->path_sel[i] != path) {
881 			p_div->path_sel[i] = path;
882 			#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
883 			if (dm->support_ic_type & ODM_IC_JGR3_SERIES)
884 				phydm_set_resp_tx_path_by_fw_jgr3(dm, i,
885 								  path, true);
886 			#endif
887 		}
888 
889 		p_div->path_a_cnt[i] = 0;
890 		p_div->path_a_sum[i] = 0;
891 		p_div->path_b_cnt[i] = 0;
892 		p_div->path_b_sum[i] = 0;
893 	}
894 
895 	/* 2 Update default Tx path */
896 	phydm_set_tx_path_by_bb_reg(dm, default_tx_path);
897 	PHYDM_DBG(dm, DBG_PATH_DIV, "[%s] end\n\n", __func__);
898 }
899 
phydm_tx_path_diversity(void * dm_void)900 void phydm_tx_path_diversity(void *dm_void)
901 {
902 	struct dm_struct *dm = (struct dm_struct *)dm_void;
903 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
904 
905 	p_div->path_div_in_progress = false;
906 
907 	if (!(dm->support_ability & ODM_BB_PATH_DIV))
908 		return;
909 
910 	if (p_div->stop_path_div) {
911 		PHYDM_DBG(dm, DBG_PATH_DIV,
912 			  "stop_path_div=1, tx_1ss_status=%d\n",
913 			  dm->tx_1ss_status);
914 		return;
915 	}
916 
917 	switch (dm->support_ic_type) {
918 	#ifdef PHYDM_CONFIG_PATH_DIV_V2
919 	case ODM_RTL8822B:
920 	case ODM_RTL8822C:
921 	case ODM_RTL8192F:
922 	case ODM_RTL8812F:
923 	case ODM_RTL8197G:
924 		if (dm->rx_ant_status != BB_PATH_AB) {
925 			PHYDM_DBG(dm, DBG_PATH_DIV,
926 				  "[Return] tx_Path_en=%d, rx_Path_en=%d\n",
927 				  dm->tx_ant_status, dm->rx_ant_status);
928 			return;
929 		}
930 
931 		p_div->path_div_in_progress = true;
932 		phydm_tx_path_diversity_2ss(dm);
933 		break;
934 	#endif
935 
936 	#if (RTL8812A_SUPPORT)
937 	case ODM_RTL8812:
938 		phydm_tx_path_diversity_2ss(dm);
939 		break;
940 	#endif
941 
942 	#if RTL8814A_SUPPORT
943 	case ODM_RTL8814A:
944 		phydm_dynamic_tx_path(dm);
945 		break;
946 	#endif
947 	}
948 }
949 
phydm_tx_path_diversity_init_v2(void * dm_void)950 void phydm_tx_path_diversity_init_v2(void *dm_void)
951 {
952 	struct dm_struct *dm = (struct dm_struct *)dm_void;
953 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
954 	u32 i = 0;
955 
956 	PHYDM_DBG(dm, DBG_PATH_DIV, "[%s] ====>\n", __func__);
957 
958 	/*BB_PATH_AB is a invalid value used for init state*/
959 	p_div->default_tx_path = BB_PATH_A;
960 	p_div->tx_path_ctrl = TX_PATH_CTRL_INIT;
961 	p_div->path_div_in_progress = false;
962 
963 	p_div->cck_fix_path_en = false;
964 	p_div->ofdm_fix_path_en = false;
965 	p_div->force_update = false;
966 
967 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++)
968 		p_div->path_sel[i] = BB_PATH_A; /* TxInfo default at path-A */
969 
970 	phydm_tx_path_by_mac_or_reg(dm, TX_PATH_BY_REG);
971 }
972 
phydm_tx_path_diversity_init(void * dm_void)973 void phydm_tx_path_diversity_init(void *dm_void)
974 {
975 	struct dm_struct *dm = (struct dm_struct *)dm_void;
976 
977 	if (!(dm->support_ability & ODM_BB_PATH_DIV))
978 		return;
979 
980 	switch (dm->support_ic_type) {
981 	#ifdef PHYDM_CONFIG_PATH_DIV_V2
982 	case ODM_RTL8822C:
983 	case ODM_RTL8822B:
984 	case ODM_RTL8192F:
985 	case ODM_RTL8812F:
986 	case ODM_RTL8197G:
987 	phydm_tx_path_diversity_init_v2(dm); /*@ After 8822B*/
988 	break;
989 	#endif
990 
991 	#if RTL8812A_SUPPORT
992 	case ODM_RTL8812:
993 	phydm_path_diversity_init_8812a(dm);
994 	break;
995 	#endif
996 
997 	#if RTL8814A_SUPPORT
998 	case ODM_RTL8814A:
999 	phydm_dynamic_tx_path_init(dm);
1000 	break;
1001 	#endif
1002 	}
1003 }
1004 
phydm_process_rssi_for_path_div(void * dm_void,void * phy_info_void,void * pkt_info_void)1005 void phydm_process_rssi_for_path_div(void *dm_void, void *phy_info_void,
1006 				     void *pkt_info_void)
1007 {
1008 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1009 	struct phydm_phyinfo_struct *phy_info = NULL;
1010 	struct phydm_perpkt_info_struct *pktinfo = NULL;
1011 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
1012 	u8 id = 0;
1013 
1014 	phy_info = (struct phydm_phyinfo_struct *)phy_info_void;
1015 	pktinfo = (struct phydm_perpkt_info_struct *)pkt_info_void;
1016 
1017 	if (!(pktinfo->is_packet_to_self || pktinfo->is_packet_match_bssid))
1018 		return;
1019 
1020 	if (pktinfo->is_cck_rate)
1021 		return;
1022 
1023 	id = pktinfo->station_id;
1024 	p_div->path_a_sum[id] += phy_info->rx_mimo_signal_strength[0];
1025 	p_div->path_a_cnt[id]++;
1026 
1027 	p_div->path_b_sum[id] += phy_info->rx_mimo_signal_strength[1];
1028 	p_div->path_b_cnt[id]++;
1029 }
1030 
phydm_pathdiv_debug(void * dm_void,char input[][16],u32 * _used,char * output,u32 * _out_len)1031 void phydm_pathdiv_debug(void *dm_void, char input[][16], u32 *_used,
1032 			 char *output, u32 *_out_len)
1033 {
1034 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1035 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
1036 	char help[] = "-h";
1037 	u32 used = *_used;
1038 	u32 out_len = *_out_len;
1039 	u32 val[10] = {0};
1040 	u8 i, input_idx = 0;
1041 
1042 	for (i = 0; i < 5; i++) {
1043 		PHYDM_SSCANF(input[i + 1], DCMD_HEX, &val[i]);
1044 		input_idx++;
1045 	}
1046 
1047 	if (input_idx == 0)
1048 		return;
1049 
1050 	PHYDM_SSCANF(input[1], DCMD_HEX, &val[0]);
1051 	PHYDM_SSCANF(input[2], DCMD_HEX, &val[1]);
1052 
1053 	if ((strcmp(input[1], help) == 0)) {
1054 		PDM_SNPF(out_len, used, output + used, out_len - used,
1055 			 "{1:TX Ctrl Sig} {0:BB, 1:MAC}\n");
1056 		PDM_SNPF(out_len, used, output + used, out_len - used,
1057 			 "{2:BB Default TX REG} {path}\n");
1058 		PDM_SNPF(out_len, used, output + used, out_len - used,
1059 			 "{3:MAC DESC TX} {path} {macid}\n");
1060 		#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1061 		PDM_SNPF(out_len, used, output + used, out_len - used,
1062 			 "{4:MAC Resp TX} {path} {macid}\n");
1063 		#endif
1064 		PDM_SNPF(out_len, used, output + used, out_len - used,
1065 			 "{5:Fix 1ss path} {ofdm path} {cck path}\n");
1066 	} else if (val[0] == 1) {
1067 		phydm_tx_path_by_mac_or_reg(dm, (enum phydm_path_ctrl)val[1]);
1068 	} else if (val[0] == 2) {
1069 		phydm_set_tx_path_by_bb_reg(dm, (enum bb_path)val[1]);
1070 	} else if (val[0] == 3) {
1071 		p_div->path_sel[val[2]] = (enum bb_path)val[1];
1072 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
1073 	} else if (val[0] == 4) {
1074 		phydm_set_resp_tx_path_by_fw_jgr3(dm, (u8)val[2],
1075 						  (enum bb_path)val[1], true);
1076 	#endif
1077 	} else if (val[0] == 5) {
1078 		phydm_fix_1ss_tx_path_by_bb_reg(dm, (enum bb_path)val[1],
1079 						(enum bb_path)val[2]);
1080 	}
1081 	*_used = used;
1082 	*_out_len = out_len;
1083 }
1084 
phydm_c2h_dtp_handler(void * dm_void,u8 * cmd_buf,u8 cmd_len)1085 void phydm_c2h_dtp_handler(void *dm_void, u8 *cmd_buf, u8 cmd_len)
1086 {
1087 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1088 	struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div;
1089 
1090 	u8 macid = cmd_buf[0];
1091 	u8 target = cmd_buf[1];
1092 	u8 nsc_1 = cmd_buf[2];
1093 	u8 nsc_2 = cmd_buf[3];
1094 	u8 nsc_3 = cmd_buf[4];
1095 
1096 	PHYDM_DBG(dm, DBG_PATH_DIV, "Target_candidate = (( %d ))\n", target);
1097 /*@
1098 	if( (nsc_1 >= nsc_2) &&  (nsc_1 >= nsc_3))
1099 	{
1100 		phydm_dtp_fix_tx_path(dm, p_div->ant_candidate_1);
1101 	}
1102 	else	if( nsc_2 >= nsc_3)
1103 	{
1104 		phydm_dtp_fix_tx_path(dm, p_div->ant_candidate_2);
1105 	}
1106 	else
1107 	{
1108 		phydm_dtp_fix_tx_path(dm, p_div->ant_candidate_3);
1109 	}
1110 	*/
1111 }
1112 
1113 #endif /*  @#ifdef CONFIG_PATH_DIVERSITY */
1114