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: releng/11.0/sys/dev/ath/if_ath_lna_div.c 298939 2016-05-02 19:56:48Z pfg $ 30251655Sadrian */ 31251655Sadrian#include <sys/cdefs.h> 32251655Sadrian__FBSDID("$FreeBSD: releng/11.0/sys/dev/ath/if_ath_lna_div.c 298939 2016-05-02 19:56:48Z pfg $"); 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> 47257176Sglebius#include <sys/malloc.h> 48251655Sadrian#include <sys/mutex.h> 49251655Sadrian#include <sys/errno.h> 50251655Sadrian 51251655Sadrian#include <machine/bus.h> 52251655Sadrian#include <machine/resource.h> 53251655Sadrian#include <sys/bus.h> 54251655Sadrian 55251655Sadrian#include <sys/socket.h> 56251655Sadrian 57251655Sadrian#include <net/if.h> 58257176Sglebius#include <net/if_var.h> 59251655Sadrian#include <net/if_media.h> 60251655Sadrian#include <net/if_arp.h> 61251655Sadrian#include <net/ethernet.h> /* XXX for ether_sprintf */ 62251655Sadrian 63251655Sadrian#include <net80211/ieee80211_var.h> 64251655Sadrian 65251655Sadrian#include <net/bpf.h> 66251655Sadrian 67251655Sadrian#ifdef INET 68251655Sadrian#include <netinet/in.h> 69251655Sadrian#include <netinet/if_ether.h> 70251655Sadrian#endif 71251655Sadrian 72251655Sadrian#include <dev/ath/if_athvar.h> 73251655Sadrian#include <dev/ath/if_ath_debug.h> 74251655Sadrian#include <dev/ath/if_ath_lna_div.h> 75251655Sadrian 76298939Spfg/* Linux compatibility macros */ 77251655Sadrian/* 78251655Sadrian * XXX these don't handle rounding, underflow, overflow, wrapping! 79251655Sadrian */ 80251655Sadrian#define msecs_to_jiffies(a) ( (a) * hz / 1000 ) 81251655Sadrian 82251655Sadrian/* 83251655Sadrian * Methods which are required 84251655Sadrian */ 85251655Sadrian 86251655Sadrian/* 87251655Sadrian * Attach the LNA diversity to the given interface 88251655Sadrian */ 89251655Sadrianint 90251655Sadrianath_lna_div_attach(struct ath_softc *sc) 91251655Sadrian{ 92251655Sadrian struct if_ath_ant_comb_state *ss; 93251730Sadrian HAL_ANT_COMB_CONFIG div_ant_conf; 94251655Sadrian 95251655Sadrian /* Only do this if diversity is enabled */ 96251655Sadrian if (! ath_hal_hasdivantcomb(sc->sc_ah)) 97251655Sadrian return (0); 98251655Sadrian 99251655Sadrian ss = malloc(sizeof(struct if_ath_ant_comb_state), 100251655Sadrian M_TEMP, M_WAITOK | M_ZERO); 101251655Sadrian if (ss == NULL) { 102251655Sadrian device_printf(sc->sc_dev, "%s: failed to allocate\n", 103251655Sadrian __func__); 104251655Sadrian /* Don't fail at this point */ 105251655Sadrian return (0); 106251655Sadrian } 107251655Sadrian 108251730Sadrian /* Fetch the hardware configuration */ 109251730Sadrian OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf)); 110251730Sadrian ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf); 111251730Sadrian 112251730Sadrian /* Figure out what the hardware specific bits should be */ 113251730Sadrian if ((div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_1) || 114251730Sadrian (div_ant_conf.antdiv_configgroup == HAL_ANTDIV_CONFIG_GROUP_2)) { 115251730Sadrian ss->lna1_lna2_delta = -9; 116251730Sadrian } else { 117251730Sadrian ss->lna1_lna2_delta = -3; 118251730Sadrian } 119251730Sadrian 120251655Sadrian /* Let's flip this on */ 121251655Sadrian sc->sc_lna_div = ss; 122251655Sadrian sc->sc_dolnadiv = 1; 123251655Sadrian 124251655Sadrian return (0); 125251655Sadrian} 126251655Sadrian 127251655Sadrian/* 128251655Sadrian * Detach the LNA diversity state from the given interface 129251655Sadrian */ 130251655Sadrianint 131251655Sadrianath_lna_div_detach(struct ath_softc *sc) 132251655Sadrian{ 133251655Sadrian if (sc->sc_lna_div != NULL) { 134251655Sadrian free(sc->sc_lna_div, M_TEMP); 135251655Sadrian sc->sc_lna_div = NULL; 136251655Sadrian } 137251655Sadrian sc->sc_dolnadiv = 0; 138251655Sadrian return (0); 139251655Sadrian} 140251655Sadrian 141251655Sadrian/* 142251655Sadrian * Enable LNA diversity on the current channel if it's required. 143251655Sadrian */ 144251655Sadrianint 145251655Sadrianath_lna_div_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) 146251655Sadrian{ 147251655Sadrian 148251655Sadrian return (0); 149251655Sadrian} 150251655Sadrian 151251655Sadrian/* 152251655Sadrian * Handle ioctl requests from the diagnostic interface. 153251655Sadrian * 154251655Sadrian * The initial part of this code resembles ath_ioctl_diag(); 155251655Sadrian * it's likely a good idea to reduce duplication between 156251655Sadrian * these two routines. 157251655Sadrian */ 158251655Sadrianint 159251655Sadrianath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad) 160251655Sadrian{ 161251655Sadrian unsigned int id = ad->ad_id & ATH_DIAG_ID; 162251655Sadrian void *indata = NULL; 163251655Sadrian void *outdata = NULL; 164251655Sadrian u_int32_t insize = ad->ad_in_size; 165251655Sadrian u_int32_t outsize = ad->ad_out_size; 166251655Sadrian int error = 0; 167251655Sadrian// int val; 168251655Sadrian 169251655Sadrian if (ad->ad_id & ATH_DIAG_IN) { 170251655Sadrian /* 171251655Sadrian * Copy in data. 172251655Sadrian */ 173251655Sadrian indata = malloc(insize, M_TEMP, M_NOWAIT); 174251655Sadrian if (indata == NULL) { 175251655Sadrian error = ENOMEM; 176251655Sadrian goto bad; 177251655Sadrian } 178251655Sadrian error = copyin(ad->ad_in_data, indata, insize); 179251655Sadrian if (error) 180251655Sadrian goto bad; 181251655Sadrian } 182251655Sadrian if (ad->ad_id & ATH_DIAG_DYN) { 183251655Sadrian /* 184251655Sadrian * Allocate a buffer for the results (otherwise the HAL 185251655Sadrian * returns a pointer to a buffer where we can read the 186251655Sadrian * results). Note that we depend on the HAL leaving this 187251655Sadrian * pointer for us to use below in reclaiming the buffer; 188251655Sadrian * may want to be more defensive. 189251655Sadrian */ 190251655Sadrian outdata = malloc(outsize, M_TEMP, M_NOWAIT); 191251655Sadrian if (outdata == NULL) { 192251655Sadrian error = ENOMEM; 193251655Sadrian goto bad; 194251655Sadrian } 195251655Sadrian } 196251655Sadrian switch (id) { 197251655Sadrian default: 198251655Sadrian error = EINVAL; 199251655Sadrian } 200251655Sadrian if (outsize < ad->ad_out_size) 201251655Sadrian ad->ad_out_size = outsize; 202251655Sadrian if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 203251655Sadrian error = EFAULT; 204251655Sadrianbad: 205251655Sadrian if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 206251655Sadrian free(indata, M_TEMP); 207251655Sadrian if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 208251655Sadrian free(outdata, M_TEMP); 209251655Sadrian return (error); 210251655Sadrian} 211251655Sadrian 212272292Sadrian/* 213272292Sadrian * XXX need to low_rssi_thresh config from ath9k, to support CUS198 214272292Sadrian * antenna diversity correctly. 215272292Sadrian */ 216251655Sadrianstatic HAL_BOOL 217251655Sadrianath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta, 218251655Sadrian int main_rssi_avg, int alt_rssi_avg, int pkt_count) 219251655Sadrian{ 220251655Sadrian return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 221251655Sadrian (alt_rssi_avg > main_rssi_avg + maxdelta)) || 222251655Sadrian (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); 223251655Sadrian} 224251655Sadrian 225251655Sadrianstatic void 226251655Sadrianath_lnaconf_alt_good_scan(struct if_ath_ant_comb_state *antcomb, 227251655Sadrian HAL_ANT_COMB_CONFIG *ant_conf, int main_rssi_avg) 228251655Sadrian{ 229251655Sadrian antcomb->quick_scan_cnt = 0; 230251655Sadrian 231251655Sadrian if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA2) 232251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 233251655Sadrian else if (ant_conf->main_lna_conf == HAL_ANT_DIV_COMB_LNA1) 234251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 235251655Sadrian 236251655Sadrian switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { 237251655Sadrian case (0x10): /* LNA2 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_LNA1; 242251655Sadrian break; 243251655Sadrian case (0x20): /* LNA1 A-B */ 244251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 245251655Sadrian antcomb->first_quick_scan_conf = 246251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 247251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 248251655Sadrian break; 249251655Sadrian case (0x21): /* LNA1 LNA2 */ 250251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA2; 251251655Sadrian antcomb->first_quick_scan_conf = 252251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 253251655Sadrian antcomb->second_quick_scan_conf = 254251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 255251655Sadrian break; 256251655Sadrian case (0x12): /* LNA2 LNA1 */ 257251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1; 258251655Sadrian antcomb->first_quick_scan_conf = 259251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 260251655Sadrian antcomb->second_quick_scan_conf = 261251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 262251655Sadrian break; 263251655Sadrian case (0x13): /* LNA2 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_LNA1; 268251655Sadrian break; 269251655Sadrian case (0x23): /* LNA1 A+B */ 270251655Sadrian antcomb->main_conf = HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 271251655Sadrian antcomb->first_quick_scan_conf = 272251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 273251655Sadrian antcomb->second_quick_scan_conf = HAL_ANT_DIV_COMB_LNA2; 274251655Sadrian break; 275251655Sadrian default: 276251655Sadrian break; 277251655Sadrian } 278251655Sadrian} 279251655Sadrian 280251655Sadrianstatic void 281251655Sadrianath_select_ant_div_from_quick_scan(struct if_ath_ant_comb_state *antcomb, 282251655Sadrian HAL_ANT_COMB_CONFIG *div_ant_conf, int main_rssi_avg, 283251655Sadrian int alt_rssi_avg, int alt_ratio) 284251655Sadrian{ 285251655Sadrian /* alt_good */ 286251655Sadrian switch (antcomb->quick_scan_cnt) { 287251655Sadrian case 0: 288251655Sadrian /* set alt to main, and alt to first conf */ 289251655Sadrian div_ant_conf->main_lna_conf = antcomb->main_conf; 290251655Sadrian div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; 291251655Sadrian break; 292251655Sadrian case 1: 293251655Sadrian /* set alt to main, and alt to first conf */ 294251655Sadrian div_ant_conf->main_lna_conf = antcomb->main_conf; 295251655Sadrian div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; 296251655Sadrian antcomb->rssi_first = main_rssi_avg; 297251655Sadrian antcomb->rssi_second = alt_rssi_avg; 298251655Sadrian 299251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 300251655Sadrian /* main is LNA1 */ 301251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 302251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 303251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 304251655Sadrian main_rssi_avg, alt_rssi_avg, 305251655Sadrian antcomb->total_pkt_count)) 306251655Sadrian antcomb->first_ratio = AH_TRUE; 307251655Sadrian else 308251655Sadrian antcomb->first_ratio = AH_FALSE; 309251655Sadrian } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 310251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 311251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 312251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 313251655Sadrian main_rssi_avg, alt_rssi_avg, 314251655Sadrian antcomb->total_pkt_count)) 315251655Sadrian antcomb->first_ratio = AH_TRUE; 316251655Sadrian else 317251655Sadrian antcomb->first_ratio = AH_FALSE; 318251655Sadrian } else { 319251655Sadrian if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 320251655Sadrian (alt_rssi_avg > main_rssi_avg + 321251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 322251655Sadrian (alt_rssi_avg > main_rssi_avg)) && 323251655Sadrian (antcomb->total_pkt_count > 50)) 324251655Sadrian antcomb->first_ratio = AH_TRUE; 325251655Sadrian else 326251655Sadrian antcomb->first_ratio = AH_FALSE; 327251655Sadrian } 328251655Sadrian break; 329251655Sadrian case 2: 330251655Sadrian antcomb->alt_good = AH_FALSE; 331251655Sadrian antcomb->scan_not_start = AH_FALSE; 332251655Sadrian antcomb->scan = AH_FALSE; 333251655Sadrian antcomb->rssi_first = main_rssi_avg; 334251655Sadrian antcomb->rssi_third = alt_rssi_avg; 335251655Sadrian 336251655Sadrian if (antcomb->second_quick_scan_conf == HAL_ANT_DIV_COMB_LNA1) 337251655Sadrian antcomb->rssi_lna1 = alt_rssi_avg; 338251655Sadrian else if (antcomb->second_quick_scan_conf == 339251655Sadrian HAL_ANT_DIV_COMB_LNA2) 340251655Sadrian antcomb->rssi_lna2 = alt_rssi_avg; 341251655Sadrian else if (antcomb->second_quick_scan_conf == 342251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2) { 343251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) 344251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 345251655Sadrian else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) 346251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 347251655Sadrian } 348251655Sadrian 349251655Sadrian if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + 350251655Sadrian ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) 351251655Sadrian div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 352251655Sadrian else 353251655Sadrian div_ant_conf->main_lna_conf = HAL_ANT_DIV_COMB_LNA1; 354251655Sadrian 355251655Sadrian if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) { 356251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 357251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI, 358251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 359251655Sadrian main_rssi_avg, alt_rssi_avg, 360251655Sadrian antcomb->total_pkt_count)) 361251655Sadrian antcomb->second_ratio = AH_TRUE; 362251655Sadrian else 363251655Sadrian antcomb->second_ratio = AH_FALSE; 364251655Sadrian } else if (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2) { 365251655Sadrian if (ath_is_alt_ant_ratio_better(alt_ratio, 366251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_MID, 367251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, 368251655Sadrian main_rssi_avg, alt_rssi_avg, 369251655Sadrian antcomb->total_pkt_count)) 370251655Sadrian antcomb->second_ratio = AH_TRUE; 371251655Sadrian else 372251655Sadrian antcomb->second_ratio = AH_FALSE; 373251655Sadrian } else { 374251655Sadrian if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && 375251655Sadrian (alt_rssi_avg > main_rssi_avg + 376251655Sadrian ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || 377251655Sadrian (alt_rssi_avg > main_rssi_avg)) && 378251655Sadrian (antcomb->total_pkt_count > 50)) 379251655Sadrian antcomb->second_ratio = AH_TRUE; 380251655Sadrian else 381251655Sadrian antcomb->second_ratio = AH_FALSE; 382251655Sadrian } 383251655Sadrian 384251655Sadrian /* set alt to the conf with maximun ratio */ 385251655Sadrian if (antcomb->first_ratio && antcomb->second_ratio) { 386251655Sadrian if (antcomb->rssi_second > antcomb->rssi_third) { 387251655Sadrian /* first alt*/ 388251655Sadrian if ((antcomb->first_quick_scan_conf == 389251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 390251655Sadrian (antcomb->first_quick_scan_conf == 391251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 392251655Sadrian /* Set alt LNA1 or LNA2*/ 393251655Sadrian if (div_ant_conf->main_lna_conf == 394251655Sadrian HAL_ANT_DIV_COMB_LNA2) 395251655Sadrian div_ant_conf->alt_lna_conf = 396251655Sadrian HAL_ANT_DIV_COMB_LNA1; 397251655Sadrian else 398251655Sadrian div_ant_conf->alt_lna_conf = 399251655Sadrian HAL_ANT_DIV_COMB_LNA2; 400251655Sadrian else 401251655Sadrian /* Set alt to A+B or A-B */ 402251655Sadrian div_ant_conf->alt_lna_conf = 403251655Sadrian antcomb->first_quick_scan_conf; 404251655Sadrian } else if ((antcomb->second_quick_scan_conf == 405251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 406251655Sadrian (antcomb->second_quick_scan_conf == 407251655Sadrian HAL_ANT_DIV_COMB_LNA2)) { 408251655Sadrian /* Set alt LNA1 or LNA2 */ 409251655Sadrian if (div_ant_conf->main_lna_conf == 410251655Sadrian HAL_ANT_DIV_COMB_LNA2) 411251655Sadrian div_ant_conf->alt_lna_conf = 412251655Sadrian HAL_ANT_DIV_COMB_LNA1; 413251655Sadrian else 414251655Sadrian div_ant_conf->alt_lna_conf = 415251655Sadrian HAL_ANT_DIV_COMB_LNA2; 416251655Sadrian } else { 417251655Sadrian /* Set alt to A+B or A-B */ 418251655Sadrian div_ant_conf->alt_lna_conf = 419251655Sadrian antcomb->second_quick_scan_conf; 420251655Sadrian } 421251655Sadrian } else if (antcomb->first_ratio) { 422251655Sadrian /* first alt */ 423251655Sadrian if ((antcomb->first_quick_scan_conf == 424251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 425251655Sadrian (antcomb->first_quick_scan_conf == 426251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 427251655Sadrian /* Set alt LNA1 or LNA2 */ 428251655Sadrian if (div_ant_conf->main_lna_conf == 429251655Sadrian HAL_ANT_DIV_COMB_LNA2) 430251655Sadrian div_ant_conf->alt_lna_conf = 431251655Sadrian HAL_ANT_DIV_COMB_LNA1; 432251655Sadrian else 433251655Sadrian div_ant_conf->alt_lna_conf = 434251655Sadrian HAL_ANT_DIV_COMB_LNA2; 435251655Sadrian else 436251655Sadrian /* Set alt to A+B or A-B */ 437251655Sadrian div_ant_conf->alt_lna_conf = 438251655Sadrian antcomb->first_quick_scan_conf; 439251655Sadrian } else if (antcomb->second_ratio) { 440251655Sadrian /* second alt */ 441251655Sadrian if ((antcomb->second_quick_scan_conf == 442251655Sadrian HAL_ANT_DIV_COMB_LNA1) || 443251655Sadrian (antcomb->second_quick_scan_conf == 444251655Sadrian HAL_ANT_DIV_COMB_LNA2)) 445251655Sadrian /* Set alt LNA1 or LNA2 */ 446251655Sadrian if (div_ant_conf->main_lna_conf == 447251655Sadrian HAL_ANT_DIV_COMB_LNA2) 448251655Sadrian div_ant_conf->alt_lna_conf = 449251655Sadrian HAL_ANT_DIV_COMB_LNA1; 450251655Sadrian else 451251655Sadrian div_ant_conf->alt_lna_conf = 452251655Sadrian HAL_ANT_DIV_COMB_LNA2; 453251655Sadrian else 454251655Sadrian /* Set alt to A+B or A-B */ 455251655Sadrian div_ant_conf->alt_lna_conf = 456251655Sadrian antcomb->second_quick_scan_conf; 457251655Sadrian } else { 458251655Sadrian /* main is largest */ 459251655Sadrian if ((antcomb->main_conf == HAL_ANT_DIV_COMB_LNA1) || 460251655Sadrian (antcomb->main_conf == HAL_ANT_DIV_COMB_LNA2)) 461251655Sadrian /* Set alt LNA1 or LNA2 */ 462251655Sadrian if (div_ant_conf->main_lna_conf == 463251655Sadrian HAL_ANT_DIV_COMB_LNA2) 464251655Sadrian div_ant_conf->alt_lna_conf = 465251655Sadrian HAL_ANT_DIV_COMB_LNA1; 466251655Sadrian else 467251655Sadrian div_ant_conf->alt_lna_conf = 468251655Sadrian HAL_ANT_DIV_COMB_LNA2; 469251655Sadrian else 470251655Sadrian /* Set alt to A+B or A-B */ 471251655Sadrian div_ant_conf->alt_lna_conf = antcomb->main_conf; 472251655Sadrian } 473251655Sadrian break; 474251655Sadrian default: 475251655Sadrian break; 476251655Sadrian } 477251655Sadrian} 478251655Sadrian 479251655Sadrianstatic void 480251730Sadrianath_ant_adjust_fast_divbias(struct if_ath_ant_comb_state *antcomb, 481251730Sadrian int alt_ratio, int alt_ant_ratio_th, u_int config_group, 482251730Sadrian HAL_ANT_COMB_CONFIG *pdiv_ant_conf) 483251655Sadrian{ 484251730Sadrian 485251730Sadrian if (config_group == HAL_ANTDIV_CONFIG_GROUP_1) { 486251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) 487251730Sadrian | pdiv_ant_conf->alt_lna_conf) { 488251730Sadrian case (0x01): //A-B LNA2 489251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 490251730Sadrian pdiv_ant_conf->main_gaintb = 0; 491251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 492251730Sadrian break; 493251730Sadrian case (0x02): //A-B LNA1 494251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 495251730Sadrian pdiv_ant_conf->main_gaintb = 0; 496251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 497251730Sadrian break; 498251730Sadrian case (0x03): //A-B A+B 499251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 500251730Sadrian pdiv_ant_conf->main_gaintb = 0; 501251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 502251730Sadrian break; 503251730Sadrian case (0x10): //LNA2 A-B 504251730Sadrian if ((antcomb->scan == 0) 505251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 506251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 507251730Sadrian } else { 508251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 509251730Sadrian } 510251730Sadrian pdiv_ant_conf->main_gaintb = 0; 511251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 512251730Sadrian break; 513251730Sadrian case (0x12): //LNA2 LNA1 514251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 515251730Sadrian pdiv_ant_conf->main_gaintb = 0; 516251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 517251730Sadrian break; 518251730Sadrian case (0x13): //LNA2 A+B 519251730Sadrian if ((antcomb->scan == 0) 520251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 521251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 522251730Sadrian } else { 523251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 524251730Sadrian } 525251730Sadrian pdiv_ant_conf->main_gaintb = 0; 526251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 527251730Sadrian break; 528251730Sadrian case (0x20): //LNA1 A-B 529251730Sadrian if ((antcomb->scan == 0) 530251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 531251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 532251730Sadrian } else { 533251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 534251730Sadrian } 535251730Sadrian pdiv_ant_conf->main_gaintb = 0; 536251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 537251730Sadrian break; 538251730Sadrian case (0x21): //LNA1 LNA2 539251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 540251730Sadrian pdiv_ant_conf->main_gaintb = 0; 541251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 542251730Sadrian break; 543251730Sadrian case (0x23): //LNA1 A+B 544251730Sadrian if ((antcomb->scan == 0) 545251730Sadrian && (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { 546251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3f; 547251730Sadrian } else { 548251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 549251730Sadrian } 550251730Sadrian pdiv_ant_conf->main_gaintb = 0; 551251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 552251730Sadrian break; 553251730Sadrian case (0x30): //A+B A-B 554251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 555251730Sadrian pdiv_ant_conf->main_gaintb = 0; 556251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 557251730Sadrian break; 558251730Sadrian case (0x31): //A+B LNA2 559251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 560251730Sadrian pdiv_ant_conf->main_gaintb = 0; 561251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 562251730Sadrian break; 563251730Sadrian case (0x32): //A+B LNA1 564251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 565251730Sadrian pdiv_ant_conf->main_gaintb = 0; 566251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 567251730Sadrian break; 568251730Sadrian default: 569251730Sadrian break; 570251730Sadrian } 571251730Sadrian } else if (config_group == HAL_ANTDIV_CONFIG_GROUP_2) { 572251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) 573251730Sadrian | pdiv_ant_conf->alt_lna_conf) { 574251730Sadrian case (0x01): //A-B LNA2 575251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 576251730Sadrian pdiv_ant_conf->main_gaintb = 0; 577251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 578251730Sadrian break; 579251730Sadrian case (0x02): //A-B LNA1 580251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 581251730Sadrian pdiv_ant_conf->main_gaintb = 0; 582251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 583251730Sadrian break; 584251730Sadrian case (0x03): //A-B A+B 585251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 586251730Sadrian pdiv_ant_conf->main_gaintb = 0; 587251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 588251730Sadrian break; 589251730Sadrian case (0x10): //LNA2 A-B 590251730Sadrian if ((antcomb->scan == 0) 591251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 592251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 593251730Sadrian } else { 594251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 595251730Sadrian } 596251730Sadrian pdiv_ant_conf->main_gaintb = 0; 597251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 598251730Sadrian break; 599251730Sadrian case (0x12): //LNA2 LNA1 600251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 601251730Sadrian pdiv_ant_conf->main_gaintb = 0; 602251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 603251730Sadrian break; 604251730Sadrian case (0x13): //LNA2 A+B 605251730Sadrian if ((antcomb->scan == 0) 606251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 607251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 608251730Sadrian } else { 609251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 610251730Sadrian } 611251730Sadrian pdiv_ant_conf->main_gaintb = 0; 612251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 613251730Sadrian break; 614251730Sadrian case (0x20): //LNA1 A-B 615251730Sadrian if ((antcomb->scan == 0) 616251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 617251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 618251730Sadrian } else { 619251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 620251730Sadrian } 621251730Sadrian pdiv_ant_conf->main_gaintb = 0; 622251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 623251730Sadrian break; 624251730Sadrian case (0x21): //LNA1 LNA2 625251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 626251730Sadrian pdiv_ant_conf->main_gaintb = 0; 627251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 628251730Sadrian break; 629251730Sadrian case (0x23): //LNA1 A+B 630251730Sadrian if ((antcomb->scan == 0) 631251730Sadrian && (alt_ratio > alt_ant_ratio_th)) { 632251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 633251730Sadrian } else { 634251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 635251730Sadrian } 636251730Sadrian pdiv_ant_conf->main_gaintb = 0; 637251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 638251730Sadrian break; 639251730Sadrian case (0x30): //A+B A-B 640251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 641251730Sadrian pdiv_ant_conf->main_gaintb = 0; 642251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 643251730Sadrian break; 644251730Sadrian case (0x31): //A+B LNA2 645251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 646251730Sadrian pdiv_ant_conf->main_gaintb = 0; 647251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 648251730Sadrian break; 649251730Sadrian case (0x32): //A+B LNA1 650251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 651251730Sadrian pdiv_ant_conf->main_gaintb = 0; 652251730Sadrian pdiv_ant_conf->alt_gaintb = 0; 653251730Sadrian break; 654251730Sadrian default: 655251730Sadrian break; 656251730Sadrian } 657251730Sadrian } else { /* DEFAULT_ANTDIV_CONFIG_GROUP */ 658251730Sadrian switch ((pdiv_ant_conf->main_lna_conf << 4) | pdiv_ant_conf->alt_lna_conf) { 659251730Sadrian case (0x01): //A-B LNA2 660251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3b; 661251730Sadrian break; 662251730Sadrian case (0x02): //A-B LNA1 663251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3d; 664251730Sadrian break; 665251730Sadrian case (0x03): //A-B A+B 666251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 667251730Sadrian break; 668251730Sadrian case (0x10): //LNA2 A-B 669251730Sadrian pdiv_ant_conf->fast_div_bias = 0x7; 670251730Sadrian break; 671251730Sadrian case (0x12): //LNA2 LNA1 672251730Sadrian pdiv_ant_conf->fast_div_bias = 0x2; 673251730Sadrian break; 674251730Sadrian case (0x13): //LNA2 A+B 675251730Sadrian pdiv_ant_conf->fast_div_bias = 0x7; 676251730Sadrian break; 677251730Sadrian case (0x20): //LNA1 A-B 678251730Sadrian pdiv_ant_conf->fast_div_bias = 0x6; 679251730Sadrian break; 680251730Sadrian case (0x21): //LNA1 LNA2 681251730Sadrian pdiv_ant_conf->fast_div_bias = 0x0; 682251730Sadrian break; 683251730Sadrian case (0x23): //LNA1 A+B 684251730Sadrian pdiv_ant_conf->fast_div_bias = 0x6; 685251730Sadrian break; 686251730Sadrian case (0x30): //A+B A-B 687251730Sadrian pdiv_ant_conf->fast_div_bias = 0x1; 688251730Sadrian break; 689251730Sadrian case (0x31): //A+B LNA2 690251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3b; 691251730Sadrian break; 692251730Sadrian case (0x32): //A+B LNA1 693251730Sadrian pdiv_ant_conf->fast_div_bias = 0x3d; 694251730Sadrian break; 695251730Sadrian default: 696251730Sadrian break; 697251730Sadrian } 698251655Sadrian } 699251655Sadrian} 700251655Sadrian 701251730Sadrian/* 702251730Sadrian * AR9485/AR933x TODO: 703251730Sadrian * + Select a ratio based on whether RSSI is low or not; but I need 704251730Sadrian * to figure out what "low_rssi_th" is sourced from. 705251730Sadrian * + What's ath_ant_div_comb_alt_check() in the reference driver do? 706251730Sadrian * + .. and there's likely a bunch of other things to include in this. 707251730Sadrian */ 708251730Sadrian 709251655Sadrian/* Antenna diversity and combining */ 710251655Sadrianvoid 711251655Sadrianath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs, 712251655Sadrian unsigned long ticks, int hz) 713251655Sadrian{ 714251655Sadrian HAL_ANT_COMB_CONFIG div_ant_conf; 715251655Sadrian struct if_ath_ant_comb_state *antcomb = sc->sc_lna_div; 716251655Sadrian int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; 717251655Sadrian int curr_main_set, curr_bias; 718251655Sadrian int main_rssi = rs->rs_rssi_ctl[0]; 719251655Sadrian int alt_rssi = rs->rs_rssi_ctl[1]; 720251655Sadrian int rx_ant_conf, main_ant_conf, alt_ant_conf; 721251655Sadrian HAL_BOOL short_scan = AH_FALSE; 722251655Sadrian 723251655Sadrian rx_ant_conf = (rs->rs_rssi_ctl[2] >> 4) & ATH_ANT_RX_MASK; 724251655Sadrian main_ant_conf = (rs->rs_rssi_ctl[2] >> 2) & ATH_ANT_RX_MASK; 725251655Sadrian alt_ant_conf = (rs->rs_rssi_ctl[2] >> 0) & ATH_ANT_RX_MASK; 726251655Sadrian 727251655Sadrian#if 0 728251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, 729251655Sadrian "%s: RSSI %d/%d, conf %x/%x, rxconf %x, LNA: %d; ANT: %d; " 730251655Sadrian "FastDiv: %d\n", 731251655Sadrian __func__, 732251655Sadrian main_rssi, 733251655Sadrian alt_rssi, 734251655Sadrian main_ant_conf, 735251655Sadrian alt_ant_conf, 736251655Sadrian rx_ant_conf, 737251655Sadrian !!(rs->rs_rssi_ctl[2] & 0x80), 738251655Sadrian !!(rs->rs_rssi_ctl[2] & 0x40), 739251655Sadrian !!(rs->rs_rssi_ext[2] & 0x40)); 740251655Sadrian#endif 741251655Sadrian 742251655Sadrian /* 743251655Sadrian * If LNA diversity combining isn't enabled, don't run this. 744251655Sadrian */ 745251655Sadrian if (! sc->sc_dolnadiv) 746251655Sadrian return; 747251655Sadrian 748251655Sadrian /* 749251655Sadrian * XXX this is ugly, but the HAL code attaches the 750251655Sadrian * LNA diversity to the TX antenna settings. 751251655Sadrian * I don't know why. 752251655Sadrian */ 753251655Sadrian if (sc->sc_txantenna != HAL_ANT_VARIABLE) 754251655Sadrian return; 755251655Sadrian 756251655Sadrian /* Record packet only when alt_rssi is positive */ 757251655Sadrian if (main_rssi > 0 && alt_rssi > 0) { 758251655Sadrian antcomb->total_pkt_count++; 759251655Sadrian antcomb->main_total_rssi += main_rssi; 760251655Sadrian antcomb->alt_total_rssi += alt_rssi; 761251655Sadrian if (main_ant_conf == rx_ant_conf) 762251655Sadrian antcomb->main_recv_cnt++; 763251655Sadrian else 764251655Sadrian antcomb->alt_recv_cnt++; 765251655Sadrian } 766251655Sadrian 767251655Sadrian /* Short scan check */ 768251655Sadrian if (antcomb->scan && antcomb->alt_good) { 769297405Sadrian if (ieee80211_time_after(ticks, antcomb->scan_start_time + 770251655Sadrian msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) 771251655Sadrian short_scan = AH_TRUE; 772251655Sadrian else 773251655Sadrian if (antcomb->total_pkt_count == 774251655Sadrian ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { 775251655Sadrian alt_ratio = ((antcomb->alt_recv_cnt * 100) / 776251655Sadrian antcomb->total_pkt_count); 777251655Sadrian if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) 778251655Sadrian short_scan = AH_TRUE; 779251655Sadrian } 780251655Sadrian } 781251655Sadrian 782251730Sadrian#if 0 783251730Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, 784251730Sadrian "%s: total pkt=%d, aggr=%d, short_scan=%d\n", 785251730Sadrian __func__, 786251730Sadrian antcomb->total_pkt_count, 787251730Sadrian !! (rs->rs_moreaggr), 788251730Sadrian !! (short_scan)); 789251730Sadrian#endif 790251730Sadrian 791251655Sadrian if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || 792251655Sadrian rs->rs_moreaggr) && !short_scan) 793251655Sadrian return; 794251655Sadrian 795251655Sadrian if (antcomb->total_pkt_count) { 796251655Sadrian alt_ratio = ((antcomb->alt_recv_cnt * 100) / 797251655Sadrian antcomb->total_pkt_count); 798251655Sadrian main_rssi_avg = (antcomb->main_total_rssi / 799251655Sadrian antcomb->total_pkt_count); 800251655Sadrian alt_rssi_avg = (antcomb->alt_total_rssi / 801251655Sadrian antcomb->total_pkt_count); 802251655Sadrian } 803251655Sadrian 804251655Sadrian OS_MEMZERO(&div_ant_conf, sizeof(div_ant_conf)); 805251655Sadrian 806251655Sadrian ath_hal_div_comb_conf_get(sc->sc_ah, &div_ant_conf); 807251655Sadrian curr_alt_set = div_ant_conf.alt_lna_conf; 808251655Sadrian curr_main_set = div_ant_conf.main_lna_conf; 809251655Sadrian curr_bias = div_ant_conf.fast_div_bias; 810251655Sadrian 811251655Sadrian antcomb->count++; 812251655Sadrian 813251655Sadrian if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { 814251655Sadrian if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 815251655Sadrian ath_lnaconf_alt_good_scan(antcomb, &div_ant_conf, 816251655Sadrian main_rssi_avg); 817251655Sadrian antcomb->alt_good = AH_TRUE; 818251655Sadrian } else { 819251655Sadrian antcomb->alt_good = AH_FALSE; 820251655Sadrian } 821251655Sadrian 822251655Sadrian antcomb->count = 0; 823251655Sadrian antcomb->scan = AH_TRUE; 824251655Sadrian antcomb->scan_not_start = AH_TRUE; 825251655Sadrian } 826251655Sadrian 827251655Sadrian if (!antcomb->scan) { 828251655Sadrian if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { 829251655Sadrian if (curr_alt_set == HAL_ANT_DIV_COMB_LNA2) { 830251655Sadrian /* Switch main and alt LNA */ 831251655Sadrian div_ant_conf.main_lna_conf = 832251655Sadrian HAL_ANT_DIV_COMB_LNA2; 833251655Sadrian div_ant_conf.alt_lna_conf = 834251655Sadrian HAL_ANT_DIV_COMB_LNA1; 835251655Sadrian } else if (curr_alt_set == HAL_ANT_DIV_COMB_LNA1) { 836251655Sadrian div_ant_conf.main_lna_conf = 837251655Sadrian HAL_ANT_DIV_COMB_LNA1; 838251655Sadrian div_ant_conf.alt_lna_conf = 839251655Sadrian HAL_ANT_DIV_COMB_LNA2; 840251655Sadrian } 841251655Sadrian 842251655Sadrian goto div_comb_done; 843251655Sadrian } else if ((curr_alt_set != HAL_ANT_DIV_COMB_LNA1) && 844251655Sadrian (curr_alt_set != HAL_ANT_DIV_COMB_LNA2)) { 845251655Sadrian /* Set alt to another LNA */ 846251655Sadrian if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) 847251655Sadrian div_ant_conf.alt_lna_conf = 848251655Sadrian HAL_ANT_DIV_COMB_LNA1; 849251655Sadrian else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) 850251655Sadrian div_ant_conf.alt_lna_conf = 851251655Sadrian HAL_ANT_DIV_COMB_LNA2; 852251655Sadrian 853251655Sadrian goto div_comb_done; 854251655Sadrian } 855251655Sadrian 856251655Sadrian if ((alt_rssi_avg < (main_rssi_avg + 857251730Sadrian antcomb->lna1_lna2_delta))) 858251655Sadrian goto div_comb_done; 859251655Sadrian } 860251655Sadrian 861251655Sadrian if (!antcomb->scan_not_start) { 862251655Sadrian switch (curr_alt_set) { 863251655Sadrian case HAL_ANT_DIV_COMB_LNA2: 864251655Sadrian antcomb->rssi_lna2 = alt_rssi_avg; 865251655Sadrian antcomb->rssi_lna1 = main_rssi_avg; 866251655Sadrian antcomb->scan = AH_TRUE; 867251655Sadrian /* set to A+B */ 868251655Sadrian div_ant_conf.main_lna_conf = 869251655Sadrian HAL_ANT_DIV_COMB_LNA1; 870251655Sadrian div_ant_conf.alt_lna_conf = 871251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 872251655Sadrian break; 873251655Sadrian case HAL_ANT_DIV_COMB_LNA1: 874251655Sadrian antcomb->rssi_lna1 = alt_rssi_avg; 875251655Sadrian antcomb->rssi_lna2 = main_rssi_avg; 876251655Sadrian antcomb->scan = AH_TRUE; 877251655Sadrian /* set to A+B */ 878251655Sadrian div_ant_conf.main_lna_conf = HAL_ANT_DIV_COMB_LNA2; 879251655Sadrian div_ant_conf.alt_lna_conf = 880251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 881251655Sadrian break; 882251655Sadrian case HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2: 883251655Sadrian antcomb->rssi_add = alt_rssi_avg; 884251655Sadrian antcomb->scan = AH_TRUE; 885251655Sadrian /* set to A-B */ 886251655Sadrian div_ant_conf.alt_lna_conf = 887251655Sadrian HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2; 888251655Sadrian break; 889251655Sadrian case HAL_ANT_DIV_COMB_LNA1_MINUS_LNA2: 890251655Sadrian antcomb->rssi_sub = alt_rssi_avg; 891251655Sadrian antcomb->scan = AH_FALSE; 892251655Sadrian if (antcomb->rssi_lna2 > 893251655Sadrian (antcomb->rssi_lna1 + 894251655Sadrian ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { 895251655Sadrian /* use LNA2 as main LNA */ 896251655Sadrian if ((antcomb->rssi_add > antcomb->rssi_lna1) && 897251655Sadrian (antcomb->rssi_add > antcomb->rssi_sub)) { 898251655Sadrian /* set to A+B */ 899251655Sadrian div_ant_conf.main_lna_conf = 900251655Sadrian HAL_ANT_DIV_COMB_LNA2; 901251655Sadrian div_ant_conf.alt_lna_conf = 902251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 903251655Sadrian } else if (antcomb->rssi_sub > 904251655Sadrian antcomb->rssi_lna1) { 905251655Sadrian /* set to A-B */ 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_MINUS_LNA2; 910251655Sadrian } else { 911251655Sadrian /* set to LNA1 */ 912251655Sadrian div_ant_conf.main_lna_conf = 913251655Sadrian HAL_ANT_DIV_COMB_LNA2; 914251655Sadrian div_ant_conf.alt_lna_conf = 915251655Sadrian HAL_ANT_DIV_COMB_LNA1; 916251655Sadrian } 917251655Sadrian } else { 918251655Sadrian /* use LNA1 as main LNA */ 919251655Sadrian if ((antcomb->rssi_add > antcomb->rssi_lna2) && 920251655Sadrian (antcomb->rssi_add > antcomb->rssi_sub)) { 921251655Sadrian /* set to A+B */ 922251655Sadrian div_ant_conf.main_lna_conf = 923251655Sadrian HAL_ANT_DIV_COMB_LNA1; 924251655Sadrian div_ant_conf.alt_lna_conf = 925251655Sadrian HAL_ANT_DIV_COMB_LNA1_PLUS_LNA2; 926251655Sadrian } else if (antcomb->rssi_sub > 927251655Sadrian antcomb->rssi_lna1) { 928251655Sadrian /* set to A-B */ 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_LNA1_MINUS_LNA2; 933251655Sadrian } else { 934251655Sadrian /* set to LNA2 */ 935251655Sadrian div_ant_conf.main_lna_conf = 936251655Sadrian HAL_ANT_DIV_COMB_LNA1; 937251655Sadrian div_ant_conf.alt_lna_conf = 938251655Sadrian HAL_ANT_DIV_COMB_LNA2; 939251655Sadrian } 940251655Sadrian } 941251655Sadrian break; 942251655Sadrian default: 943251655Sadrian break; 944251655Sadrian } 945251655Sadrian } else { 946251655Sadrian if (!antcomb->alt_good) { 947251655Sadrian antcomb->scan_not_start = AH_FALSE; 948251655Sadrian /* Set alt to another LNA */ 949251655Sadrian if (curr_main_set == HAL_ANT_DIV_COMB_LNA2) { 950251655Sadrian div_ant_conf.main_lna_conf = 951251655Sadrian HAL_ANT_DIV_COMB_LNA2; 952251655Sadrian div_ant_conf.alt_lna_conf = 953251655Sadrian HAL_ANT_DIV_COMB_LNA1; 954251655Sadrian } else if (curr_main_set == HAL_ANT_DIV_COMB_LNA1) { 955251655Sadrian div_ant_conf.main_lna_conf = 956251655Sadrian HAL_ANT_DIV_COMB_LNA1; 957251655Sadrian div_ant_conf.alt_lna_conf = 958251655Sadrian HAL_ANT_DIV_COMB_LNA2; 959251655Sadrian } 960251655Sadrian goto div_comb_done; 961251655Sadrian } 962251655Sadrian } 963251655Sadrian 964251655Sadrian ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, 965251655Sadrian main_rssi_avg, alt_rssi_avg, 966251655Sadrian alt_ratio); 967251655Sadrian 968251655Sadrian antcomb->quick_scan_cnt++; 969251655Sadrian 970251655Sadriandiv_comb_done: 971251730Sadrian#if 0 972251655Sadrian ath_ant_div_conf_fast_divbias(&div_ant_conf); 973251730Sadrian#endif 974251655Sadrian 975251730Sadrian ath_ant_adjust_fast_divbias(antcomb, 976251730Sadrian alt_ratio, 977251730Sadrian ATH_ANT_DIV_COMB_ALT_ANT_RATIO, 978251730Sadrian div_ant_conf.antdiv_configgroup, 979251730Sadrian &div_ant_conf); 980251730Sadrian 981251655Sadrian ath_hal_div_comb_conf_set(sc->sc_ah, &div_ant_conf); 982251655Sadrian 983251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n", 984251655Sadrian __func__, antcomb->total_pkt_count); 985251655Sadrian 986251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n", 987251655Sadrian __func__, antcomb->main_total_rssi); 988251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n", 989251655Sadrian __func__, antcomb->alt_total_rssi); 990251655Sadrian 991251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n", 992251655Sadrian __func__, main_rssi_avg); 993251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n", 994251655Sadrian __func__, alt_rssi_avg); 995251655Sadrian 996251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n", 997251655Sadrian __func__, antcomb->main_recv_cnt); 998251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n", 999251655Sadrian __func__, antcomb->alt_recv_cnt); 1000251655Sadrian 1001251655Sadrian// if (curr_alt_set != div_ant_conf.alt_lna_conf) 1002251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n", 1003251655Sadrian __func__, curr_alt_set, div_ant_conf.alt_lna_conf); 1004251655Sadrian// if (curr_main_set != div_ant_conf.main_lna_conf) 1005251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: main_lna_conf: %x -> %x\n", 1006251655Sadrian __func__, curr_main_set, div_ant_conf.main_lna_conf); 1007251655Sadrian// if (curr_bias != div_ant_conf.fast_div_bias) 1008251655Sadrian DPRINTF(sc, ATH_DEBUG_DIVERSITY, "%s: fast_div_bias: %x -> %x\n", 1009251655Sadrian __func__, curr_bias, div_ant_conf.fast_div_bias); 1010251655Sadrian 1011251655Sadrian antcomb->scan_start_time = ticks; 1012251655Sadrian antcomb->total_pkt_count = 0; 1013251655Sadrian antcomb->main_total_rssi = 0; 1014251655Sadrian antcomb->alt_total_rssi = 0; 1015251655Sadrian antcomb->main_recv_cnt = 0; 1016251655Sadrian antcomb->alt_recv_cnt = 0; 1017251655Sadrian} 1018251655Sadrian 1019