예제 #1
0
/*
 * Centralized txant update function. call it whenever wlc->stf->txant and/or
 * wlc->stf->txchain change.
 *
 * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
 * achieve various tx/rx antenna selection schemes
 *
 * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
 * means auto(last rx).
 * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
 * means last rx and do tx-antenna selection for SISO transmissions
 * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7
 * means last rx and do tx-antenna selection for SISO transmissions
 * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7
 * means both cores active
*/
static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
	s8 txant;

	txant = (s8) wlc->stf->txant;
	if (BRCMS_PHY_11N_CAP(wlc->band)) {
		if (txant == ANT_TX_FORCE_0) {
			wlc->stf->phytxant = PHY_TXC_ANT_0;
		} else if (txant == ANT_TX_FORCE_1) {
			wlc->stf->phytxant = PHY_TXC_ANT_1;

			if (BRCMS_ISNPHY(wlc->band) &&
			    NREV_GE(wlc->band->phyrev, 3)
			    && NREV_LT(wlc->band->phyrev, 7))
				wlc->stf->phytxant = PHY_TXC_ANT_2;
		} else {
			if (BRCMS_ISLCNPHY(wlc->band) ||
			    BRCMS_ISSSLPNPHY(wlc->band))
				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
			else {
				/* catch out of sync wlc->stf->txcore */
				WARN_ON(wlc->stf->txchain <= 0);
				wlc->stf->phytxant =
				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
			}
		}
	} else {
		if (txant == ANT_TX_FORCE_0)
			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
		else if (txant == ANT_TX_FORCE_1)
			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
		else
			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
	}

	brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
}
예제 #2
0
/*
 * Validate the chanspec for this locale, for 40MHZ we need to also
 * check that the sidebands are valid 20MZH channels in this locale
 * and they are also a legal HT combination
 */
static bool
brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
			   bool dualband)
{
	struct brcms_c_info *wlc = wlc_cm->wlc;
	u8 channel = CHSPEC_CHANNEL(chspec);

	/* check the chanspec */
	if (brcms_c_chspec_malformed(chspec)) {
		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
			wlc->pub->unit, chspec);
		return false;
	}

	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
	    chspec_bandunit(chspec))
		return false;

	/* Check a 20Mhz channel */
	if (CHSPEC_IS20(chspec)) {
		if (dualband)
			return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
							  channel);
		else
			return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
						       channel);
	}
#ifdef SUPPORT_40MHZ
	/*
	 * We know we are now checking a 40MHZ channel, so we should
	 * only be here for NPHYS
	 */
	if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
		u8 upper_sideband = 0, idx;
		u8 num_ch20_entries =
		    sizeof(chan20_info) / sizeof(struct chan20_info);

		if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
			return false;

		if (dualband) {
			if (!brcms_c_valid_channel20_db(wlc->cmi,
							lower_20_sb(channel)) ||
			    !brcms_c_valid_channel20_db(wlc->cmi,
							upper_20_sb(channel)))
				return false;
		} else {
			if (!brcms_c_valid_channel20(wlc->cmi,
						     lower_20_sb(channel)) ||
			    !brcms_c_valid_channel20(wlc->cmi,
						     upper_20_sb(channel)))
				return false;
		}

		/* find the lower sideband info in the sideband array */
		for (idx = 0; idx < num_ch20_entries; idx++) {
			if (chan20_info[idx].sb == lower_20_sb(channel))
				upper_sideband = chan20_info[idx].adj_sbs;
		}
		/* check that the lower sideband allows an upper sideband */
		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
		    (CH_UPPER_SB | CH_EWA_VALID))
			return true;
		return false;
	}
#endif				/* 40 MHZ */

	return false;
}