xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/ath/ath9k/antenna.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2012 Qualcomm Atheros, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, and/or distribute this software for any
5*4882a593Smuzhiyun  * purpose with or without fee is hereby granted, provided that the above
6*4882a593Smuzhiyun  * copyright notice and this permission notice appear in all copies.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*4882a593Smuzhiyun  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*4882a593Smuzhiyun  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*4882a593Smuzhiyun  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*4882a593Smuzhiyun  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*4882a593Smuzhiyun  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*4882a593Smuzhiyun  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "ath9k.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * AR9285
21*4882a593Smuzhiyun  * ======
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * EEPROM has 2 4-bit fields containing the card configuration.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * antdiv_ctl1:
26*4882a593Smuzhiyun  * ------------
27*4882a593Smuzhiyun  * bb_enable_ant_div_lnadiv : 1
28*4882a593Smuzhiyun  * bb_ant_div_alt_gaintb    : 1
29*4882a593Smuzhiyun  * bb_ant_div_main_gaintb   : 1
30*4882a593Smuzhiyun  * bb_enable_ant_fast_div   : 1
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  * antdiv_ctl2:
33*4882a593Smuzhiyun  * -----------
34*4882a593Smuzhiyun  * bb_ant_div_alt_lnaconf  : 2
35*4882a593Smuzhiyun  * bb_ant_div_main_lnaconf : 2
36*4882a593Smuzhiyun  *
37*4882a593Smuzhiyun  * The EEPROM bits are used as follows:
38*4882a593Smuzhiyun  * ------------------------------------
39*4882a593Smuzhiyun  *
40*4882a593Smuzhiyun  * bb_enable_ant_div_lnadiv      - Enable LNA path rx antenna diversity/combining.
41*4882a593Smuzhiyun  *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
42*4882a593Smuzhiyun  *
43*4882a593Smuzhiyun  * bb_ant_div_[alt/main]_gaintb  - 0 -> Antenna config Alt/Main uses gaintable 0
44*4882a593Smuzhiyun  *                                 1 -> Antenna config Alt/Main uses gaintable 1
45*4882a593Smuzhiyun  *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
46*4882a593Smuzhiyun  *
47*4882a593Smuzhiyun  * bb_enable_ant_fast_div        - Enable fast antenna diversity.
48*4882a593Smuzhiyun  *                                 Set in AR_PHY_CCK_DETECT.
49*4882a593Smuzhiyun  *
50*4882a593Smuzhiyun  * bb_ant_div_[alt/main]_lnaconf - Alt/Main LNA diversity/combining input config.
51*4882a593Smuzhiyun  *                                 Set in AR_PHY_MULTICHAIN_GAIN_CTL.
52*4882a593Smuzhiyun  *                                 10=LNA1
53*4882a593Smuzhiyun  *                                 01=LNA2
54*4882a593Smuzhiyun  *                                 11=LNA1+LNA2
55*4882a593Smuzhiyun  *                                 00=LNA1-LNA2
56*4882a593Smuzhiyun  *
57*4882a593Smuzhiyun  * AR9485 / AR9565 / AR9331
58*4882a593Smuzhiyun  * ========================
59*4882a593Smuzhiyun  *
60*4882a593Smuzhiyun  * The same bits are present in the EEPROM, but the location in the
61*4882a593Smuzhiyun  * EEPROM is different (ant_div_control in ar9300_BaseExtension_1).
62*4882a593Smuzhiyun  *
63*4882a593Smuzhiyun  * ant_div_alt_lnaconf      ==> bit 0~1
64*4882a593Smuzhiyun  * ant_div_main_lnaconf     ==> bit 2~3
65*4882a593Smuzhiyun  * ant_div_alt_gaintb       ==> bit 4
66*4882a593Smuzhiyun  * ant_div_main_gaintb      ==> bit 5
67*4882a593Smuzhiyun  * enable_ant_div_lnadiv    ==> bit 6
68*4882a593Smuzhiyun  * enable_ant_fast_div      ==> bit 7
69*4882a593Smuzhiyun  */
70*4882a593Smuzhiyun 
ath_is_alt_ant_ratio_better(struct ath_ant_comb * antcomb,int alt_ratio,int maxdelta,int mindelta,int main_rssi_avg,int alt_rssi_avg,int pkt_count)71*4882a593Smuzhiyun static inline bool ath_is_alt_ant_ratio_better(struct ath_ant_comb *antcomb,
72*4882a593Smuzhiyun 					       int alt_ratio, int maxdelta,
73*4882a593Smuzhiyun 					       int mindelta, int main_rssi_avg,
74*4882a593Smuzhiyun 					       int alt_rssi_avg, int pkt_count)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	if (pkt_count <= 50)
77*4882a593Smuzhiyun 		return false;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (alt_rssi_avg > main_rssi_avg + mindelta)
80*4882a593Smuzhiyun 		return true;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	if (alt_ratio >= antcomb->ant_ratio2 &&
83*4882a593Smuzhiyun 	    alt_rssi_avg >= antcomb->low_rssi_thresh &&
84*4882a593Smuzhiyun 	    (alt_rssi_avg > main_rssi_avg + maxdelta))
85*4882a593Smuzhiyun 		return true;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return false;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf * conf,struct ath_ant_comb * antcomb,int alt_ratio,int alt_rssi_avg,int main_rssi_avg)90*4882a593Smuzhiyun static inline bool ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf *conf,
91*4882a593Smuzhiyun 					      struct ath_ant_comb *antcomb,
92*4882a593Smuzhiyun 					      int alt_ratio, int alt_rssi_avg,
93*4882a593Smuzhiyun 					      int main_rssi_avg)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	bool result, set1, set2;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	result = set1 = set2 = false;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2 &&
100*4882a593Smuzhiyun 	    conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA1)
101*4882a593Smuzhiyun 		set1 = true;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA1 &&
104*4882a593Smuzhiyun 	    conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA2)
105*4882a593Smuzhiyun 		set2 = true;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	switch (conf->div_group) {
108*4882a593Smuzhiyun 	case 0:
109*4882a593Smuzhiyun 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
110*4882a593Smuzhiyun 			result = true;
111*4882a593Smuzhiyun 		break;
112*4882a593Smuzhiyun 	case 1:
113*4882a593Smuzhiyun 	case 2:
114*4882a593Smuzhiyun 		if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
115*4882a593Smuzhiyun 			break;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 		if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 5))) ||
118*4882a593Smuzhiyun 		    (set2 && (alt_rssi_avg >= (main_rssi_avg - 2))) ||
119*4882a593Smuzhiyun 		    (alt_ratio > antcomb->ant_ratio))
120*4882a593Smuzhiyun 			result = true;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 		break;
123*4882a593Smuzhiyun 	case 3:
124*4882a593Smuzhiyun 		if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
125*4882a593Smuzhiyun 			break;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 		if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 3))) ||
128*4882a593Smuzhiyun 		    (set2 && (alt_rssi_avg >= (main_rssi_avg + 3))) ||
129*4882a593Smuzhiyun 		    (alt_ratio > antcomb->ant_ratio))
130*4882a593Smuzhiyun 			result = true;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	return result;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
ath_lnaconf_alt_good_scan(struct ath_ant_comb * antcomb,struct ath_hw_antcomb_conf ant_conf,int main_rssi_avg)138*4882a593Smuzhiyun static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
139*4882a593Smuzhiyun 				      struct ath_hw_antcomb_conf ant_conf,
140*4882a593Smuzhiyun 				      int main_rssi_avg)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	antcomb->quick_scan_cnt = 0;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
145*4882a593Smuzhiyun 		antcomb->rssi_lna2 = main_rssi_avg;
146*4882a593Smuzhiyun 	else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1)
147*4882a593Smuzhiyun 		antcomb->rssi_lna1 = main_rssi_avg;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
150*4882a593Smuzhiyun 	case 0x10: /* LNA2 A-B */
151*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
152*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
153*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
154*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 	case 0x20: /* LNA1 A-B */
157*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
158*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
159*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
160*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
161*4882a593Smuzhiyun 		break;
162*4882a593Smuzhiyun 	case 0x21: /* LNA1 LNA2 */
163*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
164*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
165*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
166*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf =
167*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
168*4882a593Smuzhiyun 		break;
169*4882a593Smuzhiyun 	case 0x12: /* LNA2 LNA1 */
170*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
171*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
172*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
173*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf =
174*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
175*4882a593Smuzhiyun 		break;
176*4882a593Smuzhiyun 	case 0x13: /* LNA2 A+B */
177*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
178*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
179*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
180*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
181*4882a593Smuzhiyun 		break;
182*4882a593Smuzhiyun 	case 0x23: /* LNA1 A+B */
183*4882a593Smuzhiyun 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
184*4882a593Smuzhiyun 		antcomb->first_quick_scan_conf =
185*4882a593Smuzhiyun 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
186*4882a593Smuzhiyun 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
187*4882a593Smuzhiyun 		break;
188*4882a593Smuzhiyun 	default:
189*4882a593Smuzhiyun 		break;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
ath_ant_set_alt_ratio(struct ath_ant_comb * antcomb,struct ath_hw_antcomb_conf * conf)193*4882a593Smuzhiyun static void ath_ant_set_alt_ratio(struct ath_ant_comb *antcomb,
194*4882a593Smuzhiyun 				  struct ath_hw_antcomb_conf *conf)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	/* set alt to the conf with maximun ratio */
197*4882a593Smuzhiyun 	if (antcomb->first_ratio && antcomb->second_ratio) {
198*4882a593Smuzhiyun 		if (antcomb->rssi_second > antcomb->rssi_third) {
199*4882a593Smuzhiyun 			/* first alt*/
200*4882a593Smuzhiyun 			if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
201*4882a593Smuzhiyun 			    (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
202*4882a593Smuzhiyun 				/* Set alt LNA1 or LNA2*/
203*4882a593Smuzhiyun 				if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
204*4882a593Smuzhiyun 					conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
205*4882a593Smuzhiyun 				else
206*4882a593Smuzhiyun 					conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
207*4882a593Smuzhiyun 			else
208*4882a593Smuzhiyun 				/* Set alt to A+B or A-B */
209*4882a593Smuzhiyun 				conf->alt_lna_conf =
210*4882a593Smuzhiyun 					antcomb->first_quick_scan_conf;
211*4882a593Smuzhiyun 		} else if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
212*4882a593Smuzhiyun 			   (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) {
213*4882a593Smuzhiyun 			/* Set alt LNA1 or LNA2 */
214*4882a593Smuzhiyun 			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
215*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
216*4882a593Smuzhiyun 			else
217*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
218*4882a593Smuzhiyun 		} else {
219*4882a593Smuzhiyun 			/* Set alt to A+B or A-B */
220*4882a593Smuzhiyun 			conf->alt_lna_conf = antcomb->second_quick_scan_conf;
221*4882a593Smuzhiyun 		}
222*4882a593Smuzhiyun 	} else if (antcomb->first_ratio) {
223*4882a593Smuzhiyun 		/* first alt */
224*4882a593Smuzhiyun 		if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
225*4882a593Smuzhiyun 		    (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
226*4882a593Smuzhiyun 			/* Set alt LNA1 or LNA2 */
227*4882a593Smuzhiyun 			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
228*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
229*4882a593Smuzhiyun 			else
230*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
231*4882a593Smuzhiyun 		else
232*4882a593Smuzhiyun 			/* Set alt to A+B or A-B */
233*4882a593Smuzhiyun 			conf->alt_lna_conf = antcomb->first_quick_scan_conf;
234*4882a593Smuzhiyun 	} else if (antcomb->second_ratio) {
235*4882a593Smuzhiyun 		/* second alt */
236*4882a593Smuzhiyun 		if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) ||
237*4882a593Smuzhiyun 		    (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2))
238*4882a593Smuzhiyun 			/* Set alt LNA1 or LNA2 */
239*4882a593Smuzhiyun 			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
240*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
241*4882a593Smuzhiyun 			else
242*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
243*4882a593Smuzhiyun 		else
244*4882a593Smuzhiyun 			/* Set alt to A+B or A-B */
245*4882a593Smuzhiyun 			conf->alt_lna_conf = antcomb->second_quick_scan_conf;
246*4882a593Smuzhiyun 	} else {
247*4882a593Smuzhiyun 		/* main is largest */
248*4882a593Smuzhiyun 		if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
249*4882a593Smuzhiyun 		    (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
250*4882a593Smuzhiyun 			/* Set alt LNA1 or LNA2 */
251*4882a593Smuzhiyun 			if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
252*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
253*4882a593Smuzhiyun 			else
254*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
255*4882a593Smuzhiyun 		else
256*4882a593Smuzhiyun 			/* Set alt to A+B or A-B */
257*4882a593Smuzhiyun 			conf->alt_lna_conf = antcomb->main_conf;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
ath_select_ant_div_from_quick_scan(struct ath_ant_comb * antcomb,struct ath_hw_antcomb_conf * div_ant_conf,int main_rssi_avg,int alt_rssi_avg,int alt_ratio)261*4882a593Smuzhiyun static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
262*4882a593Smuzhiyun 				       struct ath_hw_antcomb_conf *div_ant_conf,
263*4882a593Smuzhiyun 				       int main_rssi_avg, int alt_rssi_avg,
264*4882a593Smuzhiyun 				       int alt_ratio)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun 	/* alt_good */
267*4882a593Smuzhiyun 	switch (antcomb->quick_scan_cnt) {
268*4882a593Smuzhiyun 	case 0:
269*4882a593Smuzhiyun 		/* set alt to main, and alt to first conf */
270*4882a593Smuzhiyun 		div_ant_conf->main_lna_conf = antcomb->main_conf;
271*4882a593Smuzhiyun 		div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
272*4882a593Smuzhiyun 		break;
273*4882a593Smuzhiyun 	case 1:
274*4882a593Smuzhiyun 		/* set alt to main, and alt to first conf */
275*4882a593Smuzhiyun 		div_ant_conf->main_lna_conf = antcomb->main_conf;
276*4882a593Smuzhiyun 		div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
277*4882a593Smuzhiyun 		antcomb->rssi_first = main_rssi_avg;
278*4882a593Smuzhiyun 		antcomb->rssi_second = alt_rssi_avg;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
281*4882a593Smuzhiyun 			/* main is LNA1 */
282*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
283*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
284*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
285*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
286*4882a593Smuzhiyun 						antcomb->total_pkt_count))
287*4882a593Smuzhiyun 				antcomb->first_ratio = true;
288*4882a593Smuzhiyun 			else
289*4882a593Smuzhiyun 				antcomb->first_ratio = false;
290*4882a593Smuzhiyun 		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
291*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
292*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
293*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
294*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
295*4882a593Smuzhiyun 						antcomb->total_pkt_count))
296*4882a593Smuzhiyun 				antcomb->first_ratio = true;
297*4882a593Smuzhiyun 			else
298*4882a593Smuzhiyun 				antcomb->first_ratio = false;
299*4882a593Smuzhiyun 		} else {
300*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
301*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
302*4882a593Smuzhiyun 						0,
303*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
304*4882a593Smuzhiyun 						antcomb->total_pkt_count))
305*4882a593Smuzhiyun 				antcomb->first_ratio = true;
306*4882a593Smuzhiyun 			else
307*4882a593Smuzhiyun 				antcomb->first_ratio = false;
308*4882a593Smuzhiyun 		}
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 	case 2:
311*4882a593Smuzhiyun 		antcomb->alt_good = false;
312*4882a593Smuzhiyun 		antcomb->scan_not_start = false;
313*4882a593Smuzhiyun 		antcomb->scan = false;
314*4882a593Smuzhiyun 		antcomb->rssi_first = main_rssi_avg;
315*4882a593Smuzhiyun 		antcomb->rssi_third = alt_rssi_avg;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 		switch(antcomb->second_quick_scan_conf) {
318*4882a593Smuzhiyun 		case ATH_ANT_DIV_COMB_LNA1:
319*4882a593Smuzhiyun 			antcomb->rssi_lna1 = alt_rssi_avg;
320*4882a593Smuzhiyun 			break;
321*4882a593Smuzhiyun 		case ATH_ANT_DIV_COMB_LNA2:
322*4882a593Smuzhiyun 			antcomb->rssi_lna2 = alt_rssi_avg;
323*4882a593Smuzhiyun 			break;
324*4882a593Smuzhiyun 		case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
325*4882a593Smuzhiyun 			if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
326*4882a593Smuzhiyun 				antcomb->rssi_lna2 = main_rssi_avg;
327*4882a593Smuzhiyun 			else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
328*4882a593Smuzhiyun 				antcomb->rssi_lna1 = main_rssi_avg;
329*4882a593Smuzhiyun 			break;
330*4882a593Smuzhiyun 		default:
331*4882a593Smuzhiyun 			break;
332*4882a593Smuzhiyun 		}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
335*4882a593Smuzhiyun 		    div_ant_conf->lna1_lna2_switch_delta)
336*4882a593Smuzhiyun 			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
337*4882a593Smuzhiyun 		else
338*4882a593Smuzhiyun 			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
341*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
342*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
343*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
344*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
345*4882a593Smuzhiyun 						antcomb->total_pkt_count))
346*4882a593Smuzhiyun 				antcomb->second_ratio = true;
347*4882a593Smuzhiyun 			else
348*4882a593Smuzhiyun 				antcomb->second_ratio = false;
349*4882a593Smuzhiyun 		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
350*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
351*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
352*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
353*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
354*4882a593Smuzhiyun 						antcomb->total_pkt_count))
355*4882a593Smuzhiyun 				antcomb->second_ratio = true;
356*4882a593Smuzhiyun 			else
357*4882a593Smuzhiyun 				antcomb->second_ratio = false;
358*4882a593Smuzhiyun 		} else {
359*4882a593Smuzhiyun 			if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
360*4882a593Smuzhiyun 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
361*4882a593Smuzhiyun 						0,
362*4882a593Smuzhiyun 						main_rssi_avg, alt_rssi_avg,
363*4882a593Smuzhiyun 						antcomb->total_pkt_count))
364*4882a593Smuzhiyun 				antcomb->second_ratio = true;
365*4882a593Smuzhiyun 			else
366*4882a593Smuzhiyun 				antcomb->second_ratio = false;
367*4882a593Smuzhiyun 		}
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		ath_ant_set_alt_ratio(antcomb, div_ant_conf);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		break;
372*4882a593Smuzhiyun 	default:
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf * ant_conf,struct ath_ant_comb * antcomb,int alt_ratio)377*4882a593Smuzhiyun static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
378*4882a593Smuzhiyun 					  struct ath_ant_comb *antcomb,
379*4882a593Smuzhiyun 					  int alt_ratio)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	ant_conf->main_gaintb = 0;
382*4882a593Smuzhiyun 	ant_conf->alt_gaintb = 0;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	if (ant_conf->div_group == 0) {
385*4882a593Smuzhiyun 		/* Adjust the fast_div_bias based on main and alt lna conf */
386*4882a593Smuzhiyun 		switch ((ant_conf->main_lna_conf << 4) |
387*4882a593Smuzhiyun 				ant_conf->alt_lna_conf) {
388*4882a593Smuzhiyun 		case 0x01: /* A-B LNA2 */
389*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3b;
390*4882a593Smuzhiyun 			break;
391*4882a593Smuzhiyun 		case 0x02: /* A-B LNA1 */
392*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3d;
393*4882a593Smuzhiyun 			break;
394*4882a593Smuzhiyun 		case 0x03: /* A-B A+B */
395*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
396*4882a593Smuzhiyun 			break;
397*4882a593Smuzhiyun 		case 0x10: /* LNA2 A-B */
398*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x7;
399*4882a593Smuzhiyun 			break;
400*4882a593Smuzhiyun 		case 0x12: /* LNA2 LNA1 */
401*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x2;
402*4882a593Smuzhiyun 			break;
403*4882a593Smuzhiyun 		case 0x13: /* LNA2 A+B */
404*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x7;
405*4882a593Smuzhiyun 			break;
406*4882a593Smuzhiyun 		case 0x20: /* LNA1 A-B */
407*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x6;
408*4882a593Smuzhiyun 			break;
409*4882a593Smuzhiyun 		case 0x21: /* LNA1 LNA2 */
410*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x0;
411*4882a593Smuzhiyun 			break;
412*4882a593Smuzhiyun 		case 0x23: /* LNA1 A+B */
413*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x6;
414*4882a593Smuzhiyun 			break;
415*4882a593Smuzhiyun 		case 0x30: /* A+B A-B */
416*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
417*4882a593Smuzhiyun 			break;
418*4882a593Smuzhiyun 		case 0x31: /* A+B LNA2 */
419*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3b;
420*4882a593Smuzhiyun 			break;
421*4882a593Smuzhiyun 		case 0x32: /* A+B LNA1 */
422*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3d;
423*4882a593Smuzhiyun 			break;
424*4882a593Smuzhiyun 		default:
425*4882a593Smuzhiyun 			break;
426*4882a593Smuzhiyun 		}
427*4882a593Smuzhiyun 	} else if (ant_conf->div_group == 1) {
428*4882a593Smuzhiyun 		/* Adjust the fast_div_bias based on main and alt_lna_conf */
429*4882a593Smuzhiyun 		switch ((ant_conf->main_lna_conf << 4) |
430*4882a593Smuzhiyun 			ant_conf->alt_lna_conf) {
431*4882a593Smuzhiyun 		case 0x01: /* A-B LNA2 */
432*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
433*4882a593Smuzhiyun 			break;
434*4882a593Smuzhiyun 		case 0x02: /* A-B LNA1 */
435*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
436*4882a593Smuzhiyun 			break;
437*4882a593Smuzhiyun 		case 0x03: /* A-B A+B */
438*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
439*4882a593Smuzhiyun 			break;
440*4882a593Smuzhiyun 		case 0x10: /* LNA2 A-B */
441*4882a593Smuzhiyun 			if (!(antcomb->scan) &&
442*4882a593Smuzhiyun 			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
443*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x3f;
444*4882a593Smuzhiyun 			else
445*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
446*4882a593Smuzhiyun 			break;
447*4882a593Smuzhiyun 		case 0x12: /* LNA2 LNA1 */
448*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
449*4882a593Smuzhiyun 			break;
450*4882a593Smuzhiyun 		case 0x13: /* LNA2 A+B */
451*4882a593Smuzhiyun 			if (!(antcomb->scan) &&
452*4882a593Smuzhiyun 			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
453*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x3f;
454*4882a593Smuzhiyun 			else
455*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
456*4882a593Smuzhiyun 			break;
457*4882a593Smuzhiyun 		case 0x20: /* LNA1 A-B */
458*4882a593Smuzhiyun 			if (!(antcomb->scan) &&
459*4882a593Smuzhiyun 			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
460*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x3f;
461*4882a593Smuzhiyun 			else
462*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
463*4882a593Smuzhiyun 			break;
464*4882a593Smuzhiyun 		case 0x21: /* LNA1 LNA2 */
465*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
466*4882a593Smuzhiyun 			break;
467*4882a593Smuzhiyun 		case 0x23: /* LNA1 A+B */
468*4882a593Smuzhiyun 			if (!(antcomb->scan) &&
469*4882a593Smuzhiyun 			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
470*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x3f;
471*4882a593Smuzhiyun 			else
472*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
473*4882a593Smuzhiyun 			break;
474*4882a593Smuzhiyun 		case 0x30: /* A+B A-B */
475*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
476*4882a593Smuzhiyun 			break;
477*4882a593Smuzhiyun 		case 0x31: /* A+B LNA2 */
478*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
479*4882a593Smuzhiyun 			break;
480*4882a593Smuzhiyun 		case 0x32: /* A+B LNA1 */
481*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
482*4882a593Smuzhiyun 			break;
483*4882a593Smuzhiyun 		default:
484*4882a593Smuzhiyun 			break;
485*4882a593Smuzhiyun 		}
486*4882a593Smuzhiyun 	} else if (ant_conf->div_group == 2) {
487*4882a593Smuzhiyun 		/* Adjust the fast_div_bias based on main and alt_lna_conf */
488*4882a593Smuzhiyun 		switch ((ant_conf->main_lna_conf << 4) |
489*4882a593Smuzhiyun 				ant_conf->alt_lna_conf) {
490*4882a593Smuzhiyun 		case 0x01: /* A-B LNA2 */
491*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
492*4882a593Smuzhiyun 			break;
493*4882a593Smuzhiyun 		case 0x02: /* A-B LNA1 */
494*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
495*4882a593Smuzhiyun 			break;
496*4882a593Smuzhiyun 		case 0x03: /* A-B A+B */
497*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
498*4882a593Smuzhiyun 			break;
499*4882a593Smuzhiyun 		case 0x10: /* LNA2 A-B */
500*4882a593Smuzhiyun 			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
501*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
502*4882a593Smuzhiyun 			else
503*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x2;
504*4882a593Smuzhiyun 			break;
505*4882a593Smuzhiyun 		case 0x12: /* LNA2 LNA1 */
506*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
507*4882a593Smuzhiyun 			break;
508*4882a593Smuzhiyun 		case 0x13: /* LNA2 A+B */
509*4882a593Smuzhiyun 			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
510*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
511*4882a593Smuzhiyun 			else
512*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x2;
513*4882a593Smuzhiyun 			break;
514*4882a593Smuzhiyun 		case 0x20: /* LNA1 A-B */
515*4882a593Smuzhiyun 			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
516*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
517*4882a593Smuzhiyun 			else
518*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x2;
519*4882a593Smuzhiyun 			break;
520*4882a593Smuzhiyun 		case 0x21: /* LNA1 LNA2 */
521*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
522*4882a593Smuzhiyun 			break;
523*4882a593Smuzhiyun 		case 0x23: /* LNA1 A+B */
524*4882a593Smuzhiyun 			if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
525*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x1;
526*4882a593Smuzhiyun 			else
527*4882a593Smuzhiyun 				ant_conf->fast_div_bias = 0x2;
528*4882a593Smuzhiyun 			break;
529*4882a593Smuzhiyun 		case 0x30: /* A+B A-B */
530*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
531*4882a593Smuzhiyun 			break;
532*4882a593Smuzhiyun 		case 0x31: /* A+B LNA2 */
533*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
534*4882a593Smuzhiyun 			break;
535*4882a593Smuzhiyun 		case 0x32: /* A+B LNA1 */
536*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
537*4882a593Smuzhiyun 			break;
538*4882a593Smuzhiyun 		default:
539*4882a593Smuzhiyun 			break;
540*4882a593Smuzhiyun 		}
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 		if (antcomb->fast_div_bias)
543*4882a593Smuzhiyun 			ant_conf->fast_div_bias = antcomb->fast_div_bias;
544*4882a593Smuzhiyun 	} else if (ant_conf->div_group == 3) {
545*4882a593Smuzhiyun 		switch ((ant_conf->main_lna_conf << 4) |
546*4882a593Smuzhiyun 			ant_conf->alt_lna_conf) {
547*4882a593Smuzhiyun 		case 0x01: /* A-B LNA2 */
548*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
549*4882a593Smuzhiyun 			break;
550*4882a593Smuzhiyun 		case 0x02: /* A-B LNA1 */
551*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x39;
552*4882a593Smuzhiyun 			break;
553*4882a593Smuzhiyun 		case 0x03: /* A-B A+B */
554*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
555*4882a593Smuzhiyun 			break;
556*4882a593Smuzhiyun 		case 0x10: /* LNA2 A-B */
557*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x2;
558*4882a593Smuzhiyun 			break;
559*4882a593Smuzhiyun 		case 0x12: /* LNA2 LNA1 */
560*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3f;
561*4882a593Smuzhiyun 			break;
562*4882a593Smuzhiyun 		case 0x13: /* LNA2 A+B */
563*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x2;
564*4882a593Smuzhiyun 			break;
565*4882a593Smuzhiyun 		case 0x20: /* LNA1 A-B */
566*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3;
567*4882a593Smuzhiyun 			break;
568*4882a593Smuzhiyun 		case 0x21: /* LNA1 LNA2 */
569*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3;
570*4882a593Smuzhiyun 			break;
571*4882a593Smuzhiyun 		case 0x23: /* LNA1 A+B */
572*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x3;
573*4882a593Smuzhiyun 			break;
574*4882a593Smuzhiyun 		case 0x30: /* A+B A-B */
575*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
576*4882a593Smuzhiyun 			break;
577*4882a593Smuzhiyun 		case 0x31: /* A+B LNA2 */
578*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x6;
579*4882a593Smuzhiyun 			break;
580*4882a593Smuzhiyun 		case 0x32: /* A+B LNA1 */
581*4882a593Smuzhiyun 			ant_conf->fast_div_bias = 0x1;
582*4882a593Smuzhiyun 			break;
583*4882a593Smuzhiyun 		default:
584*4882a593Smuzhiyun 			break;
585*4882a593Smuzhiyun 		}
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun 
ath_ant_try_scan(struct ath_ant_comb * antcomb,struct ath_hw_antcomb_conf * conf,int curr_alt_set,int alt_rssi_avg,int main_rssi_avg)589*4882a593Smuzhiyun static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
590*4882a593Smuzhiyun 			     struct ath_hw_antcomb_conf *conf,
591*4882a593Smuzhiyun 			     int curr_alt_set, int alt_rssi_avg,
592*4882a593Smuzhiyun 			     int main_rssi_avg)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun 	switch (curr_alt_set) {
595*4882a593Smuzhiyun 	case ATH_ANT_DIV_COMB_LNA2:
596*4882a593Smuzhiyun 		antcomb->rssi_lna2 = alt_rssi_avg;
597*4882a593Smuzhiyun 		antcomb->rssi_lna1 = main_rssi_avg;
598*4882a593Smuzhiyun 		antcomb->scan = true;
599*4882a593Smuzhiyun 		/* set to A+B */
600*4882a593Smuzhiyun 		conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
601*4882a593Smuzhiyun 		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
602*4882a593Smuzhiyun 		break;
603*4882a593Smuzhiyun 	case ATH_ANT_DIV_COMB_LNA1:
604*4882a593Smuzhiyun 		antcomb->rssi_lna1 = alt_rssi_avg;
605*4882a593Smuzhiyun 		antcomb->rssi_lna2 = main_rssi_avg;
606*4882a593Smuzhiyun 		antcomb->scan = true;
607*4882a593Smuzhiyun 		/* set to A+B */
608*4882a593Smuzhiyun 		conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
609*4882a593Smuzhiyun 		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
610*4882a593Smuzhiyun 		break;
611*4882a593Smuzhiyun 	case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
612*4882a593Smuzhiyun 		antcomb->rssi_add = alt_rssi_avg;
613*4882a593Smuzhiyun 		antcomb->scan = true;
614*4882a593Smuzhiyun 		/* set to A-B */
615*4882a593Smuzhiyun 		conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
616*4882a593Smuzhiyun 		break;
617*4882a593Smuzhiyun 	case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
618*4882a593Smuzhiyun 		antcomb->rssi_sub = alt_rssi_avg;
619*4882a593Smuzhiyun 		antcomb->scan = false;
620*4882a593Smuzhiyun 		if (antcomb->rssi_lna2 >
621*4882a593Smuzhiyun 		    (antcomb->rssi_lna1 + conf->lna1_lna2_switch_delta)) {
622*4882a593Smuzhiyun 			/* use LNA2 as main LNA */
623*4882a593Smuzhiyun 			if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
624*4882a593Smuzhiyun 			    (antcomb->rssi_add > antcomb->rssi_sub)) {
625*4882a593Smuzhiyun 				/* set to A+B */
626*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
627*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
628*4882a593Smuzhiyun 			} else if (antcomb->rssi_sub >
629*4882a593Smuzhiyun 				   antcomb->rssi_lna1) {
630*4882a593Smuzhiyun 				/* set to A-B */
631*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
632*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
633*4882a593Smuzhiyun 			} else {
634*4882a593Smuzhiyun 				/* set to LNA1 */
635*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
636*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
637*4882a593Smuzhiyun 			}
638*4882a593Smuzhiyun 		} else {
639*4882a593Smuzhiyun 			/* use LNA1 as main LNA */
640*4882a593Smuzhiyun 			if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
641*4882a593Smuzhiyun 			    (antcomb->rssi_add > antcomb->rssi_sub)) {
642*4882a593Smuzhiyun 				/* set to A+B */
643*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
644*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
645*4882a593Smuzhiyun 			} else if (antcomb->rssi_sub >
646*4882a593Smuzhiyun 				   antcomb->rssi_lna1) {
647*4882a593Smuzhiyun 				/* set to A-B */
648*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
649*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
650*4882a593Smuzhiyun 			} else {
651*4882a593Smuzhiyun 				/* set to LNA2 */
652*4882a593Smuzhiyun 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
653*4882a593Smuzhiyun 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
654*4882a593Smuzhiyun 			}
655*4882a593Smuzhiyun 		}
656*4882a593Smuzhiyun 		break;
657*4882a593Smuzhiyun 	default:
658*4882a593Smuzhiyun 		break;
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun 
ath_ant_try_switch(struct ath_hw_antcomb_conf * div_ant_conf,struct ath_ant_comb * antcomb,int alt_ratio,int alt_rssi_avg,int main_rssi_avg,int curr_main_set,int curr_alt_set)662*4882a593Smuzhiyun static bool ath_ant_try_switch(struct ath_hw_antcomb_conf *div_ant_conf,
663*4882a593Smuzhiyun 			       struct ath_ant_comb *antcomb,
664*4882a593Smuzhiyun 			       int alt_ratio, int alt_rssi_avg,
665*4882a593Smuzhiyun 			       int main_rssi_avg, int curr_main_set,
666*4882a593Smuzhiyun 			       int curr_alt_set)
667*4882a593Smuzhiyun {
668*4882a593Smuzhiyun 	bool ret = false;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (ath_ant_div_comb_alt_check(div_ant_conf, antcomb, alt_ratio,
671*4882a593Smuzhiyun 				       alt_rssi_avg, main_rssi_avg)) {
672*4882a593Smuzhiyun 		if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
673*4882a593Smuzhiyun 			/*
674*4882a593Smuzhiyun 			 * Switch main and alt LNA.
675*4882a593Smuzhiyun 			 */
676*4882a593Smuzhiyun 			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
677*4882a593Smuzhiyun 			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
678*4882a593Smuzhiyun 		} else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
679*4882a593Smuzhiyun 			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
680*4882a593Smuzhiyun 			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
681*4882a593Smuzhiyun 		}
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 		ret = true;
684*4882a593Smuzhiyun 	} else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
685*4882a593Smuzhiyun 		   (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
686*4882a593Smuzhiyun 		/*
687*4882a593Smuzhiyun 		  Set alt to another LNA.
688*4882a593Smuzhiyun 		*/
689*4882a593Smuzhiyun 		if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
690*4882a593Smuzhiyun 			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1;
691*4882a593Smuzhiyun 		else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
692*4882a593Smuzhiyun 			div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 		ret = true;
695*4882a593Smuzhiyun 	}
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	return ret;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun 
ath_ant_short_scan_check(struct ath_ant_comb * antcomb)700*4882a593Smuzhiyun static bool ath_ant_short_scan_check(struct ath_ant_comb *antcomb)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	int alt_ratio;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	if (!antcomb->scan || !antcomb->alt_good)
705*4882a593Smuzhiyun 		return false;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	if (time_after(jiffies, antcomb->scan_start_time +
708*4882a593Smuzhiyun 		       msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
709*4882a593Smuzhiyun 		return true;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	if (antcomb->total_pkt_count == ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
712*4882a593Smuzhiyun 		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
713*4882a593Smuzhiyun 			     antcomb->total_pkt_count);
714*4882a593Smuzhiyun 		if (alt_ratio < antcomb->ant_ratio)
715*4882a593Smuzhiyun 			return true;
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	return false;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun 
ath_ant_comb_scan(struct ath_softc * sc,struct ath_rx_status * rs)721*4882a593Smuzhiyun void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun 	struct ath_hw_antcomb_conf div_ant_conf;
724*4882a593Smuzhiyun 	struct ath_ant_comb *antcomb = &sc->ant_comb;
725*4882a593Smuzhiyun 	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
726*4882a593Smuzhiyun 	int curr_main_set;
727*4882a593Smuzhiyun 	int main_rssi = rs->rs_rssi_ctl[0];
728*4882a593Smuzhiyun 	int alt_rssi = rs->rs_rssi_ctl[1];
729*4882a593Smuzhiyun 	int rx_ant_conf,  main_ant_conf;
730*4882a593Smuzhiyun 	bool short_scan = false, ret;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
733*4882a593Smuzhiyun 		       ATH_ANT_RX_MASK;
734*4882a593Smuzhiyun 	main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
735*4882a593Smuzhiyun 			 ATH_ANT_RX_MASK;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	if (alt_rssi >= antcomb->low_rssi_thresh) {
738*4882a593Smuzhiyun 		antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO;
739*4882a593Smuzhiyun 		antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2;
740*4882a593Smuzhiyun 	} else {
741*4882a593Smuzhiyun 		antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI;
742*4882a593Smuzhiyun 		antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI;
743*4882a593Smuzhiyun 	}
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	/* Record packet only when both main_rssi and  alt_rssi is positive */
746*4882a593Smuzhiyun 	if (main_rssi > 0 && alt_rssi > 0) {
747*4882a593Smuzhiyun 		antcomb->total_pkt_count++;
748*4882a593Smuzhiyun 		antcomb->main_total_rssi += main_rssi;
749*4882a593Smuzhiyun 		antcomb->alt_total_rssi  += alt_rssi;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 		if (main_ant_conf == rx_ant_conf)
752*4882a593Smuzhiyun 			antcomb->main_recv_cnt++;
753*4882a593Smuzhiyun 		else
754*4882a593Smuzhiyun 			antcomb->alt_recv_cnt++;
755*4882a593Smuzhiyun 	}
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	if (main_ant_conf == rx_ant_conf) {
758*4882a593Smuzhiyun 		ANT_STAT_INC(sc, ANT_MAIN, recv_cnt);
759*4882a593Smuzhiyun 		ANT_LNA_INC(sc, ANT_MAIN, rx_ant_conf);
760*4882a593Smuzhiyun 	} else {
761*4882a593Smuzhiyun 		ANT_STAT_INC(sc, ANT_ALT, recv_cnt);
762*4882a593Smuzhiyun 		ANT_LNA_INC(sc, ANT_ALT, rx_ant_conf);
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	/* Short scan check */
766*4882a593Smuzhiyun 	short_scan = ath_ant_short_scan_check(antcomb);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
769*4882a593Smuzhiyun 	     rs->rs_moreaggr) && !short_scan)
770*4882a593Smuzhiyun 		return;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	if (antcomb->total_pkt_count) {
773*4882a593Smuzhiyun 		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
774*4882a593Smuzhiyun 			     antcomb->total_pkt_count);
775*4882a593Smuzhiyun 		main_rssi_avg = (antcomb->main_total_rssi /
776*4882a593Smuzhiyun 				 antcomb->total_pkt_count);
777*4882a593Smuzhiyun 		alt_rssi_avg = (antcomb->alt_total_rssi /
778*4882a593Smuzhiyun 				 antcomb->total_pkt_count);
779*4882a593Smuzhiyun 	}
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
782*4882a593Smuzhiyun 	curr_alt_set = div_ant_conf.alt_lna_conf;
783*4882a593Smuzhiyun 	curr_main_set = div_ant_conf.main_lna_conf;
784*4882a593Smuzhiyun 	antcomb->count++;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
787*4882a593Smuzhiyun 		if (alt_ratio > antcomb->ant_ratio) {
788*4882a593Smuzhiyun 			ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
789*4882a593Smuzhiyun 						  main_rssi_avg);
790*4882a593Smuzhiyun 			antcomb->alt_good = true;
791*4882a593Smuzhiyun 		} else {
792*4882a593Smuzhiyun 			antcomb->alt_good = false;
793*4882a593Smuzhiyun 		}
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 		antcomb->count = 0;
796*4882a593Smuzhiyun 		antcomb->scan = true;
797*4882a593Smuzhiyun 		antcomb->scan_not_start = true;
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	if (!antcomb->scan) {
801*4882a593Smuzhiyun 		ret = ath_ant_try_switch(&div_ant_conf, antcomb, alt_ratio,
802*4882a593Smuzhiyun 					 alt_rssi_avg, main_rssi_avg,
803*4882a593Smuzhiyun 					 curr_main_set, curr_alt_set);
804*4882a593Smuzhiyun 		if (ret)
805*4882a593Smuzhiyun 			goto div_comb_done;
806*4882a593Smuzhiyun 	}
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	if (!antcomb->scan &&
809*4882a593Smuzhiyun 	    (alt_rssi_avg < (main_rssi_avg + div_ant_conf.lna1_lna2_delta)))
810*4882a593Smuzhiyun 		goto div_comb_done;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	if (!antcomb->scan_not_start) {
813*4882a593Smuzhiyun 		ath_ant_try_scan(antcomb, &div_ant_conf, curr_alt_set,
814*4882a593Smuzhiyun 				 alt_rssi_avg, main_rssi_avg);
815*4882a593Smuzhiyun 	} else {
816*4882a593Smuzhiyun 		if (!antcomb->alt_good) {
817*4882a593Smuzhiyun 			antcomb->scan_not_start = false;
818*4882a593Smuzhiyun 			/* Set alt to another LNA */
819*4882a593Smuzhiyun 			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
820*4882a593Smuzhiyun 				div_ant_conf.main_lna_conf =
821*4882a593Smuzhiyun 					ATH_ANT_DIV_COMB_LNA2;
822*4882a593Smuzhiyun 				div_ant_conf.alt_lna_conf =
823*4882a593Smuzhiyun 					ATH_ANT_DIV_COMB_LNA1;
824*4882a593Smuzhiyun 			} else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
825*4882a593Smuzhiyun 				div_ant_conf.main_lna_conf =
826*4882a593Smuzhiyun 					ATH_ANT_DIV_COMB_LNA1;
827*4882a593Smuzhiyun 				div_ant_conf.alt_lna_conf =
828*4882a593Smuzhiyun 					ATH_ANT_DIV_COMB_LNA2;
829*4882a593Smuzhiyun 			}
830*4882a593Smuzhiyun 			goto div_comb_done;
831*4882a593Smuzhiyun 		}
832*4882a593Smuzhiyun 		ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
833*4882a593Smuzhiyun 						   main_rssi_avg, alt_rssi_avg,
834*4882a593Smuzhiyun 						   alt_ratio);
835*4882a593Smuzhiyun 		antcomb->quick_scan_cnt++;
836*4882a593Smuzhiyun 	}
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun div_comb_done:
839*4882a593Smuzhiyun 	ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio);
840*4882a593Smuzhiyun 	ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
841*4882a593Smuzhiyun 	ath9k_debug_stat_ant(sc, &div_ant_conf, main_rssi_avg, alt_rssi_avg);
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	antcomb->scan_start_time = jiffies;
844*4882a593Smuzhiyun 	antcomb->total_pkt_count = 0;
845*4882a593Smuzhiyun 	antcomb->main_total_rssi = 0;
846*4882a593Smuzhiyun 	antcomb->alt_total_rssi = 0;
847*4882a593Smuzhiyun 	antcomb->main_recv_cnt = 0;
848*4882a593Smuzhiyun 	antcomb->alt_recv_cnt = 0;
849*4882a593Smuzhiyun }
850