2 * Copyright (c) 2012 Qualcomm Atheros, Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 static inline bool ath_is_alt_ant_ratio_better(int alt_ratio
, int maxdelta
,
20 int mindelta
, int main_rssi_avg
,
21 int alt_rssi_avg
, int pkt_count
)
23 return (((alt_ratio
>= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2
) &&
24 (alt_rssi_avg
> main_rssi_avg
+ maxdelta
)) ||
25 (alt_rssi_avg
> main_rssi_avg
+ mindelta
)) && (pkt_count
> 50);
28 static inline bool ath_ant_div_comb_alt_check(u8 div_group
, int alt_ratio
,
29 int curr_main_set
, int curr_alt_set
,
30 int alt_rssi_avg
, int main_rssi_avg
)
35 if (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)
40 if ((((curr_main_set
== ATH_ANT_DIV_COMB_LNA2
) &&
41 (curr_alt_set
== ATH_ANT_DIV_COMB_LNA1
) &&
42 (alt_rssi_avg
>= (main_rssi_avg
- 5))) ||
43 ((curr_main_set
== ATH_ANT_DIV_COMB_LNA1
) &&
44 (curr_alt_set
== ATH_ANT_DIV_COMB_LNA2
) &&
45 (alt_rssi_avg
>= (main_rssi_avg
- 2)))) &&
56 static void ath_lnaconf_alt_good_scan(struct ath_ant_comb
*antcomb
,
57 struct ath_hw_antcomb_conf ant_conf
,
60 antcomb
->quick_scan_cnt
= 0;
62 if (ant_conf
.main_lna_conf
== ATH_ANT_DIV_COMB_LNA2
)
63 antcomb
->rssi_lna2
= main_rssi_avg
;
64 else if (ant_conf
.main_lna_conf
== ATH_ANT_DIV_COMB_LNA1
)
65 antcomb
->rssi_lna1
= main_rssi_avg
;
67 switch ((ant_conf
.main_lna_conf
<< 4) | ant_conf
.alt_lna_conf
) {
68 case 0x10: /* LNA2 A-B */
69 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
70 antcomb
->first_quick_scan_conf
=
71 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
72 antcomb
->second_quick_scan_conf
= ATH_ANT_DIV_COMB_LNA1
;
74 case 0x20: /* LNA1 A-B */
75 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
76 antcomb
->first_quick_scan_conf
=
77 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
78 antcomb
->second_quick_scan_conf
= ATH_ANT_DIV_COMB_LNA2
;
80 case 0x21: /* LNA1 LNA2 */
81 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA2
;
82 antcomb
->first_quick_scan_conf
=
83 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
84 antcomb
->second_quick_scan_conf
=
85 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
87 case 0x12: /* LNA2 LNA1 */
88 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA1
;
89 antcomb
->first_quick_scan_conf
=
90 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
91 antcomb
->second_quick_scan_conf
=
92 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
94 case 0x13: /* LNA2 A+B */
95 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
96 antcomb
->first_quick_scan_conf
=
97 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
98 antcomb
->second_quick_scan_conf
= ATH_ANT_DIV_COMB_LNA1
;
100 case 0x23: /* LNA1 A+B */
101 antcomb
->main_conf
= ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
102 antcomb
->first_quick_scan_conf
=
103 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
104 antcomb
->second_quick_scan_conf
= ATH_ANT_DIV_COMB_LNA2
;
111 static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb
*antcomb
,
112 struct ath_hw_antcomb_conf
*div_ant_conf
,
113 int main_rssi_avg
, int alt_rssi_avg
,
117 switch (antcomb
->quick_scan_cnt
) {
119 /* set alt to main, and alt to first conf */
120 div_ant_conf
->main_lna_conf
= antcomb
->main_conf
;
121 div_ant_conf
->alt_lna_conf
= antcomb
->first_quick_scan_conf
;
124 /* set alt to main, and alt to first conf */
125 div_ant_conf
->main_lna_conf
= antcomb
->main_conf
;
126 div_ant_conf
->alt_lna_conf
= antcomb
->second_quick_scan_conf
;
127 antcomb
->rssi_first
= main_rssi_avg
;
128 antcomb
->rssi_second
= alt_rssi_avg
;
130 if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA1
) {
132 if (ath_is_alt_ant_ratio_better(alt_ratio
,
133 ATH_ANT_DIV_COMB_LNA1_DELTA_HI
,
134 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW
,
135 main_rssi_avg
, alt_rssi_avg
,
136 antcomb
->total_pkt_count
))
137 antcomb
->first_ratio
= true;
139 antcomb
->first_ratio
= false;
140 } else if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA2
) {
141 if (ath_is_alt_ant_ratio_better(alt_ratio
,
142 ATH_ANT_DIV_COMB_LNA1_DELTA_MID
,
143 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW
,
144 main_rssi_avg
, alt_rssi_avg
,
145 antcomb
->total_pkt_count
))
146 antcomb
->first_ratio
= true;
148 antcomb
->first_ratio
= false;
150 if ((((alt_ratio
>= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2
) &&
151 (alt_rssi_avg
> main_rssi_avg
+
152 ATH_ANT_DIV_COMB_LNA1_DELTA_HI
)) ||
153 (alt_rssi_avg
> main_rssi_avg
)) &&
154 (antcomb
->total_pkt_count
> 50))
155 antcomb
->first_ratio
= true;
157 antcomb
->first_ratio
= false;
161 antcomb
->alt_good
= false;
162 antcomb
->scan_not_start
= false;
163 antcomb
->scan
= false;
164 antcomb
->rssi_first
= main_rssi_avg
;
165 antcomb
->rssi_third
= alt_rssi_avg
;
167 if (antcomb
->second_quick_scan_conf
== ATH_ANT_DIV_COMB_LNA1
)
168 antcomb
->rssi_lna1
= alt_rssi_avg
;
169 else if (antcomb
->second_quick_scan_conf
==
170 ATH_ANT_DIV_COMB_LNA2
)
171 antcomb
->rssi_lna2
= alt_rssi_avg
;
172 else if (antcomb
->second_quick_scan_conf
==
173 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
) {
174 if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA2
)
175 antcomb
->rssi_lna2
= main_rssi_avg
;
176 else if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA1
)
177 antcomb
->rssi_lna1
= main_rssi_avg
;
180 if (antcomb
->rssi_lna2
> antcomb
->rssi_lna1
+
181 ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA
)
182 div_ant_conf
->main_lna_conf
= ATH_ANT_DIV_COMB_LNA2
;
184 div_ant_conf
->main_lna_conf
= ATH_ANT_DIV_COMB_LNA1
;
186 if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA1
) {
187 if (ath_is_alt_ant_ratio_better(alt_ratio
,
188 ATH_ANT_DIV_COMB_LNA1_DELTA_HI
,
189 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW
,
190 main_rssi_avg
, alt_rssi_avg
,
191 antcomb
->total_pkt_count
))
192 antcomb
->second_ratio
= true;
194 antcomb
->second_ratio
= false;
195 } else if (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA2
) {
196 if (ath_is_alt_ant_ratio_better(alt_ratio
,
197 ATH_ANT_DIV_COMB_LNA1_DELTA_MID
,
198 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW
,
199 main_rssi_avg
, alt_rssi_avg
,
200 antcomb
->total_pkt_count
))
201 antcomb
->second_ratio
= true;
203 antcomb
->second_ratio
= false;
205 if ((((alt_ratio
>= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2
) &&
206 (alt_rssi_avg
> main_rssi_avg
+
207 ATH_ANT_DIV_COMB_LNA1_DELTA_HI
)) ||
208 (alt_rssi_avg
> main_rssi_avg
)) &&
209 (antcomb
->total_pkt_count
> 50))
210 antcomb
->second_ratio
= true;
212 antcomb
->second_ratio
= false;
215 /* set alt to the conf with maximun ratio */
216 if (antcomb
->first_ratio
&& antcomb
->second_ratio
) {
217 if (antcomb
->rssi_second
> antcomb
->rssi_third
) {
219 if ((antcomb
->first_quick_scan_conf
==
220 ATH_ANT_DIV_COMB_LNA1
) ||
221 (antcomb
->first_quick_scan_conf
==
222 ATH_ANT_DIV_COMB_LNA2
))
223 /* Set alt LNA1 or LNA2*/
224 if (div_ant_conf
->main_lna_conf
==
225 ATH_ANT_DIV_COMB_LNA2
)
226 div_ant_conf
->alt_lna_conf
=
227 ATH_ANT_DIV_COMB_LNA1
;
229 div_ant_conf
->alt_lna_conf
=
230 ATH_ANT_DIV_COMB_LNA2
;
232 /* Set alt to A+B or A-B */
233 div_ant_conf
->alt_lna_conf
=
234 antcomb
->first_quick_scan_conf
;
235 } else if ((antcomb
->second_quick_scan_conf
==
236 ATH_ANT_DIV_COMB_LNA1
) ||
237 (antcomb
->second_quick_scan_conf
==
238 ATH_ANT_DIV_COMB_LNA2
)) {
239 /* Set alt LNA1 or LNA2 */
240 if (div_ant_conf
->main_lna_conf
==
241 ATH_ANT_DIV_COMB_LNA2
)
242 div_ant_conf
->alt_lna_conf
=
243 ATH_ANT_DIV_COMB_LNA1
;
245 div_ant_conf
->alt_lna_conf
=
246 ATH_ANT_DIV_COMB_LNA2
;
248 /* Set alt to A+B or A-B */
249 div_ant_conf
->alt_lna_conf
=
250 antcomb
->second_quick_scan_conf
;
252 } else if (antcomb
->first_ratio
) {
254 if ((antcomb
->first_quick_scan_conf
==
255 ATH_ANT_DIV_COMB_LNA1
) ||
256 (antcomb
->first_quick_scan_conf
==
257 ATH_ANT_DIV_COMB_LNA2
))
258 /* Set alt LNA1 or LNA2 */
259 if (div_ant_conf
->main_lna_conf
==
260 ATH_ANT_DIV_COMB_LNA2
)
261 div_ant_conf
->alt_lna_conf
=
262 ATH_ANT_DIV_COMB_LNA1
;
264 div_ant_conf
->alt_lna_conf
=
265 ATH_ANT_DIV_COMB_LNA2
;
267 /* Set alt to A+B or A-B */
268 div_ant_conf
->alt_lna_conf
=
269 antcomb
->first_quick_scan_conf
;
270 } else if (antcomb
->second_ratio
) {
272 if ((antcomb
->second_quick_scan_conf
==
273 ATH_ANT_DIV_COMB_LNA1
) ||
274 (antcomb
->second_quick_scan_conf
==
275 ATH_ANT_DIV_COMB_LNA2
))
276 /* Set alt LNA1 or LNA2 */
277 if (div_ant_conf
->main_lna_conf
==
278 ATH_ANT_DIV_COMB_LNA2
)
279 div_ant_conf
->alt_lna_conf
=
280 ATH_ANT_DIV_COMB_LNA1
;
282 div_ant_conf
->alt_lna_conf
=
283 ATH_ANT_DIV_COMB_LNA2
;
285 /* Set alt to A+B or A-B */
286 div_ant_conf
->alt_lna_conf
=
287 antcomb
->second_quick_scan_conf
;
289 /* main is largest */
290 if ((antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA1
) ||
291 (antcomb
->main_conf
== ATH_ANT_DIV_COMB_LNA2
))
292 /* Set alt LNA1 or LNA2 */
293 if (div_ant_conf
->main_lna_conf
==
294 ATH_ANT_DIV_COMB_LNA2
)
295 div_ant_conf
->alt_lna_conf
=
296 ATH_ANT_DIV_COMB_LNA1
;
298 div_ant_conf
->alt_lna_conf
=
299 ATH_ANT_DIV_COMB_LNA2
;
301 /* Set alt to A+B or A-B */
302 div_ant_conf
->alt_lna_conf
= antcomb
->main_conf
;
310 static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf
*ant_conf
,
311 struct ath_ant_comb
*antcomb
,
314 ant_conf
->main_gaintb
= 0;
315 ant_conf
->alt_gaintb
= 0;
317 if (ant_conf
->div_group
== 0) {
318 /* Adjust the fast_div_bias based on main and alt lna conf */
319 switch ((ant_conf
->main_lna_conf
<< 4) |
320 ant_conf
->alt_lna_conf
) {
321 case 0x01: /* A-B LNA2 */
322 ant_conf
->fast_div_bias
= 0x3b;
324 case 0x02: /* A-B LNA1 */
325 ant_conf
->fast_div_bias
= 0x3d;
327 case 0x03: /* A-B A+B */
328 ant_conf
->fast_div_bias
= 0x1;
330 case 0x10: /* LNA2 A-B */
331 ant_conf
->fast_div_bias
= 0x7;
333 case 0x12: /* LNA2 LNA1 */
334 ant_conf
->fast_div_bias
= 0x2;
336 case 0x13: /* LNA2 A+B */
337 ant_conf
->fast_div_bias
= 0x7;
339 case 0x20: /* LNA1 A-B */
340 ant_conf
->fast_div_bias
= 0x6;
342 case 0x21: /* LNA1 LNA2 */
343 ant_conf
->fast_div_bias
= 0x0;
345 case 0x23: /* LNA1 A+B */
346 ant_conf
->fast_div_bias
= 0x6;
348 case 0x30: /* A+B A-B */
349 ant_conf
->fast_div_bias
= 0x1;
351 case 0x31: /* A+B LNA2 */
352 ant_conf
->fast_div_bias
= 0x3b;
354 case 0x32: /* A+B LNA1 */
355 ant_conf
->fast_div_bias
= 0x3d;
360 } else if (ant_conf
->div_group
== 1) {
361 /* Adjust the fast_div_bias based on main and alt_lna_conf */
362 switch ((ant_conf
->main_lna_conf
<< 4) |
363 ant_conf
->alt_lna_conf
) {
364 case 0x01: /* A-B LNA2 */
365 ant_conf
->fast_div_bias
= 0x1;
367 case 0x02: /* A-B LNA1 */
368 ant_conf
->fast_div_bias
= 0x1;
370 case 0x03: /* A-B A+B */
371 ant_conf
->fast_div_bias
= 0x1;
373 case 0x10: /* LNA2 A-B */
374 if (!(antcomb
->scan
) &&
375 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
376 ant_conf
->fast_div_bias
= 0x3f;
378 ant_conf
->fast_div_bias
= 0x1;
380 case 0x12: /* LNA2 LNA1 */
381 ant_conf
->fast_div_bias
= 0x1;
383 case 0x13: /* LNA2 A+B */
384 if (!(antcomb
->scan
) &&
385 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
386 ant_conf
->fast_div_bias
= 0x3f;
388 ant_conf
->fast_div_bias
= 0x1;
390 case 0x20: /* LNA1 A-B */
391 if (!(antcomb
->scan
) &&
392 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
393 ant_conf
->fast_div_bias
= 0x3f;
395 ant_conf
->fast_div_bias
= 0x1;
397 case 0x21: /* LNA1 LNA2 */
398 ant_conf
->fast_div_bias
= 0x1;
400 case 0x23: /* LNA1 A+B */
401 if (!(antcomb
->scan
) &&
402 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
403 ant_conf
->fast_div_bias
= 0x3f;
405 ant_conf
->fast_div_bias
= 0x1;
407 case 0x30: /* A+B A-B */
408 ant_conf
->fast_div_bias
= 0x1;
410 case 0x31: /* A+B LNA2 */
411 ant_conf
->fast_div_bias
= 0x1;
413 case 0x32: /* A+B LNA1 */
414 ant_conf
->fast_div_bias
= 0x1;
419 } else if (ant_conf
->div_group
== 2) {
420 /* Adjust the fast_div_bias based on main and alt_lna_conf */
421 switch ((ant_conf
->main_lna_conf
<< 4) |
422 ant_conf
->alt_lna_conf
) {
423 case 0x01: /* A-B LNA2 */
424 ant_conf
->fast_div_bias
= 0x1;
426 case 0x02: /* A-B LNA1 */
427 ant_conf
->fast_div_bias
= 0x1;
429 case 0x03: /* A-B A+B */
430 ant_conf
->fast_div_bias
= 0x1;
432 case 0x10: /* LNA2 A-B */
433 if (!(antcomb
->scan
) &&
434 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
435 ant_conf
->fast_div_bias
= 0x1;
437 ant_conf
->fast_div_bias
= 0x2;
439 case 0x12: /* LNA2 LNA1 */
440 ant_conf
->fast_div_bias
= 0x1;
442 case 0x13: /* LNA2 A+B */
443 if (!(antcomb
->scan
) &&
444 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
445 ant_conf
->fast_div_bias
= 0x1;
447 ant_conf
->fast_div_bias
= 0x2;
449 case 0x20: /* LNA1 A-B */
450 if (!(antcomb
->scan
) &&
451 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
452 ant_conf
->fast_div_bias
= 0x1;
454 ant_conf
->fast_div_bias
= 0x2;
456 case 0x21: /* LNA1 LNA2 */
457 ant_conf
->fast_div_bias
= 0x1;
459 case 0x23: /* LNA1 A+B */
460 if (!(antcomb
->scan
) &&
461 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
))
462 ant_conf
->fast_div_bias
= 0x1;
464 ant_conf
->fast_div_bias
= 0x2;
466 case 0x30: /* A+B A-B */
467 ant_conf
->fast_div_bias
= 0x1;
469 case 0x31: /* A+B LNA2 */
470 ant_conf
->fast_div_bias
= 0x1;
472 case 0x32: /* A+B LNA1 */
473 ant_conf
->fast_div_bias
= 0x1;
478 } else if (ant_conf
->div_group
== 3) {
479 switch ((ant_conf
->main_lna_conf
<< 4) |
480 ant_conf
->alt_lna_conf
) {
481 case 0x01: /* A-B LNA2 */
482 ant_conf
->fast_div_bias
= 0x1;
484 case 0x02: /* A-B LNA1 */
485 ant_conf
->fast_div_bias
= 0x39;
487 case 0x03: /* A-B A+B */
488 ant_conf
->fast_div_bias
= 0x1;
490 case 0x10: /* LNA2 A-B */
491 if ((antcomb
->scan
== 0) &&
492 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)) {
493 ant_conf
->fast_div_bias
= 0x3f;
495 ant_conf
->fast_div_bias
= 0x1;
498 case 0x12: /* LNA2 LNA1 */
499 ant_conf
->fast_div_bias
= 0x39;
501 case 0x13: /* LNA2 A+B */
502 if ((antcomb
->scan
== 0) &&
503 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)) {
504 ant_conf
->fast_div_bias
= 0x3f;
506 ant_conf
->fast_div_bias
= 0x1;
509 case 0x20: /* LNA1 A-B */
510 if ((antcomb
->scan
== 0) &&
511 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)) {
512 ant_conf
->fast_div_bias
= 0x3f;
514 ant_conf
->fast_div_bias
= 0x4;
517 case 0x21: /* LNA1 LNA2 */
518 ant_conf
->fast_div_bias
= 0x6;
520 case 0x23: /* LNA1 A+B */
521 if ((antcomb
->scan
== 0) &&
522 (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)) {
523 ant_conf
->fast_div_bias
= 0x3f;
525 ant_conf
->fast_div_bias
= 0x6;
528 case 0x30: /* A+B A-B */
529 ant_conf
->fast_div_bias
= 0x1;
531 case 0x31: /* A+B LNA2 */
532 ant_conf
->fast_div_bias
= 0x6;
534 case 0x32: /* A+B LNA1 */
535 ant_conf
->fast_div_bias
= 0x1;
543 void ath_ant_comb_scan(struct ath_softc
*sc
, struct ath_rx_status
*rs
)
545 struct ath_hw_antcomb_conf div_ant_conf
;
546 struct ath_ant_comb
*antcomb
= &sc
->ant_comb
;
547 int alt_ratio
= 0, alt_rssi_avg
= 0, main_rssi_avg
= 0, curr_alt_set
;
549 int main_rssi
= rs
->rs_rssi_ctl0
;
550 int alt_rssi
= rs
->rs_rssi_ctl1
;
551 int rx_ant_conf
, main_ant_conf
;
552 bool short_scan
= false;
554 rx_ant_conf
= (rs
->rs_rssi_ctl2
>> ATH_ANT_RX_CURRENT_SHIFT
) &
556 main_ant_conf
= (rs
->rs_rssi_ctl2
>> ATH_ANT_RX_MAIN_SHIFT
) &
559 /* Record packet only when both main_rssi and alt_rssi is positive */
560 if (main_rssi
> 0 && alt_rssi
> 0) {
561 antcomb
->total_pkt_count
++;
562 antcomb
->main_total_rssi
+= main_rssi
;
563 antcomb
->alt_total_rssi
+= alt_rssi
;
564 if (main_ant_conf
== rx_ant_conf
)
565 antcomb
->main_recv_cnt
++;
567 antcomb
->alt_recv_cnt
++;
570 /* Short scan check */
571 if (antcomb
->scan
&& antcomb
->alt_good
) {
572 if (time_after(jiffies
, antcomb
->scan_start_time
+
573 msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR
)))
576 if (antcomb
->total_pkt_count
==
577 ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT
) {
578 alt_ratio
= ((antcomb
->alt_recv_cnt
* 100) /
579 antcomb
->total_pkt_count
);
580 if (alt_ratio
< ATH_ANT_DIV_COMB_ALT_ANT_RATIO
)
585 if (((antcomb
->total_pkt_count
< ATH_ANT_DIV_COMB_MAX_PKTCOUNT
) ||
586 rs
->rs_moreaggr
) && !short_scan
)
589 if (antcomb
->total_pkt_count
) {
590 alt_ratio
= ((antcomb
->alt_recv_cnt
* 100) /
591 antcomb
->total_pkt_count
);
592 main_rssi_avg
= (antcomb
->main_total_rssi
/
593 antcomb
->total_pkt_count
);
594 alt_rssi_avg
= (antcomb
->alt_total_rssi
/
595 antcomb
->total_pkt_count
);
599 ath9k_hw_antdiv_comb_conf_get(sc
->sc_ah
, &div_ant_conf
);
600 curr_alt_set
= div_ant_conf
.alt_lna_conf
;
601 curr_main_set
= div_ant_conf
.main_lna_conf
;
605 if (antcomb
->count
== ATH_ANT_DIV_COMB_MAX_COUNT
) {
606 if (alt_ratio
> ATH_ANT_DIV_COMB_ALT_ANT_RATIO
) {
607 ath_lnaconf_alt_good_scan(antcomb
, div_ant_conf
,
609 antcomb
->alt_good
= true;
611 antcomb
->alt_good
= false;
615 antcomb
->scan
= true;
616 antcomb
->scan_not_start
= true;
619 if (!antcomb
->scan
) {
620 if (ath_ant_div_comb_alt_check(div_ant_conf
.div_group
,
621 alt_ratio
, curr_main_set
, curr_alt_set
,
622 alt_rssi_avg
, main_rssi_avg
)) {
623 if (curr_alt_set
== ATH_ANT_DIV_COMB_LNA2
) {
624 /* Switch main and alt LNA */
625 div_ant_conf
.main_lna_conf
=
626 ATH_ANT_DIV_COMB_LNA2
;
627 div_ant_conf
.alt_lna_conf
=
628 ATH_ANT_DIV_COMB_LNA1
;
629 } else if (curr_alt_set
== ATH_ANT_DIV_COMB_LNA1
) {
630 div_ant_conf
.main_lna_conf
=
631 ATH_ANT_DIV_COMB_LNA1
;
632 div_ant_conf
.alt_lna_conf
=
633 ATH_ANT_DIV_COMB_LNA2
;
637 } else if ((curr_alt_set
!= ATH_ANT_DIV_COMB_LNA1
) &&
638 (curr_alt_set
!= ATH_ANT_DIV_COMB_LNA2
)) {
639 /* Set alt to another LNA */
640 if (curr_main_set
== ATH_ANT_DIV_COMB_LNA2
)
641 div_ant_conf
.alt_lna_conf
=
642 ATH_ANT_DIV_COMB_LNA1
;
643 else if (curr_main_set
== ATH_ANT_DIV_COMB_LNA1
)
644 div_ant_conf
.alt_lna_conf
=
645 ATH_ANT_DIV_COMB_LNA2
;
650 if ((alt_rssi_avg
< (main_rssi_avg
+
651 div_ant_conf
.lna1_lna2_delta
)))
655 if (!antcomb
->scan_not_start
) {
656 switch (curr_alt_set
) {
657 case ATH_ANT_DIV_COMB_LNA2
:
658 antcomb
->rssi_lna2
= alt_rssi_avg
;
659 antcomb
->rssi_lna1
= main_rssi_avg
;
660 antcomb
->scan
= true;
662 div_ant_conf
.main_lna_conf
=
663 ATH_ANT_DIV_COMB_LNA1
;
664 div_ant_conf
.alt_lna_conf
=
665 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
667 case ATH_ANT_DIV_COMB_LNA1
:
668 antcomb
->rssi_lna1
= alt_rssi_avg
;
669 antcomb
->rssi_lna2
= main_rssi_avg
;
670 antcomb
->scan
= true;
672 div_ant_conf
.main_lna_conf
= ATH_ANT_DIV_COMB_LNA2
;
673 div_ant_conf
.alt_lna_conf
=
674 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
676 case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
:
677 antcomb
->rssi_add
= alt_rssi_avg
;
678 antcomb
->scan
= true;
680 div_ant_conf
.alt_lna_conf
=
681 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
683 case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
:
684 antcomb
->rssi_sub
= alt_rssi_avg
;
685 antcomb
->scan
= false;
686 if (antcomb
->rssi_lna2
>
687 (antcomb
->rssi_lna1
+
688 ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA
)) {
689 /* use LNA2 as main LNA */
690 if ((antcomb
->rssi_add
> antcomb
->rssi_lna1
) &&
691 (antcomb
->rssi_add
> antcomb
->rssi_sub
)) {
693 div_ant_conf
.main_lna_conf
=
694 ATH_ANT_DIV_COMB_LNA2
;
695 div_ant_conf
.alt_lna_conf
=
696 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
697 } else if (antcomb
->rssi_sub
>
698 antcomb
->rssi_lna1
) {
700 div_ant_conf
.main_lna_conf
=
701 ATH_ANT_DIV_COMB_LNA2
;
702 div_ant_conf
.alt_lna_conf
=
703 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
706 div_ant_conf
.main_lna_conf
=
707 ATH_ANT_DIV_COMB_LNA2
;
708 div_ant_conf
.alt_lna_conf
=
709 ATH_ANT_DIV_COMB_LNA1
;
712 /* use LNA1 as main LNA */
713 if ((antcomb
->rssi_add
> antcomb
->rssi_lna2
) &&
714 (antcomb
->rssi_add
> antcomb
->rssi_sub
)) {
716 div_ant_conf
.main_lna_conf
=
717 ATH_ANT_DIV_COMB_LNA1
;
718 div_ant_conf
.alt_lna_conf
=
719 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2
;
720 } else if (antcomb
->rssi_sub
>
721 antcomb
->rssi_lna1
) {
723 div_ant_conf
.main_lna_conf
=
724 ATH_ANT_DIV_COMB_LNA1
;
725 div_ant_conf
.alt_lna_conf
=
726 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2
;
729 div_ant_conf
.main_lna_conf
=
730 ATH_ANT_DIV_COMB_LNA1
;
731 div_ant_conf
.alt_lna_conf
=
732 ATH_ANT_DIV_COMB_LNA2
;
740 if (!antcomb
->alt_good
) {
741 antcomb
->scan_not_start
= false;
742 /* Set alt to another LNA */
743 if (curr_main_set
== ATH_ANT_DIV_COMB_LNA2
) {
744 div_ant_conf
.main_lna_conf
=
745 ATH_ANT_DIV_COMB_LNA2
;
746 div_ant_conf
.alt_lna_conf
=
747 ATH_ANT_DIV_COMB_LNA1
;
748 } else if (curr_main_set
== ATH_ANT_DIV_COMB_LNA1
) {
749 div_ant_conf
.main_lna_conf
=
750 ATH_ANT_DIV_COMB_LNA1
;
751 div_ant_conf
.alt_lna_conf
=
752 ATH_ANT_DIV_COMB_LNA2
;
758 ath_select_ant_div_from_quick_scan(antcomb
, &div_ant_conf
,
759 main_rssi_avg
, alt_rssi_avg
,
762 antcomb
->quick_scan_cnt
++;
765 ath_ant_div_conf_fast_divbias(&div_ant_conf
, antcomb
, alt_ratio
);
766 ath9k_hw_antdiv_comb_conf_set(sc
->sc_ah
, &div_ant_conf
);
768 antcomb
->scan_start_time
= jiffies
;
769 antcomb
->total_pkt_count
= 0;
770 antcomb
->main_total_rssi
= 0;
771 antcomb
->alt_total_rssi
= 0;
772 antcomb
->main_recv_cnt
= 0;
773 antcomb
->alt_recv_cnt
= 0;
776 void ath_ant_comb_update(struct ath_softc
*sc
)
778 struct ath_hw
*ah
= sc
->sc_ah
;
779 struct ath_common
*common
= ath9k_hw_common(ah
);
780 struct ath_hw_antcomb_conf div_ant_conf
;
783 ath9k_hw_antdiv_comb_conf_get(ah
, &div_ant_conf
);
786 lna_conf
= ATH_ANT_DIV_COMB_LNA1
;
788 lna_conf
= ATH_ANT_DIV_COMB_LNA2
;
790 div_ant_conf
.main_lna_conf
= lna_conf
;
791 div_ant_conf
.alt_lna_conf
= lna_conf
;
793 ath9k_hw_antdiv_comb_conf_set(ah
, &div_ant_conf
);
795 if (common
->antenna_diversity
)
796 ath9k_hw_antctrl_shared_chain_lnadiv(ah
, true);