Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
antenna.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Qualcomm Atheros, Inc.
3  *
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.
7  *
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.
15  */
16 
17 #include "ath9k.h"
18 
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)
22 {
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);
26 }
27 
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)
31 {
32  bool result = false;
33  switch (div_group) {
34  case 0:
35  if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
36  result = true;
37  break;
38  case 1:
39  case 2:
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)))) &&
46  (alt_rssi_avg >= 4))
47  result = true;
48  else
49  result = false;
50  break;
51  }
52 
53  return result;
54 }
55 
56 static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
57  struct ath_hw_antcomb_conf ant_conf,
58  int main_rssi_avg)
59 {
60  antcomb->quick_scan_cnt = 0;
61 
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;
66 
67  switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
68  case 0x10: /* LNA2 A-B */
70  antcomb->first_quick_scan_conf =
73  break;
74  case 0x20: /* LNA1 A-B */
76  antcomb->first_quick_scan_conf =
79  break;
80  case 0x21: /* LNA1 LNA2 */
82  antcomb->first_quick_scan_conf =
84  antcomb->second_quick_scan_conf =
86  break;
87  case 0x12: /* LNA2 LNA1 */
89  antcomb->first_quick_scan_conf =
91  antcomb->second_quick_scan_conf =
93  break;
94  case 0x13: /* LNA2 A+B */
96  antcomb->first_quick_scan_conf =
99  break;
100  case 0x23: /* LNA1 A+B */
102  antcomb->first_quick_scan_conf =
105  break;
106  default:
107  break;
108  }
109 }
110 
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,
114  int alt_ratio)
115 {
116  /* alt_good */
117  switch (antcomb->quick_scan_cnt) {
118  case 0:
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;
122  break;
123  case 1:
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;
129 
130  if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
131  /* main is LNA1 */
132  if (ath_is_alt_ant_ratio_better(alt_ratio,
135  main_rssi_avg, alt_rssi_avg,
136  antcomb->total_pkt_count))
137  antcomb->first_ratio = true;
138  else
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,
144  main_rssi_avg, alt_rssi_avg,
145  antcomb->total_pkt_count))
146  antcomb->first_ratio = true;
147  else
148  antcomb->first_ratio = false;
149  } else {
150  if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
151  (alt_rssi_avg > main_rssi_avg +
153  (alt_rssi_avg > main_rssi_avg)) &&
154  (antcomb->total_pkt_count > 50))
155  antcomb->first_ratio = true;
156  else
157  antcomb->first_ratio = false;
158  }
159  break;
160  case 2:
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;
166 
168  antcomb->rssi_lna1 = alt_rssi_avg;
169  else if (antcomb->second_quick_scan_conf ==
171  antcomb->rssi_lna2 = alt_rssi_avg;
172  else if (antcomb->second_quick_scan_conf ==
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;
178  }
179 
180  if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
182  div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
183  else
184  div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
185 
186  if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
187  if (ath_is_alt_ant_ratio_better(alt_ratio,
190  main_rssi_avg, alt_rssi_avg,
191  antcomb->total_pkt_count))
192  antcomb->second_ratio = true;
193  else
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,
199  main_rssi_avg, alt_rssi_avg,
200  antcomb->total_pkt_count))
201  antcomb->second_ratio = true;
202  else
203  antcomb->second_ratio = false;
204  } else {
205  if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
206  (alt_rssi_avg > main_rssi_avg +
208  (alt_rssi_avg > main_rssi_avg)) &&
209  (antcomb->total_pkt_count > 50))
210  antcomb->second_ratio = true;
211  else
212  antcomb->second_ratio = false;
213  }
214 
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) {
218  /* first alt*/
219  if ((antcomb->first_quick_scan_conf ==
221  (antcomb->first_quick_scan_conf ==
223  /* Set alt LNA1 or LNA2*/
224  if (div_ant_conf->main_lna_conf ==
226  div_ant_conf->alt_lna_conf =
228  else
229  div_ant_conf->alt_lna_conf =
231  else
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 ==
237  (antcomb->second_quick_scan_conf ==
239  /* Set alt LNA1 or LNA2 */
240  if (div_ant_conf->main_lna_conf ==
242  div_ant_conf->alt_lna_conf =
244  else
245  div_ant_conf->alt_lna_conf =
247  } else {
248  /* Set alt to A+B or A-B */
249  div_ant_conf->alt_lna_conf =
250  antcomb->second_quick_scan_conf;
251  }
252  } else if (antcomb->first_ratio) {
253  /* first alt */
254  if ((antcomb->first_quick_scan_conf ==
256  (antcomb->first_quick_scan_conf ==
258  /* Set alt LNA1 or LNA2 */
259  if (div_ant_conf->main_lna_conf ==
261  div_ant_conf->alt_lna_conf =
263  else
264  div_ant_conf->alt_lna_conf =
266  else
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) {
271  /* second alt */
272  if ((antcomb->second_quick_scan_conf ==
274  (antcomb->second_quick_scan_conf ==
276  /* Set alt LNA1 or LNA2 */
277  if (div_ant_conf->main_lna_conf ==
279  div_ant_conf->alt_lna_conf =
281  else
282  div_ant_conf->alt_lna_conf =
284  else
285  /* Set alt to A+B or A-B */
286  div_ant_conf->alt_lna_conf =
287  antcomb->second_quick_scan_conf;
288  } else {
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 ==
295  div_ant_conf->alt_lna_conf =
297  else
298  div_ant_conf->alt_lna_conf =
300  else
301  /* Set alt to A+B or A-B */
302  div_ant_conf->alt_lna_conf = antcomb->main_conf;
303  }
304  break;
305  default:
306  break;
307  }
308 }
309 
310 static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
311  struct ath_ant_comb *antcomb,
312  int alt_ratio)
313 {
314  ant_conf->main_gaintb = 0;
315  ant_conf->alt_gaintb = 0;
316 
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;
323  break;
324  case 0x02: /* A-B LNA1 */
325  ant_conf->fast_div_bias = 0x3d;
326  break;
327  case 0x03: /* A-B A+B */
328  ant_conf->fast_div_bias = 0x1;
329  break;
330  case 0x10: /* LNA2 A-B */
331  ant_conf->fast_div_bias = 0x7;
332  break;
333  case 0x12: /* LNA2 LNA1 */
334  ant_conf->fast_div_bias = 0x2;
335  break;
336  case 0x13: /* LNA2 A+B */
337  ant_conf->fast_div_bias = 0x7;
338  break;
339  case 0x20: /* LNA1 A-B */
340  ant_conf->fast_div_bias = 0x6;
341  break;
342  case 0x21: /* LNA1 LNA2 */
343  ant_conf->fast_div_bias = 0x0;
344  break;
345  case 0x23: /* LNA1 A+B */
346  ant_conf->fast_div_bias = 0x6;
347  break;
348  case 0x30: /* A+B A-B */
349  ant_conf->fast_div_bias = 0x1;
350  break;
351  case 0x31: /* A+B LNA2 */
352  ant_conf->fast_div_bias = 0x3b;
353  break;
354  case 0x32: /* A+B LNA1 */
355  ant_conf->fast_div_bias = 0x3d;
356  break;
357  default:
358  break;
359  }
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;
366  break;
367  case 0x02: /* A-B LNA1 */
368  ant_conf->fast_div_bias = 0x1;
369  break;
370  case 0x03: /* A-B A+B */
371  ant_conf->fast_div_bias = 0x1;
372  break;
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;
377  else
378  ant_conf->fast_div_bias = 0x1;
379  break;
380  case 0x12: /* LNA2 LNA1 */
381  ant_conf->fast_div_bias = 0x1;
382  break;
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;
387  else
388  ant_conf->fast_div_bias = 0x1;
389  break;
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;
394  else
395  ant_conf->fast_div_bias = 0x1;
396  break;
397  case 0x21: /* LNA1 LNA2 */
398  ant_conf->fast_div_bias = 0x1;
399  break;
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;
404  else
405  ant_conf->fast_div_bias = 0x1;
406  break;
407  case 0x30: /* A+B A-B */
408  ant_conf->fast_div_bias = 0x1;
409  break;
410  case 0x31: /* A+B LNA2 */
411  ant_conf->fast_div_bias = 0x1;
412  break;
413  case 0x32: /* A+B LNA1 */
414  ant_conf->fast_div_bias = 0x1;
415  break;
416  default:
417  break;
418  }
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;
425  break;
426  case 0x02: /* A-B LNA1 */
427  ant_conf->fast_div_bias = 0x1;
428  break;
429  case 0x03: /* A-B A+B */
430  ant_conf->fast_div_bias = 0x1;
431  break;
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;
436  else
437  ant_conf->fast_div_bias = 0x2;
438  break;
439  case 0x12: /* LNA2 LNA1 */
440  ant_conf->fast_div_bias = 0x1;
441  break;
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;
446  else
447  ant_conf->fast_div_bias = 0x2;
448  break;
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;
453  else
454  ant_conf->fast_div_bias = 0x2;
455  break;
456  case 0x21: /* LNA1 LNA2 */
457  ant_conf->fast_div_bias = 0x1;
458  break;
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;
463  else
464  ant_conf->fast_div_bias = 0x2;
465  break;
466  case 0x30: /* A+B A-B */
467  ant_conf->fast_div_bias = 0x1;
468  break;
469  case 0x31: /* A+B LNA2 */
470  ant_conf->fast_div_bias = 0x1;
471  break;
472  case 0x32: /* A+B LNA1 */
473  ant_conf->fast_div_bias = 0x1;
474  break;
475  default:
476  break;
477  }
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;
483  break;
484  case 0x02: /* A-B LNA1 */
485  ant_conf->fast_div_bias = 0x39;
486  break;
487  case 0x03: /* A-B A+B */
488  ant_conf->fast_div_bias = 0x1;
489  break;
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;
494  } else {
495  ant_conf->fast_div_bias = 0x1;
496  }
497  break;
498  case 0x12: /* LNA2 LNA1 */
499  ant_conf->fast_div_bias = 0x39;
500  break;
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;
505  } else {
506  ant_conf->fast_div_bias = 0x1;
507  }
508  break;
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;
513  } else {
514  ant_conf->fast_div_bias = 0x4;
515  }
516  break;
517  case 0x21: /* LNA1 LNA2 */
518  ant_conf->fast_div_bias = 0x6;
519  break;
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;
524  } else {
525  ant_conf->fast_div_bias = 0x6;
526  }
527  break;
528  case 0x30: /* A+B A-B */
529  ant_conf->fast_div_bias = 0x1;
530  break;
531  case 0x31: /* A+B LNA2 */
532  ant_conf->fast_div_bias = 0x6;
533  break;
534  case 0x32: /* A+B LNA1 */
535  ant_conf->fast_div_bias = 0x1;
536  break;
537  default:
538  break;
539  }
540  }
541 }
542 
543 void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
544 {
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;
548  int curr_main_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;
553 
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) &
558 
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++;
566  else
567  antcomb->alt_recv_cnt++;
568  }
569 
570  /* Short scan check */
571  if (antcomb->scan && antcomb->alt_good) {
572  if (time_after(jiffies, antcomb->scan_start_time +
574  short_scan = true;
575  else
576  if (antcomb->total_pkt_count ==
578  alt_ratio = ((antcomb->alt_recv_cnt * 100) /
579  antcomb->total_pkt_count);
580  if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
581  short_scan = true;
582  }
583  }
584 
586  rs->rs_moreaggr) && !short_scan)
587  return;
588 
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);
596  }
597 
598 
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;
602 
603  antcomb->count++;
604 
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,
608  main_rssi_avg);
609  antcomb->alt_good = true;
610  } else {
611  antcomb->alt_good = false;
612  }
613 
614  antcomb->count = 0;
615  antcomb->scan = true;
616  antcomb->scan_not_start = true;
617  }
618 
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 =
627  div_ant_conf.alt_lna_conf =
629  } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
630  div_ant_conf.main_lna_conf =
632  div_ant_conf.alt_lna_conf =
634  }
635 
636  goto div_comb_done;
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 =
643  else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
644  div_ant_conf.alt_lna_conf =
646 
647  goto div_comb_done;
648  }
649 
650  if ((alt_rssi_avg < (main_rssi_avg +
651  div_ant_conf.lna1_lna2_delta)))
652  goto div_comb_done;
653  }
654 
655  if (!antcomb->scan_not_start) {
656  switch (curr_alt_set) {
658  antcomb->rssi_lna2 = alt_rssi_avg;
659  antcomb->rssi_lna1 = main_rssi_avg;
660  antcomb->scan = true;
661  /* set to A+B */
662  div_ant_conf.main_lna_conf =
664  div_ant_conf.alt_lna_conf =
666  break;
668  antcomb->rssi_lna1 = alt_rssi_avg;
669  antcomb->rssi_lna2 = main_rssi_avg;
670  antcomb->scan = true;
671  /* set to A+B */
672  div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
673  div_ant_conf.alt_lna_conf =
675  break;
677  antcomb->rssi_add = alt_rssi_avg;
678  antcomb->scan = true;
679  /* set to A-B */
680  div_ant_conf.alt_lna_conf =
682  break;
684  antcomb->rssi_sub = alt_rssi_avg;
685  antcomb->scan = false;
686  if (antcomb->rssi_lna2 >
687  (antcomb->rssi_lna1 +
689  /* use LNA2 as main LNA */
690  if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
691  (antcomb->rssi_add > antcomb->rssi_sub)) {
692  /* set to A+B */
693  div_ant_conf.main_lna_conf =
695  div_ant_conf.alt_lna_conf =
697  } else if (antcomb->rssi_sub >
698  antcomb->rssi_lna1) {
699  /* set to A-B */
700  div_ant_conf.main_lna_conf =
702  div_ant_conf.alt_lna_conf =
704  } else {
705  /* set to LNA1 */
706  div_ant_conf.main_lna_conf =
708  div_ant_conf.alt_lna_conf =
710  }
711  } else {
712  /* use LNA1 as main LNA */
713  if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
714  (antcomb->rssi_add > antcomb->rssi_sub)) {
715  /* set to A+B */
716  div_ant_conf.main_lna_conf =
718  div_ant_conf.alt_lna_conf =
720  } else if (antcomb->rssi_sub >
721  antcomb->rssi_lna1) {
722  /* set to A-B */
723  div_ant_conf.main_lna_conf =
725  div_ant_conf.alt_lna_conf =
727  } else {
728  /* set to LNA2 */
729  div_ant_conf.main_lna_conf =
731  div_ant_conf.alt_lna_conf =
733  }
734  }
735  break;
736  default:
737  break;
738  }
739  } else {
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 =
746  div_ant_conf.alt_lna_conf =
748  } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
749  div_ant_conf.main_lna_conf =
751  div_ant_conf.alt_lna_conf =
753  }
754  goto div_comb_done;
755  }
756  }
757 
758  ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
759  main_rssi_avg, alt_rssi_avg,
760  alt_ratio);
761 
762  antcomb->quick_scan_cnt++;
763 
764 div_comb_done:
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);
767 
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;
774 }
775 
777 {
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;
781  u8 lna_conf;
782 
783  ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
784 
785  if (sc->ant_rx == 1)
786  lna_conf = ATH_ANT_DIV_COMB_LNA1;
787  else
788  lna_conf = ATH_ANT_DIV_COMB_LNA2;
789 
790  div_ant_conf.main_lna_conf = lna_conf;
791  div_ant_conf.alt_lna_conf = lna_conf;
792 
793  ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
794 
795  if (common->antenna_diversity)
796  ath9k_hw_antctrl_shared_chain_lnadiv(ah, true);
797 }