xref: /freebsd/sys/dev/ath/if_ath_lna_div.c (revision 0f0eebe793c5bb52b04971ead536604360596408)
1216ca234SAdrian Chadd /*-
2216ca234SAdrian Chadd  * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
3216ca234SAdrian Chadd  * All rights reserved.
4216ca234SAdrian Chadd  *
5216ca234SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
6216ca234SAdrian Chadd  * modification, are permitted provided that the following conditions
7216ca234SAdrian Chadd  * are met:
8216ca234SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
9216ca234SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
10216ca234SAdrian Chadd  *    without modification.
11216ca234SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12216ca234SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13216ca234SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
14216ca234SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
15216ca234SAdrian Chadd  *
16216ca234SAdrian Chadd  * NO WARRANTY
17216ca234SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18216ca234SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19216ca234SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20216ca234SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21216ca234SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22216ca234SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23216ca234SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24216ca234SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25216ca234SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26216ca234SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27216ca234SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
28216ca234SAdrian Chadd  *
29216ca234SAdrian Chadd  * $FreeBSD$
30216ca234SAdrian Chadd  */
31216ca234SAdrian Chadd #include <sys/cdefs.h>
32216ca234SAdrian Chadd __FBSDID("$FreeBSD$");
33216ca234SAdrian Chadd 
34216ca234SAdrian Chadd /*
35216ca234SAdrian Chadd  * This module handles LNA diversity for those chips which implement LNA
36216ca234SAdrian Chadd  * mixing (AR9285/AR9485.)
37216ca234SAdrian Chadd  */
38216ca234SAdrian Chadd #include "opt_ath.h"
39216ca234SAdrian Chadd #include "opt_inet.h"
40216ca234SAdrian Chadd #include "opt_wlan.h"
41216ca234SAdrian Chadd 
42216ca234SAdrian Chadd #include <sys/param.h>
43216ca234SAdrian Chadd #include <sys/systm.h>
44216ca234SAdrian Chadd #include <sys/sysctl.h>
45216ca234SAdrian Chadd #include <sys/kernel.h>
46216ca234SAdrian Chadd #include <sys/lock.h>
47216ca234SAdrian Chadd #include <sys/mutex.h>
48216ca234SAdrian Chadd #include <sys/errno.h>
49216ca234SAdrian Chadd 
50216ca234SAdrian Chadd #include <machine/bus.h>
51216ca234SAdrian Chadd #include <machine/resource.h>
52216ca234SAdrian Chadd #include <sys/bus.h>
53216ca234SAdrian Chadd 
54216ca234SAdrian Chadd #include <sys/socket.h>
55216ca234SAdrian Chadd 
56216ca234SAdrian Chadd #include <net/if.h>
57216ca234SAdrian Chadd #include <net/if_media.h>
58216ca234SAdrian Chadd #include <net/if_arp.h>
59216ca234SAdrian Chadd #include <net/ethernet.h>		/* XXX for ether_sprintf */
60216ca234SAdrian Chadd 
61216ca234SAdrian Chadd #include <net80211/ieee80211_var.h>
62216ca234SAdrian Chadd 
63216ca234SAdrian Chadd #include <net/bpf.h>
64216ca234SAdrian Chadd 
65216ca234SAdrian Chadd #ifdef INET
66216ca234SAdrian Chadd #include <netinet/in.h>
67216ca234SAdrian Chadd #include <netinet/if_ether.h>
68216ca234SAdrian Chadd #endif
69216ca234SAdrian Chadd 
70216ca234SAdrian Chadd #include <dev/ath/if_athvar.h>
71216ca234SAdrian Chadd #include <dev/ath/if_ath_debug.h>
72216ca234SAdrian Chadd #include <dev/ath/if_ath_lna_div.h>
73216ca234SAdrian Chadd 
74216ca234SAdrian Chadd /* Linux compability macros */
75216ca234SAdrian Chadd /*
76216ca234SAdrian Chadd  * XXX these don't handle rounding, underflow, overflow, wrapping!
77216ca234SAdrian Chadd  */
78216ca234SAdrian Chadd #define	msecs_to_jiffies(a)		( (a) * hz / 1000 )
79216ca234SAdrian Chadd 
80216ca234SAdrian Chadd /*
81216ca234SAdrian Chadd  * Methods which are required
82216ca234SAdrian Chadd  */
83216ca234SAdrian Chadd 
84216ca234SAdrian Chadd /*
85216ca234SAdrian Chadd  * Attach the LNA diversity to the given interface
86216ca234SAdrian Chadd  */
87216ca234SAdrian Chadd int
88216ca234SAdrian Chadd ath_lna_div_attach(struct ath_softc *sc)
89216ca234SAdrian Chadd {
90216ca234SAdrian Chadd 	struct if_ath_ant_comb_state *ss;
91*0f0eebe7SAdrian Chadd 	HAL_ANT_COMB_CONFIG div_ant_conf;
92216ca234SAdrian Chadd 
93216ca234SAdrian Chadd 	/* Only do this if diversity is enabled */
94216ca234SAdrian Chadd 	if (! ath_hal_hasdivantcomb(sc->sc_ah))
95216ca234SAdrian Chadd 		return (0);
96216ca234SAdrian Chadd 
97216ca234SAdrian Chadd 	ss = malloc(sizeof(struct if_ath_ant_comb_state),
98216ca234SAdrian Chadd 	    M_TEMP, M_WAITOK | M_ZERO);
99216ca234SAdrian Chadd 	if (ss == NULL) {
100216ca234SAdrian Chadd 		device_printf(sc->sc_dev, "%s: failed to allocate\n",
101216ca234SAdrian Chadd 		    __func__);
102216ca234SAdrian Chadd 		/* Don't fail at this point */
103216ca234SAdrian Chadd 		return (0);
104216ca234SAdrian Chadd 	}
105216ca234SAdrian Chadd 
106*0f0eebe7SAdrian Chadd 	/* Fetch the hardware configuration */
107*0f0eebe7SAdrian Chadd 	OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf));
108*0f0eebe7SAdrian Chadd 	ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf);
109*0f0eebe7SAdrian Chadd 
110*0f0eebe7SAdrian Chadd 	/* Figure out what the hardware specific bits should be */
111*0f0eebe7SAdrian Chadd 	if ((div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_1) ||
112*0f0eebe7SAdrian Chadd 	    (div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_2)) {
113*0f0eebe7SAdrian Chadd 		ss->lna1_lna2_delta = -9;
114*0f0eebe7SAdrian Chadd 	} else {
115*0f0eebe7SAdrian Chadd 		ss->lna1_lna2_delta = -3;
116*0f0eebe7SAdrian Chadd 	}
117*0f0eebe7SAdrian Chadd 
118216ca234SAdrian Chadd 	/* Let's flip this on */
119216ca234SAdrian Chadd 	sc->sc_lna_div = ss;
120216ca234SAdrian Chadd 	sc->sc_dolnadiv = 1;
121216ca234SAdrian Chadd 
122216ca234SAdrian Chadd 	return (0);
123216ca234SAdrian Chadd }
124216ca234SAdrian Chadd 
125216ca234SAdrian Chadd /*
126216ca234SAdrian Chadd  * Detach the LNA diversity state from the given interface
127216ca234SAdrian Chadd  */
128216ca234SAdrian Chadd int
129216ca234SAdrian Chadd ath_lna_div_detach(struct ath_softc *sc)
130216ca234SAdrian Chadd {
131216ca234SAdrian Chadd 	if (sc->sc_lna_div != NULL) {
132216ca234SAdrian Chadd 		free(sc->sc_lna_div, M_TEMP);
133216ca234SAdrian Chadd 		sc->sc_lna_div = NULL;
134216ca234SAdrian Chadd 	}
135216ca234SAdrian Chadd 	sc->sc_dolnadiv = 0;
136216ca234SAdrian Chadd 	return (0);
137216ca234SAdrian Chadd }
138216ca234SAdrian Chadd 
139216ca234SAdrian Chadd /*
140216ca234SAdrian Chadd  * Enable LNA diversity on the current channel if it's required.
141216ca234SAdrian Chadd  */
142216ca234SAdrian Chadd int
143216ca234SAdrian Chadd ath_lna_div_enable(struct ath_softc *sc, const struct ieee80211_channel *chan)
144216ca234SAdrian Chadd {
145216ca234SAdrian Chadd 
146216ca234SAdrian Chadd 	return (0);
147216ca234SAdrian Chadd }
148216ca234SAdrian Chadd 
149216ca234SAdrian Chadd /*
150216ca234SAdrian Chadd  * Handle ioctl requests from the diagnostic interface.
151216ca234SAdrian Chadd  *
152216ca234SAdrian Chadd  * The initial part of this code resembles ath_ioctl_diag();
153216ca234SAdrian Chadd  * it's likely a good idea to reduce duplication between
154216ca234SAdrian Chadd  * these two routines.
155216ca234SAdrian Chadd  */
156216ca234SAdrian Chadd int
157216ca234SAdrian Chadd ath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad)
158216ca234SAdrian Chadd {
159216ca234SAdrian Chadd 	unsigned int id = ad->ad_id & ATH_DIAG_ID;
160216ca234SAdrian Chadd 	void *indata = NULL;
161216ca234SAdrian Chadd 	void *outdata = NULL;
162216ca234SAdrian Chadd 	u_int32_t insize = ad->ad_in_size;
163216ca234SAdrian Chadd 	u_int32_t outsize = ad->ad_out_size;
164216ca234SAdrian Chadd 	int error = 0;
165216ca234SAdrian Chadd //	int val;
166216ca234SAdrian Chadd 
167216ca234SAdrian Chadd 	if (ad->ad_id & ATH_DIAG_IN) {
168216ca234SAdrian Chadd 		/*
169216ca234SAdrian Chadd 		 * Copy in data.
170216ca234SAdrian Chadd 		 */
171216ca234SAdrian Chadd 		indata = malloc(insize, M_TEMP, M_NOWAIT);
172216ca234SAdrian Chadd 		if (indata == NULL) {
173216ca234SAdrian Chadd 			error = ENOMEM;
174216ca234SAdrian Chadd 			goto bad;
175216ca234SAdrian Chadd 		}
176216ca234SAdrian Chadd 		error = copyin(ad->ad_in_data, indata, insize);
177216ca234SAdrian Chadd 		if (error)
178216ca234SAdrian Chadd 			goto bad;
179216ca234SAdrian Chadd 	}
180216ca234SAdrian Chadd 	if (ad->ad_id & ATH_DIAG_DYN) {
181216ca234SAdrian Chadd 		/*
182216ca234SAdrian Chadd 		 * Allocate a buffer for the results (otherwise the HAL
183216ca234SAdrian Chadd 		 * returns a pointer to a buffer where we can read the
184216ca234SAdrian Chadd 		 * results).  Note that we depend on the HAL leaving this
185216ca234SAdrian Chadd 		 * pointer for us to use below in reclaiming the buffer;
186216ca234SAdrian Chadd 		 * may want to be more defensive.
187216ca234SAdrian Chadd 		 */
188216ca234SAdrian Chadd 		outdata = malloc(outsize, M_TEMP, M_NOWAIT);
189216ca234SAdrian Chadd 		if (outdata == NULL) {
190216ca234SAdrian Chadd 			error = ENOMEM;
191216ca234SAdrian Chadd 			goto bad;
192216ca234SAdrian Chadd 		}
193216ca234SAdrian Chadd 	}
194216ca234SAdrian Chadd 	switch (id) {
195216ca234SAdrian Chadd 		default:
196216ca234SAdrian Chadd 			error = EINVAL;
197216ca234SAdrian Chadd 	}
198216ca234SAdrian Chadd 	if (outsize < ad->ad_out_size)
199216ca234SAdrian Chadd 		ad->ad_out_size = outsize;
200216ca234SAdrian Chadd 	if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
201216ca234SAdrian Chadd 		error = EFAULT;
202216ca234SAdrian Chadd bad:
203216ca234SAdrian Chadd 	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
204216ca234SAdrian Chadd 		free(indata, M_TEMP);
205216ca234SAdrian Chadd 	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
206216ca234SAdrian Chadd 		free(outdata, M_TEMP);
207216ca234SAdrian Chadd 	return (error);
208216ca234SAdrian Chadd }
209216ca234SAdrian Chadd 
210216ca234SAdrian Chadd static HAL_BOOL
211216ca234SAdrian Chadd ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta,
212216ca234SAdrian Chadd     int main_rssi_avg, int alt_rssi_avg, int pkt_count)
213216ca234SAdrian Chadd {
214216ca234SAdrian Chadd 	return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
215216ca234SAdrian Chadd 		(alt_rssi_avg > main_rssi_avg + maxdelta)) ||
216216ca234SAdrian Chadd 		(alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
217216ca234SAdrian Chadd }
218216ca234SAdrian Chadd 
219216ca234SAdrian Chadd static void
220216ca234SAdrian Chadd ath_lnaconf_alt_good_scan(struct if_ath_ant_comb_state *antcomb,
221216ca234SAdrian Chadd     HAL_ANT_COMB_CONFIG *ant_conf, int main_rssi_avg)
222216ca234SAdrian Chadd {
223216ca234SAdrian Chadd 	antcomb->quick_scan_cnt = 0;
224216ca234SAdrian Chadd 
225216ca234SAdrian Chadd 	if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA2)
226216ca234SAdrian Chadd 		antcomb->rssi_lna2 = main_rssi_avg;
227216ca234SAdrian Chadd 	else if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA1)
228216ca234SAdrian Chadd 		antcomb->rssi_lna1 = main_rssi_avg;
229216ca234SAdrian Chadd 
230216ca234SAdrian Chadd 	switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
231216ca234SAdrian Chadd 	case (0x10): /* LNA2 A-B */
232216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
233216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
234216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
235216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1;
236216ca234SAdrian Chadd 		break;
237216ca234SAdrian Chadd 	case (0x20): /* LNA1 A-B */
238216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
239216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
240216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
241216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2;
242216ca234SAdrian Chadd 		break;
243216ca234SAdrian Chadd 	case (0x21): /* LNA1 LNA2 */
244216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA2;
245216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
246216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
247216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf =
248216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
249216ca234SAdrian Chadd 		break;
250216ca234SAdrian Chadd 	case (0x12): /* LNA2 LNA1 */
251216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1;
252216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
253216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
254216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf =
255216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
256216ca234SAdrian Chadd 		break;
257216ca234SAdrian Chadd 	case (0x13): /* LNA2 A+B */
258216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
259216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
260216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
261216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1;
262216ca234SAdrian Chadd 		break;
263216ca234SAdrian Chadd 	case (0x23): /* LNA1 A+B */
264216ca234SAdrian Chadd 		antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
265216ca234SAdrian Chadd 		antcomb->first_quick_scan_conf =
266216ca234SAdrian Chadd 			HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
267216ca234SAdrian Chadd 		antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2;
268216ca234SAdrian Chadd 		break;
269216ca234SAdrian Chadd 	default:
270216ca234SAdrian Chadd 		break;
271216ca234SAdrian Chadd 	}
272216ca234SAdrian Chadd }
273216ca234SAdrian Chadd 
274216ca234SAdrian Chadd static void
275216ca234SAdrian Chadd ath_select_ant_div_from_quick_scan(struct if_ath_ant_comb_state *antcomb,
276216ca234SAdrian Chadd     HAL_ANT_COMB_CONFIG *div_ant_conf, int main_rssi_avg,
277216ca234SAdrian Chadd     int alt_rssi_avg, int alt_ratio)
278216ca234SAdrian Chadd {
279216ca234SAdrian Chadd 	/* alt_good */
280216ca234SAdrian Chadd 	switch (antcomb->quick_scan_cnt) {
281216ca234SAdrian Chadd 	case 0:
282216ca234SAdrian Chadd 		/* set alt to main, and alt to first conf */
283216ca234SAdrian Chadd 		div_ant_conf->main_lna_conf = antcomb->main_conf;
284216ca234SAdrian Chadd 		div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
285216ca234SAdrian Chadd 		break;
286216ca234SAdrian Chadd 	case 1:
287216ca234SAdrian Chadd 		/* set alt to main, and alt to first conf */
288216ca234SAdrian Chadd 		div_ant_conf->main_lna_conf = antcomb->main_conf;
289216ca234SAdrian Chadd 		div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
290216ca234SAdrian Chadd 		antcomb->rssi_first = main_rssi_avg;
291216ca234SAdrian Chadd 		antcomb->rssi_second = alt_rssi_avg;
292216ca234SAdrian Chadd 
293216ca234SAdrian Chadd 		if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) {
294216ca234SAdrian Chadd 			/* main is LNA1 */
295216ca234SAdrian Chadd 			if (ath_is_alt_ant_ratio_better(alt_ratio,
296216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
297216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
298216ca234SAdrian Chadd 						main_rssi_avg, alt_rssi_avg,
299216ca234SAdrian Chadd 						antcomb->total_pkt_count))
300216ca234SAdrian Chadd 				antcomb->first_ratio = AH_TRUE;
301216ca234SAdrian Chadd 			else
302216ca234SAdrian Chadd 				antcomb->first_ratio = AH_FALSE;
303216ca234SAdrian Chadd 		} else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) {
304216ca234SAdrian Chadd 			if (ath_is_alt_ant_ratio_better(alt_ratio,
305216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
306216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
307216ca234SAdrian Chadd 						main_rssi_avg, alt_rssi_avg,
308216ca234SAdrian Chadd 						antcomb->total_pkt_count))
309216ca234SAdrian Chadd 				antcomb->first_ratio = AH_TRUE;
310216ca234SAdrian Chadd 			else
311216ca234SAdrian Chadd 				antcomb->first_ratio = AH_FALSE;
312216ca234SAdrian Chadd 		} else {
313216ca234SAdrian Chadd 			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
314216ca234SAdrian Chadd 			    (alt_rssi_avg > main_rssi_avg +
315216ca234SAdrian Chadd 			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
316216ca234SAdrian Chadd 			    (alt_rssi_avg > main_rssi_avg)) &&
317216ca234SAdrian Chadd 			    (antcomb->total_pkt_count > 50))
318216ca234SAdrian Chadd 				antcomb->first_ratio = AH_TRUE;
319216ca234SAdrian Chadd 			else
320216ca234SAdrian Chadd 				antcomb->first_ratio = AH_FALSE;
321216ca234SAdrian Chadd 		}
322216ca234SAdrian Chadd 		break;
323216ca234SAdrian Chadd 	case 2:
324216ca234SAdrian Chadd 		antcomb->alt_good = AH_FALSE;
325216ca234SAdrian Chadd 		antcomb->scan_not_start = AH_FALSE;
326216ca234SAdrian Chadd 		antcomb->scan = AH_FALSE;
327216ca234SAdrian Chadd 		antcomb->rssi_first = main_rssi_avg;
328216ca234SAdrian Chadd 		antcomb->rssi_third = alt_rssi_avg;
329216ca234SAdrian Chadd 
330216ca234SAdrian Chadd 		if (antcomb->second_quick_scan_conf == HAL_ANT_DIV_COMB_LNA1)
331216ca234SAdrian Chadd 			antcomb->rssi_lna1 = alt_rssi_avg;
332216ca234SAdrian Chadd 		else if (antcomb->second_quick_scan_conf ==
333216ca234SAdrian Chadd 			 HAL_ANT_DIV_COMB_LNA2)
334216ca234SAdrian Chadd 			antcomb->rssi_lna2 = alt_rssi_avg;
335216ca234SAdrian Chadd 		else if (antcomb->second_quick_scan_conf ==
336216ca234SAdrian Chadd 			 HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
337216ca234SAdrian Chadd 			if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2)
338216ca234SAdrian Chadd 				antcomb->rssi_lna2 = main_rssi_avg;
339216ca234SAdrian Chadd 			else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1)
340216ca234SAdrian Chadd 				antcomb->rssi_lna1 = main_rssi_avg;
341216ca234SAdrian Chadd 		}
342216ca234SAdrian Chadd 
343216ca234SAdrian Chadd 		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
344216ca234SAdrian Chadd 		    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
345216ca234SAdrian Chadd 			div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA2;
346216ca234SAdrian Chadd 		else
347216ca234SAdrian Chadd 			div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA1;
348216ca234SAdrian Chadd 
349216ca234SAdrian Chadd 		if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) {
350216ca234SAdrian Chadd 			if (ath_is_alt_ant_ratio_better(alt_ratio,
351216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
352216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
353216ca234SAdrian Chadd 						main_rssi_avg, alt_rssi_avg,
354216ca234SAdrian Chadd 						antcomb->total_pkt_count))
355216ca234SAdrian Chadd 				antcomb->second_ratio = AH_TRUE;
356216ca234SAdrian Chadd 			else
357216ca234SAdrian Chadd 				antcomb->second_ratio = AH_FALSE;
358216ca234SAdrian Chadd 		} else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) {
359216ca234SAdrian Chadd 			if (ath_is_alt_ant_ratio_better(alt_ratio,
360216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
361216ca234SAdrian Chadd 						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
362216ca234SAdrian Chadd 						main_rssi_avg, alt_rssi_avg,
363216ca234SAdrian Chadd 						antcomb->total_pkt_count))
364216ca234SAdrian Chadd 				antcomb->second_ratio = AH_TRUE;
365216ca234SAdrian Chadd 			else
366216ca234SAdrian Chadd 				antcomb->second_ratio = AH_FALSE;
367216ca234SAdrian Chadd 		} else {
368216ca234SAdrian Chadd 			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
369216ca234SAdrian Chadd 			    (alt_rssi_avg > main_rssi_avg +
370216ca234SAdrian Chadd 			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
371216ca234SAdrian Chadd 			    (alt_rssi_avg > main_rssi_avg)) &&
372216ca234SAdrian Chadd 			    (antcomb->total_pkt_count > 50))
373216ca234SAdrian Chadd 				antcomb->second_ratio = AH_TRUE;
374216ca234SAdrian Chadd 			else
375216ca234SAdrian Chadd 				antcomb->second_ratio = AH_FALSE;
376216ca234SAdrian Chadd 		}
377216ca234SAdrian Chadd 
378216ca234SAdrian Chadd 		/* set alt to the conf with maximun ratio */
379216ca234SAdrian Chadd 		if (antcomb->first_ratio && antcomb->second_ratio) {
380216ca234SAdrian Chadd 			if (antcomb->rssi_second > antcomb->rssi_third) {
381216ca234SAdrian Chadd 				/* first alt*/
382216ca234SAdrian Chadd 				if ((antcomb->first_quick_scan_conf ==
383216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA1) ||
384216ca234SAdrian Chadd 				    (antcomb->first_quick_scan_conf ==
385216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA2))
386216ca234SAdrian Chadd 					/* Set alt LNA1 or LNA2*/
387216ca234SAdrian Chadd 					if (div_ant_conf->main_lna_conf ==
388216ca234SAdrian Chadd 					    HAL_ANT_DIV_COMB_LNA2)
389216ca234SAdrian Chadd 						div_ant_conf->alt_lna_conf =
390216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA1;
391216ca234SAdrian Chadd 					else
392216ca234SAdrian Chadd 						div_ant_conf->alt_lna_conf =
393216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA2;
394216ca234SAdrian Chadd 				else
395216ca234SAdrian Chadd 					/* Set alt to A+B or A-B */
396216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
397216ca234SAdrian Chadd 						antcomb->first_quick_scan_conf;
398216ca234SAdrian Chadd 			} else if ((antcomb->second_quick_scan_conf ==
399216ca234SAdrian Chadd 				   HAL_ANT_DIV_COMB_LNA1) ||
400216ca234SAdrian Chadd 				   (antcomb->second_quick_scan_conf ==
401216ca234SAdrian Chadd 				   HAL_ANT_DIV_COMB_LNA2)) {
402216ca234SAdrian Chadd 				/* Set alt LNA1 or LNA2 */
403216ca234SAdrian Chadd 				if (div_ant_conf->main_lna_conf ==
404216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA2)
405216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
406216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
407216ca234SAdrian Chadd 				else
408216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
409216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
410216ca234SAdrian Chadd 			} else {
411216ca234SAdrian Chadd 				/* Set alt to A+B or A-B */
412216ca234SAdrian Chadd 				div_ant_conf->alt_lna_conf =
413216ca234SAdrian Chadd 					antcomb->second_quick_scan_conf;
414216ca234SAdrian Chadd 			}
415216ca234SAdrian Chadd 		} else if (antcomb->first_ratio) {
416216ca234SAdrian Chadd 			/* first alt */
417216ca234SAdrian Chadd 			if ((antcomb->first_quick_scan_conf ==
418216ca234SAdrian Chadd 			    HAL_ANT_DIV_COMB_LNA1) ||
419216ca234SAdrian Chadd 			    (antcomb->first_quick_scan_conf ==
420216ca234SAdrian Chadd 			    HAL_ANT_DIV_COMB_LNA2))
421216ca234SAdrian Chadd 					/* Set alt LNA1 or LNA2 */
422216ca234SAdrian Chadd 				if (div_ant_conf->main_lna_conf ==
423216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA2)
424216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
425216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA1;
426216ca234SAdrian Chadd 				else
427216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
428216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA2;
429216ca234SAdrian Chadd 			else
430216ca234SAdrian Chadd 				/* Set alt to A+B or A-B */
431216ca234SAdrian Chadd 				div_ant_conf->alt_lna_conf =
432216ca234SAdrian Chadd 						antcomb->first_quick_scan_conf;
433216ca234SAdrian Chadd 		} else if (antcomb->second_ratio) {
434216ca234SAdrian Chadd 				/* second alt */
435216ca234SAdrian Chadd 			if ((antcomb->second_quick_scan_conf ==
436216ca234SAdrian Chadd 			    HAL_ANT_DIV_COMB_LNA1) ||
437216ca234SAdrian Chadd 			    (antcomb->second_quick_scan_conf ==
438216ca234SAdrian Chadd 			    HAL_ANT_DIV_COMB_LNA2))
439216ca234SAdrian Chadd 				/* Set alt LNA1 or LNA2 */
440216ca234SAdrian Chadd 				if (div_ant_conf->main_lna_conf ==
441216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA2)
442216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
443216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
444216ca234SAdrian Chadd 				else
445216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
446216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
447216ca234SAdrian Chadd 			else
448216ca234SAdrian Chadd 				/* Set alt to A+B or A-B */
449216ca234SAdrian Chadd 				div_ant_conf->alt_lna_conf =
450216ca234SAdrian Chadd 						antcomb->second_quick_scan_conf;
451216ca234SAdrian Chadd 		} else {
452216ca234SAdrian Chadd 			/* main is largest */
453216ca234SAdrian Chadd 			if ((antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) ||
454216ca234SAdrian Chadd 			    (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2))
455216ca234SAdrian Chadd 				/* Set alt LNA1 or LNA2 */
456216ca234SAdrian Chadd 				if (div_ant_conf->main_lna_conf ==
457216ca234SAdrian Chadd 				    HAL_ANT_DIV_COMB_LNA2)
458216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
459216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA1;
460216ca234SAdrian Chadd 				else
461216ca234SAdrian Chadd 					div_ant_conf->alt_lna_conf =
462216ca234SAdrian Chadd 							HAL_ANT_DIV_COMB_LNA2;
463216ca234SAdrian Chadd 			else
464216ca234SAdrian Chadd 				/* Set alt to A+B or A-B */
465216ca234SAdrian Chadd 				div_ant_conf->alt_lna_conf = antcomb->main_conf;
466216ca234SAdrian Chadd 		}
467216ca234SAdrian Chadd 		break;
468216ca234SAdrian Chadd 	default:
469216ca234SAdrian Chadd 		break;
470216ca234SAdrian Chadd 	}
471216ca234SAdrian Chadd }
472216ca234SAdrian Chadd 
473216ca234SAdrian Chadd static void
474*0f0eebe7SAdrian Chadd ath_ant_adjust_fast_divbias(struct if_ath_ant_comb_state *antcomb,
475*0f0eebe7SAdrian Chadd     int alt_ratio, int alt_ant_ratio_th, u_int config_group,
476*0f0eebe7SAdrian Chadd     HAL_ANT_COMB_CONFIG *pdiv_ant_conf)
477216ca234SAdrian Chadd {
478*0f0eebe7SAdrian Chadd 
479*0f0eebe7SAdrian Chadd 	if (config_group == HAL_ANTDIV_CONFIG_GROUP_1) {
480*0f0eebe7SAdrian Chadd 		switch ((pdiv_ant_conf->main_lna_conf << 4)
481*0f0eebe7SAdrian Chadd 		    | pdiv_ant_conf->alt_lna_conf) {
482*0f0eebe7SAdrian Chadd 		case (0x01): //A-B LNA2
483*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
484*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
485*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
486216ca234SAdrian Chadd 			break;
487*0f0eebe7SAdrian Chadd 		case (0x02): //A-B LNA1
488*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
489*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
490*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
491216ca234SAdrian Chadd 			break;
492*0f0eebe7SAdrian Chadd 		case (0x03): //A-B A+B
493*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
494*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
495*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
496216ca234SAdrian Chadd 			break;
497*0f0eebe7SAdrian Chadd 		case (0x10): //LNA2 A-B
498*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
499*0f0eebe7SAdrian Chadd 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
500*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x3f;
501*0f0eebe7SAdrian Chadd 			} else {
502*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
503*0f0eebe7SAdrian Chadd 			}
504*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
505*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
506216ca234SAdrian Chadd 			break;
507*0f0eebe7SAdrian Chadd 		case (0x12): //LNA2 LNA1
508*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
509*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
510*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
511216ca234SAdrian Chadd 			break;
512*0f0eebe7SAdrian Chadd 			case (0x13): //LNA2 A+B
513*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
514*0f0eebe7SAdrian Chadd 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
515*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x3f;
516*0f0eebe7SAdrian Chadd 			} else {
517*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
518*0f0eebe7SAdrian Chadd 			}
519*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
520*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
521216ca234SAdrian Chadd 			break;
522*0f0eebe7SAdrian Chadd 		case (0x20): //LNA1 A-B
523*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
524*0f0eebe7SAdrian Chadd 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
525*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x3f;
526*0f0eebe7SAdrian Chadd 			} else {
527*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
528*0f0eebe7SAdrian Chadd 			}
529*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
530*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
531216ca234SAdrian Chadd 			break;
532*0f0eebe7SAdrian Chadd 		case (0x21): //LNA1 LNA2
533*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
534*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
535*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
536216ca234SAdrian Chadd 			break;
537*0f0eebe7SAdrian Chadd 		case (0x23): //LNA1 A+B
538*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
539*0f0eebe7SAdrian Chadd 			    && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
540*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x3f;
541*0f0eebe7SAdrian Chadd 			} else {
542*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
543*0f0eebe7SAdrian Chadd 			}
544*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
545*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
546216ca234SAdrian Chadd 			break;
547*0f0eebe7SAdrian Chadd 		case (0x30): //A+B A-B
548*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
549*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
550*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
551216ca234SAdrian Chadd 			break;
552*0f0eebe7SAdrian Chadd 		case (0x31): //A+B LNA2
553*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
554*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
555*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
556216ca234SAdrian Chadd 			break;
557*0f0eebe7SAdrian Chadd 		case (0x32): //A+B LNA1
558*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
559*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
560*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
561*0f0eebe7SAdrian Chadd 			break;
562*0f0eebe7SAdrian Chadd 		default:
563*0f0eebe7SAdrian Chadd 			break;
564*0f0eebe7SAdrian Chadd 		}
565*0f0eebe7SAdrian Chadd 	} else if (config_group == HAL_ANTDIV_CONFIG_GROUP_2) {
566*0f0eebe7SAdrian Chadd 		switch ((pdiv_ant_conf->main_lna_conf << 4)
567*0f0eebe7SAdrian Chadd 		    | pdiv_ant_conf->alt_lna_conf) {
568*0f0eebe7SAdrian Chadd 		case (0x01): //A-B LNA2
569*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
570*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
571*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
572*0f0eebe7SAdrian Chadd 			break;
573*0f0eebe7SAdrian Chadd 		case (0x02): //A-B LNA1
574*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
575*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
576*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
577*0f0eebe7SAdrian Chadd 			break;
578*0f0eebe7SAdrian Chadd 		case (0x03): //A-B A+B
579*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
580*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
581*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
582*0f0eebe7SAdrian Chadd 			break;
583*0f0eebe7SAdrian Chadd 		case (0x10): //LNA2 A-B
584*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
585*0f0eebe7SAdrian Chadd 			    && (alt_ratio > alt_ant_ratio_th)) {
586*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
587*0f0eebe7SAdrian Chadd 			} else {
588*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x2;
589*0f0eebe7SAdrian Chadd 			}
590*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
591*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
592*0f0eebe7SAdrian Chadd 			break;
593*0f0eebe7SAdrian Chadd 		case (0x12): //LNA2 LNA1
594*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
595*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
596*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
597*0f0eebe7SAdrian Chadd 			break;
598*0f0eebe7SAdrian Chadd 		case (0x13): //LNA2 A+B
599*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
600*0f0eebe7SAdrian Chadd 			    && (alt_ratio > alt_ant_ratio_th)) {
601*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
602*0f0eebe7SAdrian Chadd 			} else {
603*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x2;
604*0f0eebe7SAdrian Chadd 			}
605*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
606*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
607*0f0eebe7SAdrian Chadd 			break;
608*0f0eebe7SAdrian Chadd 		case (0x20): //LNA1 A-B
609*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
610*0f0eebe7SAdrian Chadd 			    && (alt_ratio > alt_ant_ratio_th)) {
611*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
612*0f0eebe7SAdrian Chadd 			} else {
613*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x2;
614*0f0eebe7SAdrian Chadd 			}
615*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
616*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
617*0f0eebe7SAdrian Chadd 			break;
618*0f0eebe7SAdrian Chadd 		case (0x21): //LNA1 LNA2
619*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
620*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
621*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
622*0f0eebe7SAdrian Chadd 			break;
623*0f0eebe7SAdrian Chadd 		case (0x23): //LNA1 A+B
624*0f0eebe7SAdrian Chadd 			if ((antcomb->scan == 0)
625*0f0eebe7SAdrian Chadd 			    && (alt_ratio > alt_ant_ratio_th)) {
626*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x1;
627*0f0eebe7SAdrian Chadd 			} else {
628*0f0eebe7SAdrian Chadd 				pdiv_ant_conf->fast_div_bias = 0x2;
629*0f0eebe7SAdrian Chadd 			}
630*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
631*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
632*0f0eebe7SAdrian Chadd 			break;
633*0f0eebe7SAdrian Chadd 		case (0x30): //A+B A-B
634*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
635*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
636*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
637*0f0eebe7SAdrian Chadd 			break;
638*0f0eebe7SAdrian Chadd 		case (0x31): //A+B LNA2
639*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
640*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
641*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
642*0f0eebe7SAdrian Chadd 			break;
643*0f0eebe7SAdrian Chadd 		case (0x32): //A+B LNA1
644*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
645*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->main_gaintb   = 0;
646*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->alt_gaintb    = 0;
647*0f0eebe7SAdrian Chadd 			break;
648*0f0eebe7SAdrian Chadd 		default:
649*0f0eebe7SAdrian Chadd 			break;
650*0f0eebe7SAdrian Chadd 		}
651*0f0eebe7SAdrian Chadd 	} else { /* DEFAULT_ANTDIV_CONFIG_GROUP */
652*0f0eebe7SAdrian Chadd 		switch ((pdiv_ant_conf->main_lna_conf << 4) | pdiv_ant_conf->alt_lna_conf) {
653*0f0eebe7SAdrian Chadd 		case (0x01): //A-B LNA2
654*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x3b;
655*0f0eebe7SAdrian Chadd 			break;
656*0f0eebe7SAdrian Chadd 		case (0x02): //A-B LNA1
657*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x3d;
658*0f0eebe7SAdrian Chadd 			break;
659*0f0eebe7SAdrian Chadd 		case (0x03): //A-B A+B
660*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
661*0f0eebe7SAdrian Chadd 			break;
662*0f0eebe7SAdrian Chadd 		case (0x10): //LNA2 A-B
663*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x7;
664*0f0eebe7SAdrian Chadd 			break;
665*0f0eebe7SAdrian Chadd 		case (0x12): //LNA2 LNA1
666*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x2;
667*0f0eebe7SAdrian Chadd 			break;
668*0f0eebe7SAdrian Chadd 		case (0x13): //LNA2 A+B
669*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x7;
670*0f0eebe7SAdrian Chadd 			break;
671*0f0eebe7SAdrian Chadd 		case (0x20): //LNA1 A-B
672*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x6;
673*0f0eebe7SAdrian Chadd 			break;
674*0f0eebe7SAdrian Chadd 		case (0x21): //LNA1 LNA2
675*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x0;
676*0f0eebe7SAdrian Chadd 			break;
677*0f0eebe7SAdrian Chadd 		case (0x23): //LNA1 A+B
678*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x6;
679*0f0eebe7SAdrian Chadd 			break;
680*0f0eebe7SAdrian Chadd 		case (0x30): //A+B A-B
681*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x1;
682*0f0eebe7SAdrian Chadd 			break;
683*0f0eebe7SAdrian Chadd 		case (0x31): //A+B LNA2
684*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x3b;
685*0f0eebe7SAdrian Chadd 			break;
686*0f0eebe7SAdrian Chadd 		case (0x32): //A+B LNA1
687*0f0eebe7SAdrian Chadd 			pdiv_ant_conf->fast_div_bias = 0x3d;
688216ca234SAdrian Chadd 			break;
689216ca234SAdrian Chadd 		default:
690216ca234SAdrian Chadd 			break;
691216ca234SAdrian Chadd 		}
692216ca234SAdrian Chadd 	}
693*0f0eebe7SAdrian Chadd }
694*0f0eebe7SAdrian Chadd 
695*0f0eebe7SAdrian Chadd /*
696*0f0eebe7SAdrian Chadd  * AR9485/AR933x TODO:
697*0f0eebe7SAdrian Chadd  * + Select a ratio based on whether RSSI is low or not; but I need
698*0f0eebe7SAdrian Chadd  *   to figure out what "low_rssi_th" is sourced from.
699*0f0eebe7SAdrian Chadd  * + What's ath_ant_div_comb_alt_check() in the reference driver do?
700*0f0eebe7SAdrian Chadd  * + .. and there's likely a bunch of other things to include in this.
701*0f0eebe7SAdrian Chadd  */
702216ca234SAdrian Chadd 
703216ca234SAdrian Chadd /* Antenna diversity and combining */
704216ca234SAdrian Chadd void
705216ca234SAdrian Chadd ath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs,
706216ca234SAdrian Chadd     unsigned long ticks, int hz)
707216ca234SAdrian Chadd {
708216ca234SAdrian Chadd 	HAL_ANT_COMB_CONFIG div_ant_conf;
709216ca234SAdrian Chadd 	struct if_ath_ant_comb_state *antcomb = sc->sc_lna_div;
710216ca234SAdrian Chadd 	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
711216ca234SAdrian Chadd 	int curr_main_set, curr_bias;
712216ca234SAdrian Chadd 	int main_rssi = rs->rs_rssi_ctl[0];
713216ca234SAdrian Chadd 	int alt_rssi = rs->rs_rssi_ctl[1];
714216ca234SAdrian Chadd 	int rx_ant_conf, main_ant_conf, alt_ant_conf;
715216ca234SAdrian Chadd 	HAL_BOOL short_scan = AH_FALSE;
716216ca234SAdrian Chadd 
717216ca234SAdrian Chadd 	rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK;
718216ca234SAdrian Chadd 	main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK;
719216ca234SAdrian Chadd 	alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK;
720216ca234SAdrian Chadd 
721216ca234SAdrian Chadd #if 0
722216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY,
723216ca234SAdrian Chadd 	    "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; "
724216ca234SAdrian Chadd 	    "FastDiv: %d\n",
725216ca234SAdrian Chadd 	    __func__,
726216ca234SAdrian Chadd 	    main_rssi,
727216ca234SAdrian Chadd 	    alt_rssi,
728216ca234SAdrian Chadd 	    main_ant_conf,
729216ca234SAdrian Chadd 	    alt_ant_conf,
730216ca234SAdrian Chadd 	    rx_ant_conf,
731216ca234SAdrian Chadd 	    !!(rs->rs_rssi_ctl[2] & 0x80),
732216ca234SAdrian Chadd 	    !!(rs->rs_rssi_ctl[2] & 0x40),
733216ca234SAdrian Chadd 	    !!(rs->rs_rssi_ext[2] & 0x40));
734216ca234SAdrian Chadd #endif
735216ca234SAdrian Chadd 
736216ca234SAdrian Chadd 	/*
737216ca234SAdrian Chadd 	 * If LNA diversity combining isn't enabled, don't run this.
738216ca234SAdrian Chadd 	 */
739216ca234SAdrian Chadd 	if (! sc->sc_dolnadiv)
740216ca234SAdrian Chadd 		return;
741216ca234SAdrian Chadd 
742216ca234SAdrian Chadd 	/*
743216ca234SAdrian Chadd 	 * XXX this is ugly, but the HAL code attaches the
744216ca234SAdrian Chadd 	 * LNA diversity to the TX antenna settings.
745216ca234SAdrian Chadd 	 * I don't know why.
746216ca234SAdrian Chadd 	 */
747216ca234SAdrian Chadd 	if (sc->sc_txantenna != HAL_ANT_VARIABLE)
748216ca234SAdrian Chadd 		return;
749216ca234SAdrian Chadd 
750216ca234SAdrian Chadd 	/* Record packet only when alt_rssi is positive */
751216ca234SAdrian Chadd 	if (main_rssi > 0 && alt_rssi > 0) {
752216ca234SAdrian Chadd 		antcomb->total_pkt_count++;
753216ca234SAdrian Chadd 		antcomb->main_total_rssi += main_rssi;
754216ca234SAdrian Chadd 		antcomb->alt_total_rssi  += alt_rssi;
755216ca234SAdrian Chadd 		if (main_ant_conf == rx_ant_conf)
756216ca234SAdrian Chadd 			antcomb->main_recv_cnt++;
757216ca234SAdrian Chadd 		else
758216ca234SAdrian Chadd 			antcomb->alt_recv_cnt++;
759216ca234SAdrian Chadd 	}
760216ca234SAdrian Chadd 
761216ca234SAdrian Chadd 	/* Short scan check */
762216ca234SAdrian Chadd 	if (antcomb->scan && antcomb->alt_good) {
763216ca234SAdrian Chadd 		if (time_after(ticks, antcomb->scan_start_time +
764216ca234SAdrian Chadd 		    msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
765216ca234SAdrian Chadd 			short_scan = AH_TRUE;
766216ca234SAdrian Chadd 		else
767216ca234SAdrian Chadd 			if (antcomb->total_pkt_count ==
768216ca234SAdrian Chadd 			    ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
769216ca234SAdrian Chadd 				alt_ratio = ((antcomb->alt_recv_cnt * 100) /
770216ca234SAdrian Chadd 					    antcomb->total_pkt_count);
771216ca234SAdrian Chadd 				if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
772216ca234SAdrian Chadd 					short_scan = AH_TRUE;
773216ca234SAdrian Chadd 			}
774216ca234SAdrian Chadd 	}
775216ca234SAdrian Chadd 
776*0f0eebe7SAdrian Chadd #if 0
777*0f0eebe7SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY,
778*0f0eebe7SAdrian Chadd 	    "%s: total pkt=%d, aggr=%d, short_scan=%d\n",
779*0f0eebe7SAdrian Chadd 	    __func__,
780*0f0eebe7SAdrian Chadd 	    antcomb->total_pkt_count,
781*0f0eebe7SAdrian Chadd 	    !! (rs->rs_moreaggr),
782*0f0eebe7SAdrian Chadd 	    !! (short_scan));
783*0f0eebe7SAdrian Chadd #endif
784*0f0eebe7SAdrian Chadd 
785216ca234SAdrian Chadd 	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
786216ca234SAdrian Chadd 	    rs->rs_moreaggr) && !short_scan)
787216ca234SAdrian Chadd 		return;
788216ca234SAdrian Chadd 
789216ca234SAdrian Chadd 	if (antcomb->total_pkt_count) {
790216ca234SAdrian Chadd 		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
791216ca234SAdrian Chadd 			     antcomb->total_pkt_count);
792216ca234SAdrian Chadd 		main_rssi_avg = (antcomb->main_total_rssi /
793216ca234SAdrian Chadd 				 antcomb->total_pkt_count);
794216ca234SAdrian Chadd 		alt_rssi_avg = (antcomb->alt_total_rssi /
795216ca234SAdrian Chadd 				 antcomb->total_pkt_count);
796216ca234SAdrian Chadd 	}
797216ca234SAdrian Chadd 
798216ca234SAdrian Chadd 	OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf));
799216ca234SAdrian Chadd 
800216ca234SAdrian Chadd 	ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf);
801216ca234SAdrian Chadd 	curr_alt_set = div_ant_conf.alt_lna_conf;
802216ca234SAdrian Chadd 	curr_main_set = div_ant_conf.main_lna_conf;
803216ca234SAdrian Chadd 	curr_bias = div_ant_conf.fast_div_bias;
804216ca234SAdrian Chadd 
805216ca234SAdrian Chadd 	antcomb->count++;
806216ca234SAdrian Chadd 
807216ca234SAdrian Chadd 	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
808216ca234SAdrian Chadd 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
809216ca234SAdrian Chadd 			ath_lnaconf_alt_good_scan(antcomb, &div_ant_conf,
810216ca234SAdrian Chadd 						  main_rssi_avg);
811216ca234SAdrian Chadd 			antcomb->alt_good = AH_TRUE;
812216ca234SAdrian Chadd 		} else {
813216ca234SAdrian Chadd 			antcomb->alt_good = AH_FALSE;
814216ca234SAdrian Chadd 		}
815216ca234SAdrian Chadd 
816216ca234SAdrian Chadd 		antcomb->count = 0;
817216ca234SAdrian Chadd 		antcomb->scan = AH_TRUE;
818216ca234SAdrian Chadd 		antcomb->scan_not_start = AH_TRUE;
819216ca234SAdrian Chadd 	}
820216ca234SAdrian Chadd 
821216ca234SAdrian Chadd 	if (!antcomb->scan) {
822216ca234SAdrian Chadd 		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
823216ca234SAdrian Chadd 			if (curr_alt_set == HAL_ANT_DIV_COMB_LNA2) {
824216ca234SAdrian Chadd 				/* Switch main and alt LNA */
825216ca234SAdrian Chadd 				div_ant_conf.main_lna_conf =
826216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
827216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf  =
828216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
829216ca234SAdrian Chadd 			} else if (curr_alt_set == HAL_ANT_DIV_COMB_LNA1) {
830216ca234SAdrian Chadd 				div_ant_conf.main_lna_conf =
831216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
832216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf  =
833216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
834216ca234SAdrian Chadd 			}
835216ca234SAdrian Chadd 
836216ca234SAdrian Chadd 			goto div_comb_done;
837216ca234SAdrian Chadd 		} else if ((curr_alt_set != HAL_ANT_DIV_COMB_LNA1) &&
838216ca234SAdrian Chadd 			   (curr_alt_set != HAL_ANT_DIV_COMB_LNA2)) {
839216ca234SAdrian Chadd 			/* Set alt to another LNA */
840216ca234SAdrian Chadd 			if (curr_main_set == HAL_ANT_DIV_COMB_LNA2)
841216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf =
842216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
843216ca234SAdrian Chadd 			else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1)
844216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf =
845216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
846216ca234SAdrian Chadd 
847216ca234SAdrian Chadd 			goto div_comb_done;
848216ca234SAdrian Chadd 		}
849216ca234SAdrian Chadd 
850216ca234SAdrian Chadd 		if ((alt_rssi_avg < (main_rssi_avg +
851*0f0eebe7SAdrian Chadd 		    antcomb->lna1_lna2_delta)))
852216ca234SAdrian Chadd 			goto div_comb_done;
853216ca234SAdrian Chadd 	}
854216ca234SAdrian Chadd 
855216ca234SAdrian Chadd 	if (!antcomb->scan_not_start) {
856216ca234SAdrian Chadd 		switch (curr_alt_set) {
857216ca234SAdrian Chadd 		case HAL_ANT_DIV_COMB_LNA2:
858216ca234SAdrian Chadd 			antcomb->rssi_lna2 = alt_rssi_avg;
859216ca234SAdrian Chadd 			antcomb->rssi_lna1 = main_rssi_avg;
860216ca234SAdrian Chadd 			antcomb->scan = AH_TRUE;
861216ca234SAdrian Chadd 			/* set to A+B */
862216ca234SAdrian Chadd 			div_ant_conf.main_lna_conf =
863216ca234SAdrian Chadd 				HAL_ANT_DIV_COMB_LNA1;
864216ca234SAdrian Chadd 			div_ant_conf.alt_lna_conf  =
865216ca234SAdrian Chadd 				HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
866216ca234SAdrian Chadd 			break;
867216ca234SAdrian Chadd 		case HAL_ANT_DIV_COMB_LNA1:
868216ca234SAdrian Chadd 			antcomb->rssi_lna1 = alt_rssi_avg;
869216ca234SAdrian Chadd 			antcomb->rssi_lna2 = main_rssi_avg;
870216ca234SAdrian Chadd 			antcomb->scan = AH_TRUE;
871216ca234SAdrian Chadd 			/* set to A+B */
872216ca234SAdrian Chadd 			div_ant_conf.main_lna_conf = HAL_ANT_DIV_COMB_LNA2;
873216ca234SAdrian Chadd 			div_ant_conf.alt_lna_conf  =
874216ca234SAdrian Chadd 				HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
875216ca234SAdrian Chadd 			break;
876216ca234SAdrian Chadd 		case HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2:
877216ca234SAdrian Chadd 			antcomb->rssi_add = alt_rssi_avg;
878216ca234SAdrian Chadd 			antcomb->scan = AH_TRUE;
879216ca234SAdrian Chadd 			/* set to A-B */
880216ca234SAdrian Chadd 			div_ant_conf.alt_lna_conf =
881216ca234SAdrian Chadd 				HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
882216ca234SAdrian Chadd 			break;
883216ca234SAdrian Chadd 		case HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2:
884216ca234SAdrian Chadd 			antcomb->rssi_sub = alt_rssi_avg;
885216ca234SAdrian Chadd 			antcomb->scan = AH_FALSE;
886216ca234SAdrian Chadd 			if (antcomb->rssi_lna2 >
887216ca234SAdrian Chadd 			    (antcomb->rssi_lna1 +
888216ca234SAdrian Chadd 			    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
889216ca234SAdrian Chadd 				/* use LNA2 as main LNA */
890216ca234SAdrian Chadd 				if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
891216ca234SAdrian Chadd 				    (antcomb->rssi_add > antcomb->rssi_sub)) {
892216ca234SAdrian Chadd 					/* set to A+B */
893216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
894216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
895216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf  =
896216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
897216ca234SAdrian Chadd 				} else if (antcomb->rssi_sub >
898216ca234SAdrian Chadd 					   antcomb->rssi_lna1) {
899216ca234SAdrian Chadd 					/* set to A-B */
900216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
901216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
902216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf =
903216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
904216ca234SAdrian Chadd 				} else {
905216ca234SAdrian Chadd 					/* set to LNA1 */
906216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
907216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
908216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf =
909216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
910216ca234SAdrian Chadd 				}
911216ca234SAdrian Chadd 			} else {
912216ca234SAdrian Chadd 				/* use LNA1 as main LNA */
913216ca234SAdrian Chadd 				if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
914216ca234SAdrian Chadd 				    (antcomb->rssi_add > antcomb->rssi_sub)) {
915216ca234SAdrian Chadd 					/* set to A+B */
916216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
917216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
918216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf  =
919216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2;
920216ca234SAdrian Chadd 				} else if (antcomb->rssi_sub >
921216ca234SAdrian Chadd 					   antcomb->rssi_lna1) {
922216ca234SAdrian Chadd 					/* set to A-B */
923216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
924216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
925216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf =
926216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2;
927216ca234SAdrian Chadd 				} else {
928216ca234SAdrian Chadd 					/* set to LNA2 */
929216ca234SAdrian Chadd 					div_ant_conf.main_lna_conf =
930216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
931216ca234SAdrian Chadd 					div_ant_conf.alt_lna_conf =
932216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
933216ca234SAdrian Chadd 				}
934216ca234SAdrian Chadd 			}
935216ca234SAdrian Chadd 			break;
936216ca234SAdrian Chadd 		default:
937216ca234SAdrian Chadd 			break;
938216ca234SAdrian Chadd 		}
939216ca234SAdrian Chadd 	} else {
940216ca234SAdrian Chadd 		if (!antcomb->alt_good) {
941216ca234SAdrian Chadd 			antcomb->scan_not_start = AH_FALSE;
942216ca234SAdrian Chadd 			/* Set alt to another LNA */
943216ca234SAdrian Chadd 			if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) {
944216ca234SAdrian Chadd 				div_ant_conf.main_lna_conf =
945216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
946216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf =
947216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
948216ca234SAdrian Chadd 			} else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) {
949216ca234SAdrian Chadd 				div_ant_conf.main_lna_conf =
950216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA1;
951216ca234SAdrian Chadd 				div_ant_conf.alt_lna_conf =
952216ca234SAdrian Chadd 						HAL_ANT_DIV_COMB_LNA2;
953216ca234SAdrian Chadd 			}
954216ca234SAdrian Chadd 			goto div_comb_done;
955216ca234SAdrian Chadd 		}
956216ca234SAdrian Chadd 	}
957216ca234SAdrian Chadd 
958216ca234SAdrian Chadd 	ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
959216ca234SAdrian Chadd 					   main_rssi_avg, alt_rssi_avg,
960216ca234SAdrian Chadd 					   alt_ratio);
961216ca234SAdrian Chadd 
962216ca234SAdrian Chadd 	antcomb->quick_scan_cnt++;
963216ca234SAdrian Chadd 
964216ca234SAdrian Chadd div_comb_done:
965*0f0eebe7SAdrian Chadd #if 0
966216ca234SAdrian Chadd 	ath_ant_div_conf_fast_divbias(&div_ant_conf);
967*0f0eebe7SAdrian Chadd #endif
968*0f0eebe7SAdrian Chadd 
969*0f0eebe7SAdrian Chadd 	ath_ant_adjust_fast_divbias(antcomb,
970*0f0eebe7SAdrian Chadd 	    alt_ratio,
971*0f0eebe7SAdrian Chadd 	    ATH_ANT_DIV_COMB_ALT_ANT_RATIO,
972*0f0eebe7SAdrian Chadd 	    div_ant_conf.antdiv_configgroup,
973*0f0eebe7SAdrian Chadd 	    &div_ant_conf);
974216ca234SAdrian Chadd 
975216ca234SAdrian Chadd 	ath_hal_div_comb_conf_set(sc->sc_ah, &div_ant_conf);
976216ca234SAdrian Chadd 
977216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n",
978216ca234SAdrian Chadd 	   __func__, antcomb->total_pkt_count);
979216ca234SAdrian Chadd 
980216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n",
981216ca234SAdrian Chadd 	   __func__, antcomb->main_total_rssi);
982216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n",
983216ca234SAdrian Chadd 	   __func__, antcomb->alt_total_rssi);
984216ca234SAdrian Chadd 
985216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n",
986216ca234SAdrian Chadd 	   __func__, main_rssi_avg);
987216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n",
988216ca234SAdrian Chadd 	   __func__, alt_rssi_avg);
989216ca234SAdrian Chadd 
990216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n",
991216ca234SAdrian Chadd 	   __func__, antcomb->main_recv_cnt);
992216ca234SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n",
993216ca234SAdrian Chadd 	   __func__, antcomb->alt_recv_cnt);
994216ca234SAdrian Chadd 
995216ca234SAdrian Chadd //	if (curr_alt_set != div_ant_conf.alt_lna_conf)
996216ca234SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n",
997216ca234SAdrian Chadd 		    __func__, curr_alt_set, div_ant_conf.alt_lna_conf);
998216ca234SAdrian Chadd //	if (curr_main_set != div_ant_conf.main_lna_conf)
999216ca234SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n",
1000216ca234SAdrian Chadd 		    __func__, curr_main_set, div_ant_conf.main_lna_conf);
1001216ca234SAdrian Chadd //	if (curr_bias != div_ant_conf.fast_div_bias)
1002216ca234SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n",
1003216ca234SAdrian Chadd 		    __func__, curr_bias, div_ant_conf.fast_div_bias);
1004216ca234SAdrian Chadd 
1005216ca234SAdrian Chadd 	antcomb->scan_start_time = ticks;
1006216ca234SAdrian Chadd 	antcomb->total_pkt_count = 0;
1007216ca234SAdrian Chadd 	antcomb->main_total_rssi = 0;
1008216ca234SAdrian Chadd 	antcomb->alt_total_rssi = 0;
1009216ca234SAdrian Chadd 	antcomb->main_recv_cnt = 0;
1010216ca234SAdrian Chadd 	antcomb->alt_recv_cnt = 0;
1011216ca234SAdrian Chadd }
1012216ca234SAdrian Chadd 
1013