1*216ca234SAdrian Chadd /*- 2*216ca234SAdrian Chadd * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3*216ca234SAdrian Chadd * All rights reserved. 4*216ca234SAdrian Chadd * 5*216ca234SAdrian Chadd * Redistribution and use in source and binary forms, with or without 6*216ca234SAdrian Chadd * modification, are permitted provided that the following conditions 7*216ca234SAdrian Chadd * are met: 8*216ca234SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 9*216ca234SAdrian Chadd * notice, this list of conditions and the following disclaimer, 10*216ca234SAdrian Chadd * without modification. 11*216ca234SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12*216ca234SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13*216ca234SAdrian Chadd * redistribution must be conditioned upon including a substantially 14*216ca234SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 15*216ca234SAdrian Chadd * 16*216ca234SAdrian Chadd * NO WARRANTY 17*216ca234SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*216ca234SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*216ca234SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20*216ca234SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21*216ca234SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22*216ca234SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*216ca234SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*216ca234SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*216ca234SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*216ca234SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27*216ca234SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 28*216ca234SAdrian Chadd * 29*216ca234SAdrian Chadd * $FreeBSD$ 30*216ca234SAdrian Chadd */ 31*216ca234SAdrian Chadd #include <sys/cdefs.h> 32*216ca234SAdrian Chadd __FBSDID("$FreeBSD$"); 33*216ca234SAdrian Chadd 34*216ca234SAdrian Chadd /* 35*216ca234SAdrian Chadd * This module handles LNA diversity for those chips which implement LNA 36*216ca234SAdrian Chadd * mixing (AR9285/AR9485.) 37*216ca234SAdrian Chadd */ 38*216ca234SAdrian Chadd #include "opt_ath.h" 39*216ca234SAdrian Chadd #include "opt_inet.h" 40*216ca234SAdrian Chadd #include "opt_wlan.h" 41*216ca234SAdrian Chadd 42*216ca234SAdrian Chadd #include <sys/param.h> 43*216ca234SAdrian Chadd #include <sys/systm.h> 44*216ca234SAdrian Chadd #include <sys/sysctl.h> 45*216ca234SAdrian Chadd #include <sys/kernel.h> 46*216ca234SAdrian Chadd #include <sys/lock.h> 47*216ca234SAdrian Chadd #include <sys/mutex.h> 48*216ca234SAdrian Chadd #include <sys/errno.h> 49*216ca234SAdrian Chadd 50*216ca234SAdrian Chadd #include <machine/bus.h> 51*216ca234SAdrian Chadd #include <machine/resource.h> 52*216ca234SAdrian Chadd #include <sys/bus.h> 53*216ca234SAdrian Chadd 54*216ca234SAdrian Chadd #include <sys/socket.h> 55*216ca234SAdrian Chadd 56*216ca234SAdrian Chadd #include <net/if.h> 57*216ca234SAdrian Chadd #include <net/if_media.h> 58*216ca234SAdrian Chadd #include <net/if_arp.h> 59*216ca234SAdrian Chadd #include <net/ethernet.h> /* XXX for ether_sprintf */ 60*216ca234SAdrian Chadd 61*216ca234SAdrian Chadd #include <net80211/ieee80211_var.h> 62*216ca234SAdrian Chadd 63*216ca234SAdrian Chadd #include <net/bpf.h> 64*216ca234SAdrian Chadd 65*216ca234SAdrian Chadd #ifdef INET 66*216ca234SAdrian Chadd #include <netinet/in.h> 67*216ca234SAdrian Chadd #include <netinet/if_ether.h> 68*216ca234SAdrian Chadd #endif 69*216ca234SAdrian Chadd 70*216ca234SAdrian Chadd #include <dev/ath/if_athvar.h> 71*216ca234SAdrian Chadd #include <dev/ath/if_ath_debug.h> 72*216ca234SAdrian Chadd #include <dev/ath/if_ath_lna_div.h> 73*216ca234SAdrian Chadd 74*216ca234SAdrian Chadd /* Linux compability macros */ 75*216ca234SAdrian Chadd /* 76*216ca234SAdrian Chadd * XXX these don't handle rounding, underflow, overflow, wrapping! 77*216ca234SAdrian Chadd */ 78*216ca234SAdrian Chadd #define msecs_to_jiffies(a) ( (a) * hz / 1000 ) 79*216ca234SAdrian Chadd 80*216ca234SAdrian Chadd /* 81*216ca234SAdrian Chadd * Methods which are required 82*216ca234SAdrian Chadd */ 83*216ca234SAdrian Chadd 84*216ca234SAdrian Chadd /* 85*216ca234SAdrian Chadd * Attach the LNA diversity to the given interface 86*216ca234SAdrian Chadd */ 87*216ca234SAdrian Chadd int 88*216ca234SAdrian Chadd ath_lna_div_attach(struct ath_softc *sc) 89*216ca234SAdrian Chadd { 90*216ca234SAdrian Chadd struct if_ath_ant_comb_state *ss; 91*216ca234SAdrian Chadd 92*216ca234SAdrian Chadd /* Only do this if diversity is enabled */ 93*216ca234SAdrian Chadd if (! ath_hal_hasdivantcomb(sc->sc_ah)) 94*216ca234SAdrian Chadd return (0); 95*216ca234SAdrian Chadd 96*216ca234SAdrian Chadd ss = malloc(sizeof(struct if_ath_ant_comb_state), 97*216ca234SAdrian Chadd M_TEMP, M_WAITOK | M_ZERO); 98*216ca234SAdrian Chadd if (ss == NULL) { 99*216ca234SAdrian Chadd device_printf(sc->sc_dev, "%s: failed to allocate\n", 100*216ca234SAdrian Chadd __func__); 101*216ca234SAdrian Chadd /* Don't fail at this point */ 102*216ca234SAdrian Chadd return (0); 103*216ca234SAdrian Chadd } 104*216ca234SAdrian Chadd 105*216ca234SAdrian Chadd /* Let's flip this on */ 106*216ca234SAdrian Chadd sc->sc_lna_div = ss; 107*216ca234SAdrian Chadd sc->sc_dolnadiv = 1; 108*216ca234SAdrian Chadd 109*216ca234SAdrian Chadd return (0); 110*216ca234SAdrian Chadd } 111*216ca234SAdrian Chadd 112*216ca234SAdrian Chadd /* 113*216ca234SAdrian Chadd * Detach the LNA diversity state from the given interface 114*216ca234SAdrian Chadd */ 115*216ca234SAdrian Chadd int 116*216ca234SAdrian Chadd ath_lna_div_detach(struct ath_softc *sc) 117*216ca234SAdrian Chadd { 118*216ca234SAdrian Chadd if (sc->sc_lna_div != NULL) { 119*216ca234SAdrian Chadd free(sc->sc_lna_div, M_TEMP); 120*216ca234SAdrian Chadd sc->sc_lna_div = NULL; 121*216ca234SAdrian Chadd } 122*216ca234SAdrian Chadd sc->sc_dolnadiv = 0; 123*216ca234SAdrian Chadd return (0); 124*216ca234SAdrian Chadd } 125*216ca234SAdrian Chadd 126*216ca234SAdrian Chadd /* 127*216ca234SAdrian Chadd * Enable LNA diversity on the current channel if it's required. 128*216ca234SAdrian Chadd */ 129*216ca234SAdrian Chadd int 130*216ca234SAdrian Chadd ath_lna_div_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) 131*216ca234SAdrian Chadd { 132*216ca234SAdrian Chadd 133*216ca234SAdrian Chadd return (0); 134*216ca234SAdrian Chadd } 135*216ca234SAdrian Chadd 136*216ca234SAdrian Chadd /* 137*216ca234SAdrian Chadd * Handle ioctl requests from the diagnostic interface. 138*216ca234SAdrian Chadd * 139*216ca234SAdrian Chadd * The initial part of this code resembles ath_ioctl_diag(); 140*216ca234SAdrian Chadd * it's likely a good idea to reduce duplication between 141*216ca234SAdrian Chadd * these two routines. 142*216ca234SAdrian Chadd */ 143*216ca234SAdrian Chadd int 144*216ca234SAdrian Chadd ath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad) 145*216ca234SAdrian Chadd { 146*216ca234SAdrian Chadd unsigned int id = ad->ad_id & ATH_DIAG_ID; 147*216ca234SAdrian Chadd void *indata = NULL; 148*216ca234SAdrian Chadd void *outdata = NULL; 149*216ca234SAdrian Chadd u_int32_t insize = ad->ad_in_size; 150*216ca234SAdrian Chadd u_int32_t outsize = ad->ad_out_size; 151*216ca234SAdrian Chadd int error = 0; 152*216ca234SAdrian Chadd // int val; 153*216ca234SAdrian Chadd 154*216ca234SAdrian Chadd if (ad->ad_id & ATH_DIAG_IN) { 155*216ca234SAdrian Chadd /* 156*216ca234SAdrian Chadd * Copy in data. 157*216ca234SAdrian Chadd */ 158*216ca234SAdrian Chadd indata = malloc(insize, M_TEMP, M_NOWAIT); 159*216ca234SAdrian Chadd if (indata == NULL) { 160*216ca234SAdrian Chadd error = ENOMEM; 161*216ca234SAdrian Chadd goto bad; 162*216ca234SAdrian Chadd } 163*216ca234SAdrian Chadd error = copyin(ad->ad_in_data, indata, insize); 164*216ca234SAdrian Chadd if (error) 165*216ca234SAdrian Chadd goto bad; 166*216ca234SAdrian Chadd } 167*216ca234SAdrian Chadd if (ad->ad_id & ATH_DIAG_DYN) { 168*216ca234SAdrian Chadd /* 169*216ca234SAdrian Chadd * Allocate a buffer for the results (otherwise the HAL 170*216ca234SAdrian Chadd * returns a pointer to a buffer where we can read the 171*216ca234SAdrian Chadd * results). Note that we depend on the HAL leaving this 172*216ca234SAdrian Chadd * pointer for us to use below in reclaiming the buffer; 173*216ca234SAdrian Chadd * may want to be more defensive. 174*216ca234SAdrian Chadd */ 175*216ca234SAdrian Chadd outdata = malloc(outsize, M_TEMP, M_NOWAIT); 176*216ca234SAdrian Chadd if (outdata == NULL) { 177*216ca234SAdrian Chadd error = ENOMEM; 178*216ca234SAdrian Chadd goto bad; 179*216ca234SAdrian Chadd } 180*216ca234SAdrian Chadd } 181*216ca234SAdrian Chadd switch (id) { 182*216ca234SAdrian Chadd default: 183*216ca234SAdrian Chadd error = EINVAL; 184*216ca234SAdrian Chadd } 185*216ca234SAdrian Chadd if (outsize < ad->ad_out_size) 186*216ca234SAdrian Chadd ad->ad_out_size = outsize; 187*216ca234SAdrian Chadd if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 188*216ca234SAdrian Chadd error = EFAULT; 189*216ca234SAdrian Chadd bad: 190*216ca234SAdrian Chadd if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 191*216ca234SAdrian Chadd free(indata, M_TEMP); 192*216ca234SAdrian Chadd if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 193*216ca234SAdrian Chadd free(outdata, M_TEMP); 194*216ca234SAdrian Chadd return (error); 195*216ca234SAdrian Chadd } 196*216ca234SAdrian Chadd 197*216ca234SAdrian Chadd static HAL_BOOL 198*216ca234SAdrian Chadd ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta, 199*216ca234SAdrian Chadd int main_rssi_avg, int alt_rssi_avg, int pkt_count) 200*216ca234SAdrian Chadd { 201*216ca234SAdrian Chadd return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 202*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg + maxdelta)) || 203*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); 204*216ca234SAdrian Chadd } 205*216ca234SAdrian Chadd 206*216ca234SAdrian Chadd static void 207*216ca234SAdrian Chadd ath_lnaconf_alt_good_scan(struct if_ath_ant_comb_state *antcomb, 208*216ca234SAdrian Chadd HAL_ANT_COMB_CONFIG *ant_conf, int main_rssi_avg) 209*216ca234SAdrian Chadd { 210*216ca234SAdrian Chadd antcomb->quick_scan_cnt = 0; 211*216ca234SAdrian Chadd 212*216ca234SAdrian Chadd if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA2) 213*216ca234SAdrian Chadd antcomb->rssi_lna2 = main_rssi_avg; 214*216ca234SAdrian Chadd else if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA1) 215*216ca234SAdrian Chadd antcomb->rssi_lna1 = main_rssi_avg; 216*216ca234SAdrian Chadd 217*216ca234SAdrian Chadd switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { 218*216ca234SAdrian Chadd case (0x10): /* LNA2 A-B */ 219*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 220*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 221*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 222*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1; 223*216ca234SAdrian Chadd break; 224*216ca234SAdrian Chadd case (0x20): /* LNA1 A-B */ 225*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 226*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 227*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 228*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 229*216ca234SAdrian Chadd break; 230*216ca234SAdrian Chadd case (0x21): /* LNA1 LNA2 */ 231*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA2; 232*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 233*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 234*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = 235*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 236*216ca234SAdrian Chadd break; 237*216ca234SAdrian Chadd case (0x12): /* LNA2 LNA1 */ 238*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1; 239*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 240*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 241*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = 242*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 243*216ca234SAdrian Chadd break; 244*216ca234SAdrian Chadd case (0x13): /* LNA2 A+B */ 245*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 246*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 247*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 248*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1; 249*216ca234SAdrian Chadd break; 250*216ca234SAdrian Chadd case (0x23): /* LNA1 A+B */ 251*216ca234SAdrian Chadd antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 252*216ca234SAdrian Chadd antcomb->first_quick_scan_conf = 253*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 254*216ca234SAdrian Chadd antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 255*216ca234SAdrian Chadd break; 256*216ca234SAdrian Chadd default: 257*216ca234SAdrian Chadd break; 258*216ca234SAdrian Chadd } 259*216ca234SAdrian Chadd } 260*216ca234SAdrian Chadd 261*216ca234SAdrian Chadd static void 262*216ca234SAdrian Chadd ath_select_ant_div_from_quick_scan(struct if_ath_ant_comb_state *antcomb, 263*216ca234SAdrian Chadd HAL_ANT_COMB_CONFIG *div_ant_conf, int main_rssi_avg, 264*216ca234SAdrian Chadd int alt_rssi_avg, int alt_ratio) 265*216ca234SAdrian Chadd { 266*216ca234SAdrian Chadd /* alt_good */ 267*216ca234SAdrian Chadd switch (antcomb->quick_scan_cnt) { 268*216ca234SAdrian Chadd case 0: 269*216ca234SAdrian Chadd /* set alt to main, and alt to first conf */ 270*216ca234SAdrian Chadd div_ant_conf->main_lna_conf = antcomb->main_conf; 271*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; 272*216ca234SAdrian Chadd break; 273*216ca234SAdrian Chadd case 1: 274*216ca234SAdrian Chadd /* set alt to main, and alt to first conf */ 275*216ca234SAdrian Chadd div_ant_conf->main_lna_conf = antcomb->main_conf; 276*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; 277*216ca234SAdrian Chadd antcomb->rssi_first = main_rssi_avg; 278*216ca234SAdrian Chadd antcomb->rssi_second = alt_rssi_avg; 279*216ca234SAdrian Chadd 280*216ca234SAdrian Chadd if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 281*216ca234SAdrian Chadd /* main is LNA1 */ 282*216ca234SAdrian Chadd if (ath_is_alt_ant_ratio_better(alt_ratio, 283*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 284*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 285*216ca234SAdrian Chadd main_rssi_avg, alt_rssi_avg, 286*216ca234SAdrian Chadd antcomb->total_pkt_count)) 287*216ca234SAdrian Chadd antcomb->first_ratio = AH_TRUE; 288*216ca234SAdrian Chadd else 289*216ca234SAdrian Chadd antcomb->first_ratio = AH_FALSE; 290*216ca234SAdrian Chadd } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 291*216ca234SAdrian Chadd if (ath_is_alt_ant_ratio_better(alt_ratio, 292*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 293*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 294*216ca234SAdrian Chadd main_rssi_avg, alt_rssi_avg, 295*216ca234SAdrian Chadd antcomb->total_pkt_count)) 296*216ca234SAdrian Chadd antcomb->first_ratio = AH_TRUE; 297*216ca234SAdrian Chadd else 298*216ca234SAdrian Chadd antcomb->first_ratio = AH_FALSE; 299*216ca234SAdrian Chadd } else { 300*216ca234SAdrian Chadd if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 301*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg + 302*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 303*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg)) && 304*216ca234SAdrian Chadd (antcomb->total_pkt_count > 50)) 305*216ca234SAdrian Chadd antcomb->first_ratio = AH_TRUE; 306*216ca234SAdrian Chadd else 307*216ca234SAdrian Chadd antcomb->first_ratio = AH_FALSE; 308*216ca234SAdrian Chadd } 309*216ca234SAdrian Chadd break; 310*216ca234SAdrian Chadd case 2: 311*216ca234SAdrian Chadd antcomb->alt_good = AH_FALSE; 312*216ca234SAdrian Chadd antcomb->scan_not_start = AH_FALSE; 313*216ca234SAdrian Chadd antcomb->scan = AH_FALSE; 314*216ca234SAdrian Chadd antcomb->rssi_first = main_rssi_avg; 315*216ca234SAdrian Chadd antcomb->rssi_third = alt_rssi_avg; 316*216ca234SAdrian Chadd 317*216ca234SAdrian Chadd if (antcomb->second_quick_scan_conf == HAL_ANT_DIV_COMB_LNA1) 318*216ca234SAdrian Chadd antcomb->rssi_lna1 = alt_rssi_avg; 319*216ca234SAdrian Chadd else if (antcomb->second_quick_scan_conf == 320*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 321*216ca234SAdrian Chadd antcomb->rssi_lna2 = alt_rssi_avg; 322*216ca234SAdrian Chadd else if (antcomb->second_quick_scan_conf == 323*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2) { 324*216ca234SAdrian Chadd if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) 325*216ca234SAdrian Chadd antcomb->rssi_lna2 = main_rssi_avg; 326*216ca234SAdrian Chadd else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) 327*216ca234SAdrian Chadd antcomb->rssi_lna1 = main_rssi_avg; 328*216ca234SAdrian Chadd } 329*216ca234SAdrian Chadd 330*216ca234SAdrian Chadd if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + 331*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) 332*216ca234SAdrian Chadd div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 333*216ca234SAdrian Chadd else 334*216ca234SAdrian Chadd div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA1; 335*216ca234SAdrian Chadd 336*216ca234SAdrian Chadd if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 337*216ca234SAdrian Chadd if (ath_is_alt_ant_ratio_better(alt_ratio, 338*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 339*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 340*216ca234SAdrian Chadd main_rssi_avg, alt_rssi_avg, 341*216ca234SAdrian Chadd antcomb->total_pkt_count)) 342*216ca234SAdrian Chadd antcomb->second_ratio = AH_TRUE; 343*216ca234SAdrian Chadd else 344*216ca234SAdrian Chadd antcomb->second_ratio = AH_FALSE; 345*216ca234SAdrian Chadd } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 346*216ca234SAdrian Chadd if (ath_is_alt_ant_ratio_better(alt_ratio, 347*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 348*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 349*216ca234SAdrian Chadd main_rssi_avg, alt_rssi_avg, 350*216ca234SAdrian Chadd antcomb->total_pkt_count)) 351*216ca234SAdrian Chadd antcomb->second_ratio = AH_TRUE; 352*216ca234SAdrian Chadd else 353*216ca234SAdrian Chadd antcomb->second_ratio = AH_FALSE; 354*216ca234SAdrian Chadd } else { 355*216ca234SAdrian Chadd if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 356*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg + 357*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 358*216ca234SAdrian Chadd (alt_rssi_avg > main_rssi_avg)) && 359*216ca234SAdrian Chadd (antcomb->total_pkt_count > 50)) 360*216ca234SAdrian Chadd antcomb->second_ratio = AH_TRUE; 361*216ca234SAdrian Chadd else 362*216ca234SAdrian Chadd antcomb->second_ratio = AH_FALSE; 363*216ca234SAdrian Chadd } 364*216ca234SAdrian Chadd 365*216ca234SAdrian Chadd /* set alt to the conf with maximun ratio */ 366*216ca234SAdrian Chadd if (antcomb->first_ratio && antcomb->second_ratio) { 367*216ca234SAdrian Chadd if (antcomb->rssi_second > antcomb->rssi_third) { 368*216ca234SAdrian Chadd /* first alt*/ 369*216ca234SAdrian Chadd if ((antcomb->first_quick_scan_conf == 370*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1) || 371*216ca234SAdrian Chadd (antcomb->first_quick_scan_conf == 372*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2)) 373*216ca234SAdrian Chadd /* Set alt LNA1 or LNA2*/ 374*216ca234SAdrian Chadd if (div_ant_conf->main_lna_conf == 375*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 376*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 377*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 378*216ca234SAdrian Chadd else 379*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 380*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 381*216ca234SAdrian Chadd else 382*216ca234SAdrian Chadd /* Set alt to A+B or A-B */ 383*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 384*216ca234SAdrian Chadd antcomb->first_quick_scan_conf; 385*216ca234SAdrian Chadd } else if ((antcomb->second_quick_scan_conf == 386*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1) || 387*216ca234SAdrian Chadd (antcomb->second_quick_scan_conf == 388*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2)) { 389*216ca234SAdrian Chadd /* Set alt LNA1 or LNA2 */ 390*216ca234SAdrian Chadd if (div_ant_conf->main_lna_conf == 391*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 392*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 393*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 394*216ca234SAdrian Chadd else 395*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 396*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 397*216ca234SAdrian Chadd } else { 398*216ca234SAdrian Chadd /* Set alt to A+B or A-B */ 399*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 400*216ca234SAdrian Chadd antcomb->second_quick_scan_conf; 401*216ca234SAdrian Chadd } 402*216ca234SAdrian Chadd } else if (antcomb->first_ratio) { 403*216ca234SAdrian Chadd /* first alt */ 404*216ca234SAdrian Chadd if ((antcomb->first_quick_scan_conf == 405*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1) || 406*216ca234SAdrian Chadd (antcomb->first_quick_scan_conf == 407*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2)) 408*216ca234SAdrian Chadd /* Set alt LNA1 or LNA2 */ 409*216ca234SAdrian Chadd if (div_ant_conf->main_lna_conf == 410*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 411*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 412*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 413*216ca234SAdrian Chadd else 414*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 415*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 416*216ca234SAdrian Chadd else 417*216ca234SAdrian Chadd /* Set alt to A+B or A-B */ 418*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 419*216ca234SAdrian Chadd antcomb->first_quick_scan_conf; 420*216ca234SAdrian Chadd } else if (antcomb->second_ratio) { 421*216ca234SAdrian Chadd /* second alt */ 422*216ca234SAdrian Chadd if ((antcomb->second_quick_scan_conf == 423*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1) || 424*216ca234SAdrian Chadd (antcomb->second_quick_scan_conf == 425*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2)) 426*216ca234SAdrian Chadd /* Set alt LNA1 or LNA2 */ 427*216ca234SAdrian Chadd if (div_ant_conf->main_lna_conf == 428*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 429*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 430*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 431*216ca234SAdrian Chadd else 432*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 433*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 434*216ca234SAdrian Chadd else 435*216ca234SAdrian Chadd /* Set alt to A+B or A-B */ 436*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 437*216ca234SAdrian Chadd antcomb->second_quick_scan_conf; 438*216ca234SAdrian Chadd } else { 439*216ca234SAdrian Chadd /* main is largest */ 440*216ca234SAdrian Chadd if ((antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) || 441*216ca234SAdrian Chadd (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2)) 442*216ca234SAdrian Chadd /* Set alt LNA1 or LNA2 */ 443*216ca234SAdrian Chadd if (div_ant_conf->main_lna_conf == 444*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2) 445*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 446*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 447*216ca234SAdrian Chadd else 448*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = 449*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 450*216ca234SAdrian Chadd else 451*216ca234SAdrian Chadd /* Set alt to A+B or A-B */ 452*216ca234SAdrian Chadd div_ant_conf->alt_lna_conf = antcomb->main_conf; 453*216ca234SAdrian Chadd } 454*216ca234SAdrian Chadd break; 455*216ca234SAdrian Chadd default: 456*216ca234SAdrian Chadd break; 457*216ca234SAdrian Chadd } 458*216ca234SAdrian Chadd } 459*216ca234SAdrian Chadd 460*216ca234SAdrian Chadd static void 461*216ca234SAdrian Chadd ath_ant_div_conf_fast_divbias(HAL_ANT_COMB_CONFIG *ant_conf) 462*216ca234SAdrian Chadd { 463*216ca234SAdrian Chadd /* Adjust the fast_div_bias based on main and alt lna conf */ 464*216ca234SAdrian Chadd switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { 465*216ca234SAdrian Chadd case (0x01): /* A-B LNA2 */ 466*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x3b; 467*216ca234SAdrian Chadd break; 468*216ca234SAdrian Chadd case (0x02): /* A-B LNA1 */ 469*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x3d; 470*216ca234SAdrian Chadd break; 471*216ca234SAdrian Chadd case (0x03): /* A-B A+B */ 472*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x1; 473*216ca234SAdrian Chadd break; 474*216ca234SAdrian Chadd case (0x10): /* LNA2 A-B */ 475*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x7; 476*216ca234SAdrian Chadd break; 477*216ca234SAdrian Chadd case (0x12): /* LNA2 LNA1 */ 478*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x2; 479*216ca234SAdrian Chadd break; 480*216ca234SAdrian Chadd case (0x13): /* LNA2 A+B */ 481*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x7; 482*216ca234SAdrian Chadd break; 483*216ca234SAdrian Chadd case (0x20): /* LNA1 A-B */ 484*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x6; 485*216ca234SAdrian Chadd break; 486*216ca234SAdrian Chadd case (0x21): /* LNA1 LNA2 */ 487*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x0; 488*216ca234SAdrian Chadd break; 489*216ca234SAdrian Chadd case (0x23): /* LNA1 A+B */ 490*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x6; 491*216ca234SAdrian Chadd break; 492*216ca234SAdrian Chadd case (0x30): /* A+B A-B */ 493*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x1; 494*216ca234SAdrian Chadd break; 495*216ca234SAdrian Chadd case (0x31): /* A+B LNA2 */ 496*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x3b; 497*216ca234SAdrian Chadd break; 498*216ca234SAdrian Chadd case (0x32): /* A+B LNA1 */ 499*216ca234SAdrian Chadd ant_conf->fast_div_bias = 0x3d; 500*216ca234SAdrian Chadd break; 501*216ca234SAdrian Chadd default: 502*216ca234SAdrian Chadd break; 503*216ca234SAdrian Chadd } 504*216ca234SAdrian Chadd } 505*216ca234SAdrian Chadd 506*216ca234SAdrian Chadd /* Antenna diversity and combining */ 507*216ca234SAdrian Chadd void 508*216ca234SAdrian Chadd ath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs, 509*216ca234SAdrian Chadd unsigned long ticks, int hz) 510*216ca234SAdrian Chadd { 511*216ca234SAdrian Chadd HAL_ANT_COMB_CONFIG div_ant_conf; 512*216ca234SAdrian Chadd struct if_ath_ant_comb_state *antcomb = sc->sc_lna_div; 513*216ca234SAdrian Chadd int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; 514*216ca234SAdrian Chadd int curr_main_set, curr_bias; 515*216ca234SAdrian Chadd int main_rssi = rs->rs_rssi_ctl[0]; 516*216ca234SAdrian Chadd int alt_rssi = rs->rs_rssi_ctl[1]; 517*216ca234SAdrian Chadd int rx_ant_conf, main_ant_conf, alt_ant_conf; 518*216ca234SAdrian Chadd HAL_BOOL short_scan = AH_FALSE; 519*216ca234SAdrian Chadd 520*216ca234SAdrian Chadd rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK; 521*216ca234SAdrian Chadd main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK; 522*216ca234SAdrian Chadd alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK; 523*216ca234SAdrian Chadd 524*216ca234SAdrian Chadd #if 0 525*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, 526*216ca234SAdrian Chadd "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; " 527*216ca234SAdrian Chadd "FastDiv: %d\n", 528*216ca234SAdrian Chadd __func__, 529*216ca234SAdrian Chadd main_rssi, 530*216ca234SAdrian Chadd alt_rssi, 531*216ca234SAdrian Chadd main_ant_conf, 532*216ca234SAdrian Chadd alt_ant_conf, 533*216ca234SAdrian Chadd rx_ant_conf, 534*216ca234SAdrian Chadd !!(rs->rs_rssi_ctl[2] & 0x80), 535*216ca234SAdrian Chadd !!(rs->rs_rssi_ctl[2] & 0x40), 536*216ca234SAdrian Chadd !!(rs->rs_rssi_ext[2] & 0x40)); 537*216ca234SAdrian Chadd #endif 538*216ca234SAdrian Chadd 539*216ca234SAdrian Chadd /* 540*216ca234SAdrian Chadd * If LNA diversity combining isn't enabled, don't run this. 541*216ca234SAdrian Chadd */ 542*216ca234SAdrian Chadd if (! sc->sc_dolnadiv) 543*216ca234SAdrian Chadd return; 544*216ca234SAdrian Chadd 545*216ca234SAdrian Chadd /* 546*216ca234SAdrian Chadd * XXX this is ugly, but the HAL code attaches the 547*216ca234SAdrian Chadd * LNA diversity to the TX antenna settings. 548*216ca234SAdrian Chadd * I don't know why. 549*216ca234SAdrian Chadd */ 550*216ca234SAdrian Chadd if (sc->sc_txantenna != HAL_ANT_VARIABLE) 551*216ca234SAdrian Chadd return; 552*216ca234SAdrian Chadd 553*216ca234SAdrian Chadd /* Record packet only when alt_rssi is positive */ 554*216ca234SAdrian Chadd if (main_rssi > 0 && alt_rssi > 0) { 555*216ca234SAdrian Chadd antcomb->total_pkt_count++; 556*216ca234SAdrian Chadd antcomb->main_total_rssi += main_rssi; 557*216ca234SAdrian Chadd antcomb->alt_total_rssi += alt_rssi; 558*216ca234SAdrian Chadd if (main_ant_conf == rx_ant_conf) 559*216ca234SAdrian Chadd antcomb->main_recv_cnt++; 560*216ca234SAdrian Chadd else 561*216ca234SAdrian Chadd antcomb->alt_recv_cnt++; 562*216ca234SAdrian Chadd } 563*216ca234SAdrian Chadd 564*216ca234SAdrian Chadd /* Short scan check */ 565*216ca234SAdrian Chadd if (antcomb->scan && antcomb->alt_good) { 566*216ca234SAdrian Chadd if (time_after(ticks, antcomb->scan_start_time + 567*216ca234SAdrian Chadd msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) 568*216ca234SAdrian Chadd short_scan = AH_TRUE; 569*216ca234SAdrian Chadd else 570*216ca234SAdrian Chadd if (antcomb->total_pkt_count == 571*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { 572*216ca234SAdrian Chadd alt_ratio = ((antcomb->alt_recv_cnt * 100) / 573*216ca234SAdrian Chadd antcomb->total_pkt_count); 574*216ca234SAdrian Chadd if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) 575*216ca234SAdrian Chadd short_scan = AH_TRUE; 576*216ca234SAdrian Chadd } 577*216ca234SAdrian Chadd } 578*216ca234SAdrian Chadd 579*216ca234SAdrian Chadd if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || 580*216ca234SAdrian Chadd rs->rs_moreaggr) && !short_scan) 581*216ca234SAdrian Chadd return; 582*216ca234SAdrian Chadd 583*216ca234SAdrian Chadd if (antcomb->total_pkt_count) { 584*216ca234SAdrian Chadd alt_ratio = ((antcomb->alt_recv_cnt * 100) / 585*216ca234SAdrian Chadd antcomb->total_pkt_count); 586*216ca234SAdrian Chadd main_rssi_avg = (antcomb->main_total_rssi / 587*216ca234SAdrian Chadd antcomb->total_pkt_count); 588*216ca234SAdrian Chadd alt_rssi_avg = (antcomb->alt_total_rssi / 589*216ca234SAdrian Chadd antcomb->total_pkt_count); 590*216ca234SAdrian Chadd } 591*216ca234SAdrian Chadd 592*216ca234SAdrian Chadd OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf)); 593*216ca234SAdrian Chadd 594*216ca234SAdrian Chadd ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf); 595*216ca234SAdrian Chadd curr_alt_set = div_ant_conf.alt_lna_conf; 596*216ca234SAdrian Chadd curr_main_set = div_ant_conf.main_lna_conf; 597*216ca234SAdrian Chadd curr_bias = div_ant_conf.fast_div_bias; 598*216ca234SAdrian Chadd 599*216ca234SAdrian Chadd antcomb->count++; 600*216ca234SAdrian Chadd 601*216ca234SAdrian Chadd if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { 602*216ca234SAdrian Chadd if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 603*216ca234SAdrian Chadd ath_lnaconf_alt_good_scan(antcomb, &div_ant_conf, 604*216ca234SAdrian Chadd main_rssi_avg); 605*216ca234SAdrian Chadd antcomb->alt_good = AH_TRUE; 606*216ca234SAdrian Chadd } else { 607*216ca234SAdrian Chadd antcomb->alt_good = AH_FALSE; 608*216ca234SAdrian Chadd } 609*216ca234SAdrian Chadd 610*216ca234SAdrian Chadd antcomb->count = 0; 611*216ca234SAdrian Chadd antcomb->scan = AH_TRUE; 612*216ca234SAdrian Chadd antcomb->scan_not_start = AH_TRUE; 613*216ca234SAdrian Chadd } 614*216ca234SAdrian Chadd 615*216ca234SAdrian Chadd if (!antcomb->scan) { 616*216ca234SAdrian Chadd if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 617*216ca234SAdrian Chadd if (curr_alt_set == HAL_ANT_DIV_COMB_LNA2) { 618*216ca234SAdrian Chadd /* Switch main and alt LNA */ 619*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 620*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 621*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 622*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 623*216ca234SAdrian Chadd } else if (curr_alt_set == HAL_ANT_DIV_COMB_LNA1) { 624*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 625*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 626*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 627*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 628*216ca234SAdrian Chadd } 629*216ca234SAdrian Chadd 630*216ca234SAdrian Chadd goto div_comb_done; 631*216ca234SAdrian Chadd } else if ((curr_alt_set != HAL_ANT_DIV_COMB_LNA1) && 632*216ca234SAdrian Chadd (curr_alt_set != HAL_ANT_DIV_COMB_LNA2)) { 633*216ca234SAdrian Chadd /* Set alt to another LNA */ 634*216ca234SAdrian Chadd if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) 635*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 636*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 637*216ca234SAdrian Chadd else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) 638*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 639*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 640*216ca234SAdrian Chadd 641*216ca234SAdrian Chadd goto div_comb_done; 642*216ca234SAdrian Chadd } 643*216ca234SAdrian Chadd 644*216ca234SAdrian Chadd if ((alt_rssi_avg < (main_rssi_avg + 645*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) 646*216ca234SAdrian Chadd goto div_comb_done; 647*216ca234SAdrian Chadd } 648*216ca234SAdrian Chadd 649*216ca234SAdrian Chadd if (!antcomb->scan_not_start) { 650*216ca234SAdrian Chadd switch (curr_alt_set) { 651*216ca234SAdrian Chadd case HAL_ANT_DIV_COMB_LNA2: 652*216ca234SAdrian Chadd antcomb->rssi_lna2 = alt_rssi_avg; 653*216ca234SAdrian Chadd antcomb->rssi_lna1 = main_rssi_avg; 654*216ca234SAdrian Chadd antcomb->scan = AH_TRUE; 655*216ca234SAdrian Chadd /* set to A+B */ 656*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 657*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 658*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 659*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 660*216ca234SAdrian Chadd break; 661*216ca234SAdrian Chadd case HAL_ANT_DIV_COMB_LNA1: 662*216ca234SAdrian Chadd antcomb->rssi_lna1 = alt_rssi_avg; 663*216ca234SAdrian Chadd antcomb->rssi_lna2 = main_rssi_avg; 664*216ca234SAdrian Chadd antcomb->scan = AH_TRUE; 665*216ca234SAdrian Chadd /* set to A+B */ 666*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 667*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 668*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 669*216ca234SAdrian Chadd break; 670*216ca234SAdrian Chadd case HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2: 671*216ca234SAdrian Chadd antcomb->rssi_add = alt_rssi_avg; 672*216ca234SAdrian Chadd antcomb->scan = AH_TRUE; 673*216ca234SAdrian Chadd /* set to A-B */ 674*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 675*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 676*216ca234SAdrian Chadd break; 677*216ca234SAdrian Chadd case HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2: 678*216ca234SAdrian Chadd antcomb->rssi_sub = alt_rssi_avg; 679*216ca234SAdrian Chadd antcomb->scan = AH_FALSE; 680*216ca234SAdrian Chadd if (antcomb->rssi_lna2 > 681*216ca234SAdrian Chadd (antcomb->rssi_lna1 + 682*216ca234SAdrian Chadd ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { 683*216ca234SAdrian Chadd /* use LNA2 as main LNA */ 684*216ca234SAdrian Chadd if ((antcomb->rssi_add > antcomb->rssi_lna1) && 685*216ca234SAdrian Chadd (antcomb->rssi_add > antcomb->rssi_sub)) { 686*216ca234SAdrian Chadd /* set to A+B */ 687*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 688*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 689*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 690*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 691*216ca234SAdrian Chadd } else if (antcomb->rssi_sub > 692*216ca234SAdrian Chadd antcomb->rssi_lna1) { 693*216ca234SAdrian Chadd /* set to A-B */ 694*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 695*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 696*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 697*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 698*216ca234SAdrian Chadd } else { 699*216ca234SAdrian Chadd /* set to LNA1 */ 700*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 701*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 702*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 703*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 704*216ca234SAdrian Chadd } 705*216ca234SAdrian Chadd } else { 706*216ca234SAdrian Chadd /* use LNA1 as main LNA */ 707*216ca234SAdrian Chadd if ((antcomb->rssi_add > antcomb->rssi_lna2) && 708*216ca234SAdrian Chadd (antcomb->rssi_add > antcomb->rssi_sub)) { 709*216ca234SAdrian Chadd /* set to A+B */ 710*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 711*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 712*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 713*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 714*216ca234SAdrian Chadd } else if (antcomb->rssi_sub > 715*216ca234SAdrian Chadd antcomb->rssi_lna1) { 716*216ca234SAdrian Chadd /* set to A-B */ 717*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 718*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 719*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 720*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 721*216ca234SAdrian Chadd } else { 722*216ca234SAdrian Chadd /* set to LNA2 */ 723*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 724*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 725*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 726*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 727*216ca234SAdrian Chadd } 728*216ca234SAdrian Chadd } 729*216ca234SAdrian Chadd break; 730*216ca234SAdrian Chadd default: 731*216ca234SAdrian Chadd break; 732*216ca234SAdrian Chadd } 733*216ca234SAdrian Chadd } else { 734*216ca234SAdrian Chadd if (!antcomb->alt_good) { 735*216ca234SAdrian Chadd antcomb->scan_not_start = AH_FALSE; 736*216ca234SAdrian Chadd /* Set alt to another LNA */ 737*216ca234SAdrian Chadd if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) { 738*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 739*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 740*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 741*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 742*216ca234SAdrian Chadd } else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) { 743*216ca234SAdrian Chadd div_ant_conf.main_lna_conf = 744*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA1; 745*216ca234SAdrian Chadd div_ant_conf.alt_lna_conf = 746*216ca234SAdrian Chadd HAL_ANT_DIV_COMB_LNA2; 747*216ca234SAdrian Chadd } 748*216ca234SAdrian Chadd goto div_comb_done; 749*216ca234SAdrian Chadd } 750*216ca234SAdrian Chadd } 751*216ca234SAdrian Chadd 752*216ca234SAdrian Chadd ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, 753*216ca234SAdrian Chadd main_rssi_avg, alt_rssi_avg, 754*216ca234SAdrian Chadd alt_ratio); 755*216ca234SAdrian Chadd 756*216ca234SAdrian Chadd antcomb->quick_scan_cnt++; 757*216ca234SAdrian Chadd 758*216ca234SAdrian Chadd div_comb_done: 759*216ca234SAdrian Chadd ath_ant_div_conf_fast_divbias(&div_ant_conf); 760*216ca234SAdrian Chadd 761*216ca234SAdrian Chadd ath_hal_div_comb_conf_set(sc->sc_ah, &div_ant_conf); 762*216ca234SAdrian Chadd 763*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n", 764*216ca234SAdrian Chadd __func__, antcomb->total_pkt_count); 765*216ca234SAdrian Chadd 766*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n", 767*216ca234SAdrian Chadd __func__, antcomb->main_total_rssi); 768*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n", 769*216ca234SAdrian Chadd __func__, antcomb->alt_total_rssi); 770*216ca234SAdrian Chadd 771*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n", 772*216ca234SAdrian Chadd __func__, main_rssi_avg); 773*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n", 774*216ca234SAdrian Chadd __func__, alt_rssi_avg); 775*216ca234SAdrian Chadd 776*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n", 777*216ca234SAdrian Chadd __func__, antcomb->main_recv_cnt); 778*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n", 779*216ca234SAdrian Chadd __func__, antcomb->alt_recv_cnt); 780*216ca234SAdrian Chadd 781*216ca234SAdrian Chadd // if (curr_alt_set != div_ant_conf.alt_lna_conf) 782*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n", 783*216ca234SAdrian Chadd __func__, curr_alt_set, div_ant_conf.alt_lna_conf); 784*216ca234SAdrian Chadd // if (curr_main_set != div_ant_conf.main_lna_conf) 785*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n", 786*216ca234SAdrian Chadd __func__, curr_main_set, div_ant_conf.main_lna_conf); 787*216ca234SAdrian Chadd // if (curr_bias != div_ant_conf.fast_div_bias) 788*216ca234SAdrian Chadd DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n", 789*216ca234SAdrian Chadd __func__, curr_bias, div_ant_conf.fast_div_bias); 790*216ca234SAdrian Chadd 791*216ca234SAdrian Chadd antcomb->scan_start_time = ticks; 792*216ca234SAdrian Chadd antcomb->total_pkt_count = 0; 793*216ca234SAdrian Chadd antcomb->main_total_rssi = 0; 794*216ca234SAdrian Chadd antcomb->alt_total_rssi = 0; 795*216ca234SAdrian Chadd antcomb->main_recv_cnt = 0; 796*216ca234SAdrian Chadd antcomb->alt_recv_cnt = 0; 797*216ca234SAdrian Chadd } 798*216ca234SAdrian Chadd 799