1251655Sadrian/*- 2251655Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3251655Sadrian * All rights reserved. 4251655Sadrian * 5251655Sadrian * Redistribution and use in source and binary forms, with or without 6251655Sadrian * modification, are permitted provided that the following conditions 7251655Sadrian * are met: 8251655Sadrian * 1. Redistributions of source code must retain the above copyright 9251655Sadrian * notice, this list of conditions and the following disclaimer, 10251655Sadrian * without modification. 11251655Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12251655Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13251655Sadrian * redistribution must be conditioned upon including a substantially 14251655Sadrian * similar Disclaimer requirement for further binary redistribution. 15251655Sadrian * 16251655Sadrian * NO WARRANTY 17251655Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18251655Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19251655Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20251655Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21251655Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22251655Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23251655Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24251655Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25251655Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26251655Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27251655Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28251655Sadrian * 29251655Sadrian * $FreeBSD$ 30251655Sadrian */ 31251655Sadrian#include <sys/cdefs.h> 32251655Sadrian__FBSDID("$FreeBSD$"); 33251655Sadrian 34251655Sadrian/* 35251655Sadrian * This module handles LNA diversity for those chips which implement LNA 36251655Sadrian * mixing (AR9285/AR9485.) 37251655Sadrian */ 38251655Sadrian#include "opt_ath.h" 39251655Sadrian#include "opt_inet.h" 40251655Sadrian#include "opt_wlan.h" 41251655Sadrian 42251655Sadrian#include <sys/param.h> 43251655Sadrian#include <sys/systm.h> 44251655Sadrian#include <sys/sysctl.h> 45251655Sadrian#include <sys/kernel.h> 46251655Sadrian#include <sys/lock.h> 47251655Sadrian#include <sys/mutex.h> 48251655Sadrian#include <sys/errno.h> 49251655Sadrian 50251655Sadrian#include <machine/bus.h> 51251655Sadrian#include <machine/resource.h> 52251655Sadrian#include <sys/bus.h> 53251655Sadrian 54251655Sadrian#include <sys/socket.h> 55251655Sadrian 56251655Sadrian#include <net/if.h> 57251655Sadrian#include <net/if_media.h> 58251655Sadrian#include <net/if_arp.h> 59251655Sadrian#include <net/ethernet.h> /* XXX for ether_sprintf */ 60251655Sadrian 61251655Sadrian#include <net80211/ieee80211_var.h> 62251655Sadrian 63251655Sadrian#include <net/bpf.h> 64251655Sadrian 65251655Sadrian#ifdef INET 66251655Sadrian#include <netinet/in.h> 67251655Sadrian#include <netinet/if_ether.h> 68251655Sadrian#endif 69251655Sadrian 70251655Sadrian#include <dev/ath/if_athvar.h> 71251655Sadrian#include <dev/ath/if_ath_debug.h> 72251655Sadrian#include <dev/ath/if_ath_lna_div.h> 73251655Sadrian 74251655Sadrian/* Linux compability macros */ 75251655Sadrian/* 76251655Sadrian * XXX these don't handle rounding, underflow, overflow, wrapping! 77251655Sadrian */ 78251655Sadrian#define msecs_to_jiffies(a) ( (a) * hz / 1000 ) 79251655Sadrian 80251655Sadrian/* 81251655Sadrian * Methods which are required 82251655Sadrian */ 83251655Sadrian 84251655Sadrian/* 85251655Sadrian * Attach the LNA diversity to the given interface 86251655Sadrian */ 87251655Sadrianint 88251655Sadrianath_lna_div_attach(struct ath_softc *sc) 89251655Sadrian{ 90251655Sadrian struct if_ath_ant_comb_state *ss; 91251730Sadrian HAL_ANT_COMB_CONFIG div_ant_conf; 92251655Sadrian 93251655Sadrian /* Only do this if diversity is enabled */ 94251655Sadrian if (! ath_hal_hasdivantcomb(sc->sc_ah)) 95251655Sadrian return (0); 96251655Sadrian 97251655Sadrian ss = malloc(sizeof(struct if_ath_ant_comb_state), 98251655Sadrian M_TEMP, M_WAITOK | M_ZERO); 99251655Sadrian if (ss == NULL) { 100251655Sadrian device_printf(sc->sc_dev, "%s: failed to allocate\n", 101251655Sadrian __func__); 102251655Sadrian /* Don't fail at this point */ 103251655Sadrian return (0); 104251655Sadrian } 105251655Sadrian 106251730Sadrian /* Fetch the hardware configuration */ 107251730Sadrian OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf)); 108251730Sadrian ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf); 109251730Sadrian 110251730Sadrian /* Figure out what the hardware specific bits should be */ 111251730Sadrian if ((div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_1) || 112251730Sadrian (div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_2)) { 113251730Sadrian ss->lna1_lna2_delta = -9; 114251730Sadrian } else { 115251730Sadrian ss->lna1_lna2_delta = -3; 116251730Sadrian } 117251730Sadrian 118251655Sadrian /* Let's flip this on */ 119251655Sadrian sc->sc_lna_div = ss; 120251655Sadrian sc->sc_dolnadiv = 1; 121251655Sadrian 122251655Sadrian return (0); 123251655Sadrian} 124251655Sadrian 125251655Sadrian/* 126251655Sadrian * Detach the LNA diversity state from the given interface 127251655Sadrian */ 128251655Sadrianint 129251655Sadrianath_lna_div_detach(struct ath_softc *sc) 130251655Sadrian{ 131251655Sadrian if (sc->sc_lna_div != NULL) { 132251655Sadrian free(sc->sc_lna_div, M_TEMP); 133251655Sadrian sc->sc_lna_div = NULL; 134251655Sadrian } 135251655Sadrian sc->sc_dolnadiv = 0; 136251655Sadrian return (0); 137251655Sadrian} 138251655Sadrian 139251655Sadrian/* 140251655Sadrian * Enable LNA diversity on the current channel if it's required. 141251655Sadrian */ 142251655Sadrianint 143251655Sadrianath_lna_div_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) 144251655Sadrian{ 145251655Sadrian 146251655Sadrian return (0); 147251655Sadrian} 148251655Sadrian 149251655Sadrian/* 150251655Sadrian * Handle ioctl requests from the diagnostic interface. 151251655Sadrian * 152251655Sadrian * The initial part of this code resembles ath_ioctl_diag(); 153251655Sadrian * it's likely a good idea to reduce duplication between 154251655Sadrian * these two routines. 155251655Sadrian */ 156251655Sadrianint 157251655Sadrianath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad) 158251655Sadrian{ 159251655Sadrian unsigned int id = ad->ad_id & ATH_DIAG_ID; 160251655Sadrian void *indata = NULL; 161251655Sadrian void *outdata = NULL; 162251655Sadrian u_int32_t insize = ad->ad_in_size; 163251655Sadrian u_int32_t outsize = ad->ad_out_size; 164251655Sadrian int error = 0; 165251655Sadrian// int val; 166251655Sadrian 167251655Sadrian if (ad->ad_id & ATH_DIAG_IN) { 168251655Sadrian /* 169251655Sadrian * Copy in data. 170251655Sadrian */ 171251655Sadrian indata = malloc(insize, M_TEMP, M_NOWAIT); 172251655Sadrian if (indata == NULL) { 173251655Sadrian error = ENOMEM; 174251655Sadrian goto bad; 175251655Sadrian } 176251655Sadrian error = copyin(ad->ad_in_data, indata, insize); 177251655Sadrian if (error) 178251655Sadrian goto bad; 179251655Sadrian } 180251655Sadrian if (ad->ad_id & ATH_DIAG_DYN) { 181251655Sadrian /* 182251655Sadrian * Allocate a buffer for the results (otherwise the HAL 183251655Sadrian * returns a pointer to a buffer where we can read the 184251655Sadrian * results). Note that we depend on the HAL leaving this 185251655Sadrian * pointer for us to use below in reclaiming the buffer; 186251655Sadrian * may want to be more defensive. 187251655Sadrian */ 188251655Sadrian outdata = malloc(outsize, M_TEMP, M_NOWAIT); 189251655Sadrian if (outdata == NULL) { 190251655Sadrian error = ENOMEM; 191251655Sadrian goto bad; 192251655Sadrian } 193251655Sadrian } 194251655Sadrian switch (id) { 195251655Sadrian default: 196251655Sadrian error = EINVAL; 197251655Sadrian } 198251655Sadrian if (outsize < ad->ad_out_size) 199251655Sadrian ad->ad_out_size = outsize; 200251655Sadrian if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 201251655Sadrian error = EFAULT; 202251655Sadrianbad: 203251655Sadrian if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 204251655Sadrian free(indata, M_TEMP); 205251655Sadrian if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 206251655Sadrian free(outdata, M_TEMP); 207251655Sadrian return (error); 208251655Sadrian} 209251655Sadrian 210251655Sadrianstatic HAL_BOOL 211251655Sadrianath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta, 212251655Sadrian int main_rssi_avg, int alt_rssi_avg, int pkt_count) 213251655Sadrian{ 214251655Sadrian return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 215251655Sadrian (alt_rssi_avg > main_rssi_avg + maxdelta)) || 216251655Sadrian (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); 217251655Sadrian} 218251655Sadrian 219251655Sadrianstatic void 220251655Sadrianath_lnaconf_alt_good_scan(struct if_ath_ant_comb_state *antcomb, 221251655Sadrian HAL_ANT_COMB_CONFIG *ant_conf, int main_rssi_avg) 222251655Sadrian{ 223251655Sadrian antcomb->quick_scan_cnt = 0; 224251655Sadrian 225251655Sadrian if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA2) 226251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 227251655Sadrian else if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA1) 228251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 229251655Sadrian 230251655Sadrian switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { 231251655Sadrian case (0x10): /* LNA2 A-B */ 232251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 233251655Sadrian antcomb->first_quick_scan_conf = 234251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 235251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1; 236251655Sadrian break; 237251655Sadrian case (0x20): /* LNA1 A-B */ 238251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 239251655Sadrian antcomb->first_quick_scan_conf = 240251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 241251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 242251655Sadrian break; 243251655Sadrian case (0x21): /* LNA1 LNA2 */ 244251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA2; 245251655Sadrian antcomb->first_quick_scan_conf = 246251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 247251655Sadrian antcomb->second_quick_scan_conf = 248251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 249251655Sadrian break; 250251655Sadrian case (0x12): /* LNA2 LNA1 */ 251251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1; 252251655Sadrian antcomb->first_quick_scan_conf = 253251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 254251655Sadrian antcomb->second_quick_scan_conf = 255251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 256251655Sadrian break; 257251655Sadrian case (0x13): /* LNA2 A+B */ 258251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 259251655Sadrian antcomb->first_quick_scan_conf = 260251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 261251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA1; 262251655Sadrian break; 263251655Sadrian case (0x23): /* LNA1 A+B */ 264251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 265251655Sadrian antcomb->first_quick_scan_conf = 266251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 267251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 268251655Sadrian break; 269251655Sadrian default: 270251655Sadrian break; 271251655Sadrian } 272251655Sadrian} 273251655Sadrian 274251655Sadrianstatic void 275251655Sadrianath_select_ant_div_from_quick_scan(struct if_ath_ant_comb_state *antcomb, 276251655Sadrian HAL_ANT_COMB_CONFIG *div_ant_conf, int main_rssi_avg, 277251655Sadrian int alt_rssi_avg, int alt_ratio) 278251655Sadrian{ 279251655Sadrian /* alt_good */ 280251655Sadrian switch (antcomb->quick_scan_cnt) { 281251655Sadrian case 0: 282251655Sadrian /* set alt to main, and alt to first conf */ 283251655Sadrian div_ant_conf->main_lna_conf = antcomb->main_conf; 284251655Sadrian div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; 285251655Sadrian break; 286251655Sadrian case 1: 287251655Sadrian /* set alt to main, and alt to first conf */ 288251655Sadrian div_ant_conf->main_lna_conf = antcomb->main_conf; 289251655Sadrian div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; 290251655Sadrian antcomb->rssi_first = main_rssi_avg; 291251655Sadrian antcomb->rssi_second = alt_rssi_avg; 292251655Sadrian 293251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 294251655Sadrian /* main is LNA1 */ 295251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 296251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 297251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 298251655Sadrian main_rssi_avg, alt_rssi_avg, 299251655Sadrian antcomb->total_pkt_count)) 300251655Sadrian antcomb->first_ratio = AH_TRUE; 301251655Sadrian else 302251655Sadrian antcomb->first_ratio = AH_FALSE; 303251655Sadrian } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 304251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 305251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 306251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 307251655Sadrian main_rssi_avg, alt_rssi_avg, 308251655Sadrian antcomb->total_pkt_count)) 309251655Sadrian antcomb->first_ratio = AH_TRUE; 310251655Sadrian else 311251655Sadrian antcomb->first_ratio = AH_FALSE; 312251655Sadrian } else { 313251655Sadrian if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 314251655Sadrian (alt_rssi_avg > main_rssi_avg + 315251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 316251655Sadrian (alt_rssi_avg > main_rssi_avg)) && 317251655Sadrian (antcomb->total_pkt_count > 50)) 318251655Sadrian antcomb->first_ratio = AH_TRUE; 319251655Sadrian else 320251655Sadrian antcomb->first_ratio = AH_FALSE; 321251655Sadrian } 322251655Sadrian break; 323251655Sadrian case 2: 324251655Sadrian antcomb->alt_good = AH_FALSE; 325251655Sadrian antcomb->scan_not_start = AH_FALSE; 326251655Sadrian antcomb->scan = AH_FALSE; 327251655Sadrian antcomb->rssi_first = main_rssi_avg; 328251655Sadrian antcomb->rssi_third = alt_rssi_avg; 329251655Sadrian 330251655Sadrian if (antcomb->second_quick_scan_conf == HAL_ANT_DIV_COMB_LNA1) 331251655Sadrian antcomb->rssi_lna1 = alt_rssi_avg; 332251655Sadrian else if (antcomb->second_quick_scan_conf == 333251655Sadrian HAL_ANT_DIV_COMB_LNA2) 334251655Sadrian antcomb->rssi_lna2 = alt_rssi_avg; 335251655Sadrian else if (antcomb->second_quick_scan_conf == 336251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2) { 337251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) 338251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 339251655Sadrian else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) 340251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 341251655Sadrian } 342251655Sadrian 343251655Sadrian if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + 344251655Sadrian ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) 345251655Sadrian div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 346251655Sadrian else 347251655Sadrian div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA1; 348251655Sadrian 349251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 350251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 351251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 352251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 353251655Sadrian main_rssi_avg, alt_rssi_avg, 354251655Sadrian antcomb->total_pkt_count)) 355251655Sadrian antcomb->second_ratio = AH_TRUE; 356251655Sadrian else 357251655Sadrian antcomb->second_ratio = AH_FALSE; 358251655Sadrian } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 359251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 360251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 361251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 362251655Sadrian main_rssi_avg, alt_rssi_avg, 363251655Sadrian antcomb->total_pkt_count)) 364251655Sadrian antcomb->second_ratio = AH_TRUE; 365251655Sadrian else 366251655Sadrian antcomb->second_ratio = AH_FALSE; 367251655Sadrian } else { 368251655Sadrian if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 369251655Sadrian (alt_rssi_avg > main_rssi_avg + 370251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 371251655Sadrian (alt_rssi_avg > main_rssi_avg)) && 372251655Sadrian (antcomb->total_pkt_count > 50)) 373251655Sadrian antcomb->second_ratio = AH_TRUE; 374251655Sadrian else 375251655Sadrian antcomb->second_ratio = AH_FALSE; 376251655Sadrian } 377251655Sadrian 378251655Sadrian /* set alt to the conf with maximun ratio */ 379251655Sadrian if (antcomb->first_ratio && antcomb->second_ratio) { 380251655Sadrian if (antcomb->rssi_second > antcomb->rssi_third) { 381251655Sadrian /* first alt*/ 382251655Sadrian if ((antcomb->first_quick_scan_conf == 383251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 384251655Sadrian (antcomb->first_quick_scan_conf == 385251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 386251655Sadrian /* Set alt LNA1 or LNA2*/ 387251655Sadrian if (div_ant_conf->main_lna_conf == 388251655Sadrian HAL_ANT_DIV_COMB_LNA2) 389251655Sadrian div_ant_conf->alt_lna_conf = 390251655Sadrian HAL_ANT_DIV_COMB_LNA1; 391251655Sadrian else 392251655Sadrian div_ant_conf->alt_lna_conf = 393251655Sadrian HAL_ANT_DIV_COMB_LNA2; 394251655Sadrian else 395251655Sadrian /* Set alt to A+B or A-B */ 396251655Sadrian div_ant_conf->alt_lna_conf = 397251655Sadrian antcomb->first_quick_scan_conf; 398251655Sadrian } else if ((antcomb->second_quick_scan_conf == 399251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 400251655Sadrian (antcomb->second_quick_scan_conf == 401251655Sadrian HAL_ANT_DIV_COMB_LNA2)) { 402251655Sadrian /* Set alt LNA1 or LNA2 */ 403251655Sadrian if (div_ant_conf->main_lna_conf == 404251655Sadrian HAL_ANT_DIV_COMB_LNA2) 405251655Sadrian div_ant_conf->alt_lna_conf = 406251655Sadrian HAL_ANT_DIV_COMB_LNA1; 407251655Sadrian else 408251655Sadrian div_ant_conf->alt_lna_conf = 409251655Sadrian HAL_ANT_DIV_COMB_LNA2; 410251655Sadrian } else { 411251655Sadrian /* Set alt to A+B or A-B */ 412251655Sadrian div_ant_conf->alt_lna_conf = 413251655Sadrian antcomb->second_quick_scan_conf; 414251655Sadrian } 415251655Sadrian } else if (antcomb->first_ratio) { 416251655Sadrian /* first alt */ 417251655Sadrian if ((antcomb->first_quick_scan_conf == 418251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 419251655Sadrian (antcomb->first_quick_scan_conf == 420251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 421251655Sadrian /* Set alt LNA1 or LNA2 */ 422251655Sadrian if (div_ant_conf->main_lna_conf == 423251655Sadrian HAL_ANT_DIV_COMB_LNA2) 424251655Sadrian div_ant_conf->alt_lna_conf = 425251655Sadrian HAL_ANT_DIV_COMB_LNA1; 426251655Sadrian else 427251655Sadrian div_ant_conf->alt_lna_conf = 428251655Sadrian HAL_ANT_DIV_COMB_LNA2; 429251655Sadrian else 430251655Sadrian /* Set alt to A+B or A-B */ 431251655Sadrian div_ant_conf->alt_lna_conf = 432251655Sadrian antcomb->first_quick_scan_conf; 433251655Sadrian } else if (antcomb->second_ratio) { 434251655Sadrian /* second alt */ 435251655Sadrian if ((antcomb->second_quick_scan_conf == 436251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 437251655Sadrian (antcomb->second_quick_scan_conf == 438251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 439251655Sadrian /* Set alt LNA1 or LNA2 */ 440251655Sadrian if (div_ant_conf->main_lna_conf == 441251655Sadrian HAL_ANT_DIV_COMB_LNA2) 442251655Sadrian div_ant_conf->alt_lna_conf = 443251655Sadrian HAL_ANT_DIV_COMB_LNA1; 444251655Sadrian else 445251655Sadrian div_ant_conf->alt_lna_conf = 446251655Sadrian HAL_ANT_DIV_COMB_LNA2; 447251655Sadrian else 448251655Sadrian /* Set alt to A+B or A-B */ 449251655Sadrian div_ant_conf->alt_lna_conf = 450251655Sadrian antcomb->second_quick_scan_conf; 451251655Sadrian } else { 452251655Sadrian /* main is largest */ 453251655Sadrian if ((antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) || 454251655Sadrian (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2)) 455251655Sadrian /* Set alt LNA1 or LNA2 */ 456251655Sadrian if (div_ant_conf->main_lna_conf == 457251655Sadrian HAL_ANT_DIV_COMB_LNA2) 458251655Sadrian div_ant_conf->alt_lna_conf = 459251655Sadrian HAL_ANT_DIV_COMB_LNA1; 460251655Sadrian else 461251655Sadrian div_ant_conf->alt_lna_conf = 462251655Sadrian HAL_ANT_DIV_COMB_LNA2; 463251655Sadrian else 464251655Sadrian /* Set alt to A+B or A-B */ 465251655Sadrian div_ant_conf->alt_lna_conf = antcomb->main_conf; 466251655Sadrian } 467251655Sadrian break; 468251655Sadrian default: 469251655Sadrian break; 470251655Sadrian } 471251655Sadrian} 472251655Sadrian 473251655Sadrianstatic void 474251730Sadrianath_ant_adjust_fast_divbias(struct if_ath_ant_comb_state *antcomb, 475251730Sadrian int alt_ratio, int alt_ant_ratio_th, u_int config_group, 476251730Sadrian HAL_ANT_COMB_CONFIG *pdiv_ant_conf) 477251655Sadrian{ 478251730Sadrian 479251730Sadrian if (config_group == HAL_ANTDIV_CONFIG_GROUP_1) { 480251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) 481251730Sadrian | pdiv_ant_conf->alt_lna_conf) { 482251730Sadrian case (0x01): //A-B LNA2 483251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 484251730Sadrian pdiv_ant_conf->main_gaintb = 0; 485251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 486251730Sadrian break; 487251730Sadrian case (0x02): //A-B LNA1 488251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 489251730Sadrian pdiv_ant_conf->main_gaintb = 0; 490251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 491251730Sadrian break; 492251730Sadrian case (0x03): //A-B A+B 493251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 494251730Sadrian pdiv_ant_conf->main_gaintb = 0; 495251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 496251730Sadrian break; 497251730Sadrian case (0x10): //LNA2 A-B 498251730Sadrian if ((antcomb->scan == 0) 499251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 500251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 501251730Sadrian } else { 502251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 503251730Sadrian } 504251730Sadrian pdiv_ant_conf->main_gaintb = 0; 505251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 506251730Sadrian break; 507251730Sadrian case (0x12): //LNA2 LNA1 508251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 509251730Sadrian pdiv_ant_conf->main_gaintb = 0; 510251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 511251730Sadrian break; 512251730Sadrian case (0x13): //LNA2 A+B 513251730Sadrian if ((antcomb->scan == 0) 514251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 515251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 516251730Sadrian } else { 517251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 518251730Sadrian } 519251730Sadrian pdiv_ant_conf->main_gaintb = 0; 520251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 521251730Sadrian break; 522251730Sadrian case (0x20): //LNA1 A-B 523251730Sadrian if ((antcomb->scan == 0) 524251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 525251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 526251730Sadrian } else { 527251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 528251730Sadrian } 529251730Sadrian pdiv_ant_conf->main_gaintb = 0; 530251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 531251730Sadrian break; 532251730Sadrian case (0x21): //LNA1 LNA2 533251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 534251730Sadrian pdiv_ant_conf->main_gaintb = 0; 535251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 536251730Sadrian break; 537251730Sadrian case (0x23): //LNA1 A+B 538251730Sadrian if ((antcomb->scan == 0) 539251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 540251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 541251730Sadrian } else { 542251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 543251730Sadrian } 544251730Sadrian pdiv_ant_conf->main_gaintb = 0; 545251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 546251730Sadrian break; 547251730Sadrian case (0x30): //A+B A-B 548251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 549251730Sadrian pdiv_ant_conf->main_gaintb = 0; 550251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 551251730Sadrian break; 552251730Sadrian case (0x31): //A+B LNA2 553251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 554251730Sadrian pdiv_ant_conf->main_gaintb = 0; 555251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 556251730Sadrian break; 557251730Sadrian case (0x32): //A+B LNA1 558251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 559251730Sadrian pdiv_ant_conf->main_gaintb = 0; 560251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 561251730Sadrian break; 562251730Sadrian default: 563251730Sadrian break; 564251730Sadrian } 565251730Sadrian } else if (config_group == HAL_ANTDIV_CONFIG_GROUP_2) { 566251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) 567251730Sadrian | pdiv_ant_conf->alt_lna_conf) { 568251730Sadrian case (0x01): //A-B LNA2 569251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 570251730Sadrian pdiv_ant_conf->main_gaintb = 0; 571251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 572251730Sadrian break; 573251730Sadrian case (0x02): //A-B LNA1 574251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 575251730Sadrian pdiv_ant_conf->main_gaintb = 0; 576251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 577251730Sadrian break; 578251730Sadrian case (0x03): //A-B A+B 579251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 580251730Sadrian pdiv_ant_conf->main_gaintb = 0; 581251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 582251730Sadrian break; 583251730Sadrian case (0x10): //LNA2 A-B 584251730Sadrian if ((antcomb->scan == 0) 585251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 586251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 587251730Sadrian } else { 588251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 589251730Sadrian } 590251730Sadrian pdiv_ant_conf->main_gaintb = 0; 591251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 592251730Sadrian break; 593251730Sadrian case (0x12): //LNA2 LNA1 594251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 595251730Sadrian pdiv_ant_conf->main_gaintb = 0; 596251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 597251730Sadrian break; 598251730Sadrian case (0x13): //LNA2 A+B 599251730Sadrian if ((antcomb->scan == 0) 600251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 601251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 602251730Sadrian } else { 603251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 604251730Sadrian } 605251730Sadrian pdiv_ant_conf->main_gaintb = 0; 606251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 607251730Sadrian break; 608251730Sadrian case (0x20): //LNA1 A-B 609251730Sadrian if ((antcomb->scan == 0) 610251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 611251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 612251730Sadrian } else { 613251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 614251730Sadrian } 615251730Sadrian pdiv_ant_conf->main_gaintb = 0; 616251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 617251730Sadrian break; 618251730Sadrian case (0x21): //LNA1 LNA2 619251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 620251730Sadrian pdiv_ant_conf->main_gaintb = 0; 621251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 622251730Sadrian break; 623251730Sadrian case (0x23): //LNA1 A+B 624251730Sadrian if ((antcomb->scan == 0) 625251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 626251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 627251730Sadrian } else { 628251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 629251730Sadrian } 630251730Sadrian pdiv_ant_conf->main_gaintb = 0; 631251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 632251730Sadrian break; 633251730Sadrian case (0x30): //A+B A-B 634251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 635251730Sadrian pdiv_ant_conf->main_gaintb = 0; 636251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 637251730Sadrian break; 638251730Sadrian case (0x31): //A+B LNA2 639251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 640251730Sadrian pdiv_ant_conf->main_gaintb = 0; 641251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 642251730Sadrian break; 643251730Sadrian case (0x32): //A+B LNA1 644251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 645251730Sadrian pdiv_ant_conf->main_gaintb = 0; 646251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 647251730Sadrian break; 648251730Sadrian default: 649251730Sadrian break; 650251730Sadrian } 651251730Sadrian } else { /* DEFAULT_ANTDIV_CONFIG_GROUP */ 652251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) | pdiv_ant_conf->alt_lna_conf) { 653251730Sadrian case (0x01): //A-B LNA2 654251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3b; 655251730Sadrian break; 656251730Sadrian case (0x02): //A-B LNA1 657251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3d; 658251730Sadrian break; 659251730Sadrian case (0x03): //A-B A+B 660251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 661251730Sadrian break; 662251730Sadrian case (0x10): //LNA2 A-B 663251730Sadrian pdiv_ant_conf->fast_div_bias = 0x7; 664251730Sadrian break; 665251730Sadrian case (0x12): //LNA2 LNA1 666251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 667251730Sadrian break; 668251730Sadrian case (0x13): //LNA2 A+B 669251730Sadrian pdiv_ant_conf->fast_div_bias = 0x7; 670251730Sadrian break; 671251730Sadrian case (0x20): //LNA1 A-B 672251730Sadrian pdiv_ant_conf->fast_div_bias = 0x6; 673251730Sadrian break; 674251730Sadrian case (0x21): //LNA1 LNA2 675251730Sadrian pdiv_ant_conf->fast_div_bias = 0x0; 676251730Sadrian break; 677251730Sadrian case (0x23): //LNA1 A+B 678251730Sadrian pdiv_ant_conf->fast_div_bias = 0x6; 679251730Sadrian break; 680251730Sadrian case (0x30): //A+B A-B 681251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 682251730Sadrian break; 683251730Sadrian case (0x31): //A+B LNA2 684251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3b; 685251730Sadrian break; 686251730Sadrian case (0x32): //A+B LNA1 687251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3d; 688251730Sadrian break; 689251730Sadrian default: 690251730Sadrian break; 691251730Sadrian } 692251655Sadrian } 693251655Sadrian} 694251655Sadrian 695251730Sadrian/* 696251730Sadrian * AR9485/AR933x TODO: 697251730Sadrian * + Select a ratio based on whether RSSI is low or not; but I need 698251730Sadrian * to figure out what "low_rssi_th" is sourced from. 699251730Sadrian * + What's ath_ant_div_comb_alt_check() in the reference driver do? 700251730Sadrian * + .. and there's likely a bunch of other things to include in this. 701251730Sadrian */ 702251730Sadrian 703251655Sadrian/* Antenna diversity and combining */ 704251655Sadrianvoid 705251655Sadrianath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs, 706251655Sadrian unsigned long ticks, int hz) 707251655Sadrian{ 708251655Sadrian HAL_ANT_COMB_CONFIG div_ant_conf; 709251655Sadrian struct if_ath_ant_comb_state *antcomb = sc->sc_lna_div; 710251655Sadrian int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; 711251655Sadrian int curr_main_set, curr_bias; 712251655Sadrian int main_rssi = rs->rs_rssi_ctl[0]; 713251655Sadrian int alt_rssi = rs->rs_rssi_ctl[1]; 714251655Sadrian int rx_ant_conf, main_ant_conf, alt_ant_conf; 715251655Sadrian HAL_BOOL short_scan = AH_FALSE; 716251655Sadrian 717251655Sadrian rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK; 718251655Sadrian main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK; 719251655Sadrian alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK; 720251655Sadrian 721251655Sadrian#if 0 722251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, 723251655Sadrian "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; " 724251655Sadrian "FastDiv: %d\n", 725251655Sadrian __func__, 726251655Sadrian main_rssi, 727251655Sadrian alt_rssi, 728251655Sadrian main_ant_conf, 729251655Sadrian alt_ant_conf, 730251655Sadrian rx_ant_conf, 731251655Sadrian !!(rs->rs_rssi_ctl[2] & 0x80), 732251655Sadrian !!(rs->rs_rssi_ctl[2] & 0x40), 733251655Sadrian !!(rs->rs_rssi_ext[2] & 0x40)); 734251655Sadrian#endif 735251655Sadrian 736251655Sadrian /* 737251655Sadrian * If LNA diversity combining isn't enabled, don't run this. 738251655Sadrian */ 739251655Sadrian if (! sc->sc_dolnadiv) 740251655Sadrian return; 741251655Sadrian 742251655Sadrian /* 743251655Sadrian * XXX this is ugly, but the HAL code attaches the 744251655Sadrian * LNA diversity to the TX antenna settings. 745251655Sadrian * I don't know why. 746251655Sadrian */ 747251655Sadrian if (sc->sc_txantenna != HAL_ANT_VARIABLE) 748251655Sadrian return; 749251655Sadrian 750251655Sadrian /* Record packet only when alt_rssi is positive */ 751251655Sadrian if (main_rssi > 0 && alt_rssi > 0) { 752251655Sadrian antcomb->total_pkt_count++; 753251655Sadrian antcomb->main_total_rssi += main_rssi; 754251655Sadrian antcomb->alt_total_rssi += alt_rssi; 755251655Sadrian if (main_ant_conf == rx_ant_conf) 756251655Sadrian antcomb->main_recv_cnt++; 757251655Sadrian else 758251655Sadrian antcomb->alt_recv_cnt++; 759251655Sadrian } 760251655Sadrian 761251655Sadrian /* Short scan check */ 762251655Sadrian if (antcomb->scan && antcomb->alt_good) { 763251655Sadrian if (time_after(ticks, antcomb->scan_start_time + 764251655Sadrian msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) 765251655Sadrian short_scan = AH_TRUE; 766251655Sadrian else 767251655Sadrian if (antcomb->total_pkt_count == 768251655Sadrian ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { 769251655Sadrian alt_ratio = ((antcomb->alt_recv_cnt * 100) / 770251655Sadrian antcomb->total_pkt_count); 771251655Sadrian if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) 772251655Sadrian short_scan = AH_TRUE; 773251655Sadrian } 774251655Sadrian } 775251655Sadrian 776251730Sadrian#if 0 777251730Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, 778251730Sadrian "%s: total pkt=%d, aggr=%d, short_scan=%d\n", 779251730Sadrian __func__, 780251730Sadrian antcomb->total_pkt_count, 781251730Sadrian !! (rs->rs_moreaggr), 782251730Sadrian !! (short_scan)); 783251730Sadrian#endif 784251730Sadrian 785251655Sadrian if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || 786251655Sadrian rs->rs_moreaggr) && !short_scan) 787251655Sadrian return; 788251655Sadrian 789251655Sadrian if (antcomb->total_pkt_count) { 790251655Sadrian alt_ratio = ((antcomb->alt_recv_cnt * 100) / 791251655Sadrian antcomb->total_pkt_count); 792251655Sadrian main_rssi_avg = (antcomb->main_total_rssi / 793251655Sadrian antcomb->total_pkt_count); 794251655Sadrian alt_rssi_avg = (antcomb->alt_total_rssi / 795251655Sadrian antcomb->total_pkt_count); 796251655Sadrian } 797251655Sadrian 798251655Sadrian OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf)); 799251655Sadrian 800251655Sadrian ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf); 801251655Sadrian curr_alt_set = div_ant_conf.alt_lna_conf; 802251655Sadrian curr_main_set = div_ant_conf.main_lna_conf; 803251655Sadrian curr_bias = div_ant_conf.fast_div_bias; 804251655Sadrian 805251655Sadrian antcomb->count++; 806251655Sadrian 807251655Sadrian if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { 808251655Sadrian if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 809251655Sadrian ath_lnaconf_alt_good_scan(antcomb, &div_ant_conf, 810251655Sadrian main_rssi_avg); 811251655Sadrian antcomb->alt_good = AH_TRUE; 812251655Sadrian } else { 813251655Sadrian antcomb->alt_good = AH_FALSE; 814251655Sadrian } 815251655Sadrian 816251655Sadrian antcomb->count = 0; 817251655Sadrian antcomb->scan = AH_TRUE; 818251655Sadrian antcomb->scan_not_start = AH_TRUE; 819251655Sadrian } 820251655Sadrian 821251655Sadrian if (!antcomb->scan) { 822251655Sadrian if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 823251655Sadrian if (curr_alt_set == HAL_ANT_DIV_COMB_LNA2) { 824251655Sadrian /* Switch main and alt LNA */ 825251655Sadrian div_ant_conf.main_lna_conf = 826251655Sadrian HAL_ANT_DIV_COMB_LNA2; 827251655Sadrian div_ant_conf.alt_lna_conf = 828251655Sadrian HAL_ANT_DIV_COMB_LNA1; 829251655Sadrian } else if (curr_alt_set == HAL_ANT_DIV_COMB_LNA1) { 830251655Sadrian div_ant_conf.main_lna_conf = 831251655Sadrian HAL_ANT_DIV_COMB_LNA1; 832251655Sadrian div_ant_conf.alt_lna_conf = 833251655Sadrian HAL_ANT_DIV_COMB_LNA2; 834251655Sadrian } 835251655Sadrian 836251655Sadrian goto div_comb_done; 837251655Sadrian } else if ((curr_alt_set != HAL_ANT_DIV_COMB_LNA1) && 838251655Sadrian (curr_alt_set != HAL_ANT_DIV_COMB_LNA2)) { 839251655Sadrian /* Set alt to another LNA */ 840251655Sadrian if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) 841251655Sadrian div_ant_conf.alt_lna_conf = 842251655Sadrian HAL_ANT_DIV_COMB_LNA1; 843251655Sadrian else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) 844251655Sadrian div_ant_conf.alt_lna_conf = 845251655Sadrian HAL_ANT_DIV_COMB_LNA2; 846251655Sadrian 847251655Sadrian goto div_comb_done; 848251655Sadrian } 849251655Sadrian 850251655Sadrian if ((alt_rssi_avg < (main_rssi_avg + 851251730Sadrian antcomb->lna1_lna2_delta))) 852251655Sadrian goto div_comb_done; 853251655Sadrian } 854251655Sadrian 855251655Sadrian if (!antcomb->scan_not_start) { 856251655Sadrian switch (curr_alt_set) { 857251655Sadrian case HAL_ANT_DIV_COMB_LNA2: 858251655Sadrian antcomb->rssi_lna2 = alt_rssi_avg; 859251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 860251655Sadrian antcomb->scan = AH_TRUE; 861251655Sadrian /* set to A+B */ 862251655Sadrian div_ant_conf.main_lna_conf = 863251655Sadrian HAL_ANT_DIV_COMB_LNA1; 864251655Sadrian div_ant_conf.alt_lna_conf = 865251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 866251655Sadrian break; 867251655Sadrian case HAL_ANT_DIV_COMB_LNA1: 868251655Sadrian antcomb->rssi_lna1 = alt_rssi_avg; 869251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 870251655Sadrian antcomb->scan = AH_TRUE; 871251655Sadrian /* set to A+B */ 872251655Sadrian div_ant_conf.main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 873251655Sadrian div_ant_conf.alt_lna_conf = 874251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 875251655Sadrian break; 876251655Sadrian case HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2: 877251655Sadrian antcomb->rssi_add = alt_rssi_avg; 878251655Sadrian antcomb->scan = AH_TRUE; 879251655Sadrian /* set to A-B */ 880251655Sadrian div_ant_conf.alt_lna_conf = 881251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 882251655Sadrian break; 883251655Sadrian case HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2: 884251655Sadrian antcomb->rssi_sub = alt_rssi_avg; 885251655Sadrian antcomb->scan = AH_FALSE; 886251655Sadrian if (antcomb->rssi_lna2 > 887251655Sadrian (antcomb->rssi_lna1 + 888251655Sadrian ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { 889251655Sadrian /* use LNA2 as main LNA */ 890251655Sadrian if ((antcomb->rssi_add > antcomb->rssi_lna1) && 891251655Sadrian (antcomb->rssi_add > antcomb->rssi_sub)) { 892251655Sadrian /* set to A+B */ 893251655Sadrian div_ant_conf.main_lna_conf = 894251655Sadrian HAL_ANT_DIV_COMB_LNA2; 895251655Sadrian div_ant_conf.alt_lna_conf = 896251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 897251655Sadrian } else if (antcomb->rssi_sub > 898251655Sadrian antcomb->rssi_lna1) { 899251655Sadrian /* set to A-B */ 900251655Sadrian div_ant_conf.main_lna_conf = 901251655Sadrian HAL_ANT_DIV_COMB_LNA2; 902251655Sadrian div_ant_conf.alt_lna_conf = 903251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 904251655Sadrian } else { 905251655Sadrian /* set to LNA1 */ 906251655Sadrian div_ant_conf.main_lna_conf = 907251655Sadrian HAL_ANT_DIV_COMB_LNA2; 908251655Sadrian div_ant_conf.alt_lna_conf = 909251655Sadrian HAL_ANT_DIV_COMB_LNA1; 910251655Sadrian } 911251655Sadrian } else { 912251655Sadrian /* use LNA1 as main LNA */ 913251655Sadrian if ((antcomb->rssi_add > antcomb->rssi_lna2) && 914251655Sadrian (antcomb->rssi_add > antcomb->rssi_sub)) { 915251655Sadrian /* set to A+B */ 916251655Sadrian div_ant_conf.main_lna_conf = 917251655Sadrian HAL_ANT_DIV_COMB_LNA1; 918251655Sadrian div_ant_conf.alt_lna_conf = 919251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 920251655Sadrian } else if (antcomb->rssi_sub > 921251655Sadrian antcomb->rssi_lna1) { 922251655Sadrian /* set to A-B */ 923251655Sadrian div_ant_conf.main_lna_conf = 924251655Sadrian HAL_ANT_DIV_COMB_LNA1; 925251655Sadrian div_ant_conf.alt_lna_conf = 926251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 927251655Sadrian } else { 928251655Sadrian /* set to LNA2 */ 929251655Sadrian div_ant_conf.main_lna_conf = 930251655Sadrian HAL_ANT_DIV_COMB_LNA1; 931251655Sadrian div_ant_conf.alt_lna_conf = 932251655Sadrian HAL_ANT_DIV_COMB_LNA2; 933251655Sadrian } 934251655Sadrian } 935251655Sadrian break; 936251655Sadrian default: 937251655Sadrian break; 938251655Sadrian } 939251655Sadrian } else { 940251655Sadrian if (!antcomb->alt_good) { 941251655Sadrian antcomb->scan_not_start = AH_FALSE; 942251655Sadrian /* Set alt to another LNA */ 943251655Sadrian if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) { 944251655Sadrian div_ant_conf.main_lna_conf = 945251655Sadrian HAL_ANT_DIV_COMB_LNA2; 946251655Sadrian div_ant_conf.alt_lna_conf = 947251655Sadrian HAL_ANT_DIV_COMB_LNA1; 948251655Sadrian } else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) { 949251655Sadrian div_ant_conf.main_lna_conf = 950251655Sadrian HAL_ANT_DIV_COMB_LNA1; 951251655Sadrian div_ant_conf.alt_lna_conf = 952251655Sadrian HAL_ANT_DIV_COMB_LNA2; 953251655Sadrian } 954251655Sadrian goto div_comb_done; 955251655Sadrian } 956251655Sadrian } 957251655Sadrian 958251655Sadrian ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, 959251655Sadrian main_rssi_avg, alt_rssi_avg, 960251655Sadrian alt_ratio); 961251655Sadrian 962251655Sadrian antcomb->quick_scan_cnt++; 963251655Sadrian 964251655Sadriandiv_comb_done: 965251730Sadrian#if 0 966251655Sadrian ath_ant_div_conf_fast_divbias(&div_ant_conf); 967251730Sadrian#endif 968251655Sadrian 969251730Sadrian ath_ant_adjust_fast_divbias(antcomb, 970251730Sadrian alt_ratio, 971251730Sadrian ATH_ANT_DIV_COMB_ALT_ANT_RATIO, 972251730Sadrian div_ant_conf.antdiv_configgroup, 973251730Sadrian &div_ant_conf); 974251730Sadrian 975251655Sadrian ath_hal_div_comb_conf_set(sc->sc_ah, &div_ant_conf); 976251655Sadrian 977251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n", 978251655Sadrian __func__, antcomb->total_pkt_count); 979251655Sadrian 980251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n", 981251655Sadrian __func__, antcomb->main_total_rssi); 982251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n", 983251655Sadrian __func__, antcomb->alt_total_rssi); 984251655Sadrian 985251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n", 986251655Sadrian __func__, main_rssi_avg); 987251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n", 988251655Sadrian __func__, alt_rssi_avg); 989251655Sadrian 990251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n", 991251655Sadrian __func__, antcomb->main_recv_cnt); 992251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n", 993251655Sadrian __func__, antcomb->alt_recv_cnt); 994251655Sadrian 995251655Sadrian// if (curr_alt_set != div_ant_conf.alt_lna_conf) 996251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n", 997251655Sadrian __func__, curr_alt_set, div_ant_conf.alt_lna_conf); 998251655Sadrian// if (curr_main_set != div_ant_conf.main_lna_conf) 999251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n", 1000251655Sadrian __func__, curr_main_set, div_ant_conf.main_lna_conf); 1001251655Sadrian// if (curr_bias != div_ant_conf.fast_div_bias) 1002251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n", 1003251655Sadrian __func__, curr_bias, div_ant_conf.fast_div_bias); 1004251655Sadrian 1005251655Sadrian antcomb->scan_start_time = ticks; 1006251655Sadrian antcomb->total_pkt_count = 0; 1007251655Sadrian antcomb->main_total_rssi = 0; 1008251655Sadrian antcomb->alt_total_rssi = 0; 1009251655Sadrian antcomb->main_recv_cnt = 0; 1010251655Sadrian antcomb->alt_recv_cnt = 0; 1011251655Sadrian} 1012251655Sadrian 1013