brintos

brintos / linux-shallow public Read only

0
0
Text · 10.2 KiB · 427d187 Raw
360 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2012  Realtek Corporation.*/3 4#include "../wifi.h"5#include "def.h"6#include "reg.h"7#include "phy_common.h"8#include "rf_common.h"9 10void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)11{12	struct rtl_priv *rtlpriv = rtl_priv(hw);13	struct rtl_phy *rtlphy = &rtlpriv->phy;14	u8 rfpath;15 16	switch (bandwidth) {17	case HT_CHANNEL_WIDTH_20:18		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {19			rtlphy->rfreg_chnlval[rfpath] &= 0xfffff3ff;20			rtlphy->rfreg_chnlval[rfpath] |= 0x0400;21 22			rtl_set_rfreg(hw, rfpath, RF_CHNLBW,23				      BIT(10) | BIT(11), 0x01);24 25			rtl_dbg(rtlpriv, COMP_RF, DBG_LOUD,26				"20M RF 0x18 = 0x%x\n",27				rtlphy->rfreg_chnlval[rfpath]);28		}29 30		break;31	case HT_CHANNEL_WIDTH_20_40:32		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {33			rtlphy->rfreg_chnlval[rfpath] &= 0xfffff3ff;34 35			rtl_set_rfreg(hw, rfpath, RF_CHNLBW,36				      BIT(10) | BIT(11), 0x00);37 38			rtl_dbg(rtlpriv, COMP_RF, DBG_LOUD,39				"40M RF 0x18 = 0x%x\n",40				rtlphy->rfreg_chnlval[rfpath]);41		}42		break;43	default:44		pr_err("unknown bandwidth: %#X\n", bandwidth);45		break;46	}47}48EXPORT_SYMBOL_GPL(rtl92d_phy_rf6052_set_bandwidth);49 50void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,51				       u8 *ppowerlevel)52{53	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));54	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));55	struct rtl_priv *rtlpriv = rtl_priv(hw);56	struct rtl_phy *rtlphy = &rtlpriv->phy;57	u32 tx_agc[2] = {0, 0}, tmpval;58	bool turbo_scanoff = false;59	u8 idx1, idx2;60	u8 *ptr;61 62	if (rtlefuse->eeprom_regulatory != 0)63		turbo_scanoff = true;64	if (mac->act_scanning) {65		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;66		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;67		if (turbo_scanoff) {68			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {69				tx_agc[idx1] = ppowerlevel[idx1] |70				    (ppowerlevel[idx1] << 8) |71				    (ppowerlevel[idx1] << 16) |72				    (ppowerlevel[idx1] << 24);73			}74		}75	} else {76		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {77			tx_agc[idx1] = ppowerlevel[idx1] |78			    (ppowerlevel[idx1] << 8) |79			    (ppowerlevel[idx1] << 16) |80			    (ppowerlevel[idx1] << 24);81		}82		if (rtlefuse->eeprom_regulatory == 0) {83			tmpval = (rtlphy->mcs_offset[0][6]) +84			    (rtlphy->mcs_offset[0][7] << 8);85			tx_agc[RF90_PATH_A] += tmpval;86			tmpval = (rtlphy->mcs_offset[0][14]) +87			    (rtlphy->mcs_offset[0][15] << 24);88			tx_agc[RF90_PATH_B] += tmpval;89		}90	}91 92	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {93		ptr = (u8 *)(&tx_agc[idx1]);94		for (idx2 = 0; idx2 < 4; idx2++) {95			if (*ptr > RF6052_MAX_TX_PWR)96				*ptr = RF6052_MAX_TX_PWR;97			ptr++;98		}99	}100 101	tmpval = tx_agc[RF90_PATH_A] & 0xff;102	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);103	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,104		"CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n",105		tmpval, RTXAGC_A_CCK1_MCS32);106	tmpval = tx_agc[RF90_PATH_A] >> 8;107	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);108	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,109		"CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n",110		tmpval, RTXAGC_B_CCK11_A_CCK2_11);111	tmpval = tx_agc[RF90_PATH_B] >> 24;112	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);113	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,114		"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n",115		tmpval, RTXAGC_B_CCK11_A_CCK2_11);116	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;117	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);118	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,119		"CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n",120		tmpval, RTXAGC_B_CCK1_55_MCS32);121}122EXPORT_SYMBOL_GPL(rtl92d_phy_rf6052_set_cck_txpower);123 124static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw,125				       u8 *ppowerlevel, u8 channel,126				       u32 *ofdmbase, u32 *mcsbase)127{128	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));129	struct rtl_priv *rtlpriv = rtl_priv(hw);130	struct rtl_phy *rtlphy = &rtlpriv->phy;131	u32 powerbase0, powerbase1;132	u8 legacy_pwrdiff, ht20_pwrdiff;133	u8 i, powerlevel[2];134 135	for (i = 0; i < 2; i++) {136		powerlevel[i] = ppowerlevel[i];137		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];138		powerbase0 = powerlevel[i] + legacy_pwrdiff;139		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |140			     (powerbase0 << 8) | powerbase0;141		*(ofdmbase + i) = powerbase0;142		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,143			" [OFDM power base index rf(%c) = 0x%x]\n",144			i == 0 ? 'A' : 'B', *(ofdmbase + i));145	}146 147	for (i = 0; i < 2; i++) {148		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {149			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];150			powerlevel[i] += ht20_pwrdiff;151		}152		powerbase1 = powerlevel[i];153		powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |154			     (powerbase1 << 8) | powerbase1;155		*(mcsbase + i) = powerbase1;156		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,157			" [MCS power base index rf(%c) = 0x%x]\n",158			i == 0 ? 'A' : 'B', *(mcsbase + i));159	}160}161 162static void _rtl92d_get_pwr_diff_limit(struct ieee80211_hw *hw, u8 channel,163				       u8 index, u8 rf, u8 pwr_diff_limit[4])164{165	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));166	struct rtl_priv *rtlpriv = rtl_priv(hw);167	struct rtl_phy *rtlphy = &rtlpriv->phy;168	u32 mcs_offset;169	u8 limit;170	int i;171 172	mcs_offset = rtlphy->mcs_offset[0][index + (rf ? 8 : 0)];173 174	for (i = 0; i < 4; i++) {175		pwr_diff_limit[i] = (mcs_offset >> (i * 8)) & 0x7f;176 177		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)178			limit = rtlefuse->pwrgroup_ht40[rf][channel - 1];179		else180			limit = rtlefuse->pwrgroup_ht20[rf][channel - 1];181 182		if (pwr_diff_limit[i] > limit)183			pwr_diff_limit[i] = limit;184	}185}186 187static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,188						       u8 channel, u8 index,189						       u32 *powerbase0,190						       u32 *powerbase1,191						       u32 *p_outwriteval)192{193	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));194	struct rtl_priv *rtlpriv = rtl_priv(hw);195	struct rtl_phy *rtlphy = &rtlpriv->phy;196	u32 writeval = 0, customer_limit, rf;197	u8 chnlgroup = 0, pwr_diff_limit[4];198 199	for (rf = 0; rf < 2; rf++) {200		switch (rtlefuse->eeprom_regulatory) {201		case 0:202			writeval = rtlphy->mcs_offset[0][index + (rf ? 8 : 0)];203 204			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,205				"RTK better performance\n");206			break;207		case 1:208			if (rtlphy->pwrgroup_cnt == 1)209				chnlgroup = 0;210 211			if (rtlphy->pwrgroup_cnt < MAX_PG_GROUP)212				break;213 214			chnlgroup = rtl92d_phy_get_chnlgroup_bypg(channel - 1);215			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)216				chnlgroup++;217			else218				chnlgroup += 4;219 220			writeval = rtlphy->mcs_offset221					[chnlgroup][index + (rf ? 8 : 0)];222 223			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,224				"Realtek regulatory, 20MHz\n");225			break;226		case 2:227			writeval = 0;228 229			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, "Better regulatory\n");230			break;231		case 3:232			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {233				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,234					"customer's limit, 40MHz rf(%c) = 0x%x\n",235					rf == 0 ? 'A' : 'B',236					rtlefuse->pwrgroup_ht40[rf][channel - 1]);237			} else {238				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,239					"customer's limit, 20MHz rf(%c) = 0x%x\n",240					rf == 0 ? 'A' : 'B',241					rtlefuse->pwrgroup_ht20[rf][channel - 1]);242			}243 244			_rtl92d_get_pwr_diff_limit(hw, channel, index, rf,245						   pwr_diff_limit);246 247			customer_limit = (pwr_diff_limit[3] << 24) |248					 (pwr_diff_limit[2] << 16) |249					 (pwr_diff_limit[1] << 8) |250					 (pwr_diff_limit[0]);251 252			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,253				"Customer's limit rf(%c) = 0x%x\n",254				rf == 0 ? 'A' : 'B', customer_limit);255 256			writeval = customer_limit;257 258			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, "Customer\n");259			break;260		default:261			writeval = rtlphy->mcs_offset[0][index + (rf ? 8 : 0)];262 263			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,264				"RTK better performance\n");265			break;266		}267 268		if (index < 2)269			writeval += powerbase0[rf];270		else271			writeval += powerbase1[rf];272 273		RTPRINT(rtlpriv, FPHY, PHY_TXPWR, "writeval rf(%c)= 0x%x\n",274			rf == 0 ? 'A' : 'B', writeval);275 276		*(p_outwriteval + rf) = writeval;277	}278}279 280static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw,281					 u8 index, u32 *pvalue)282{283	struct rtl_priv *rtlpriv = rtl_priv(hw);284	struct rtl_phy *rtlphy = &rtlpriv->phy;285	static const u16 regoffset_a[6] = {286		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,287		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,288		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12289	};290	static const u16 regoffset_b[6] = {291		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,292		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,293		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12294	};295	u8 i, rf, pwr_val[4];296	u32 writeval;297	u16 regoffset;298 299	for (rf = 0; rf < 2; rf++) {300		writeval = pvalue[rf];301		for (i = 0; i < 4; i++) {302			pwr_val[i] = (u8)((writeval & (0x7f <<303				     (i * 8))) >> (i * 8));304			if (pwr_val[i] > RF6052_MAX_TX_PWR)305				pwr_val[i] = RF6052_MAX_TX_PWR;306		}307		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |308			   (pwr_val[1] << 8) | pwr_val[0];309		if (rf == 0)310			regoffset = regoffset_a[index];311		else312			regoffset = regoffset_b[index];313		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);314		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,315			"Set 0x%x = %08x\n", regoffset, writeval);316		if (((get_rf_type(rtlphy) == RF_2T2R) &&317		     (regoffset == RTXAGC_A_MCS15_MCS12 ||318		      regoffset == RTXAGC_B_MCS15_MCS12)) ||319		    ((get_rf_type(rtlphy) != RF_2T2R) &&320		     (regoffset == RTXAGC_A_MCS07_MCS04 ||321		      regoffset == RTXAGC_B_MCS07_MCS04))) {322			writeval = pwr_val[3];323			if (regoffset == RTXAGC_A_MCS15_MCS12 ||324			    regoffset == RTXAGC_A_MCS07_MCS04)325				regoffset = 0xc90;326			if (regoffset == RTXAGC_B_MCS15_MCS12 ||327			    regoffset == RTXAGC_B_MCS07_MCS04)328				regoffset = 0xc98;329			for (i = 0; i < 3; i++) {330				if (i != 2)331					writeval = (writeval > 8) ?332						   (writeval - 8) : 0;333				else334					writeval = (writeval > 6) ?335						   (writeval - 6) : 0;336				rtl_write_byte(rtlpriv, (u32)(regoffset + i),337					       (u8)writeval);338			}339		}340	}341}342 343void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,344					u8 *ppowerlevel, u8 channel)345{346	u32 writeval[2], powerbase0[2], powerbase1[2];347	u8 index;348 349	_rtl92d_phy_get_power_base(hw, ppowerlevel, channel,350				   &powerbase0[0], &powerbase1[0]);351	for (index = 0; index < 6; index++) {352		_rtl92d_get_txpower_writeval_by_regulatory(hw, channel, index,353							   &powerbase0[0],354							   &powerbase1[0],355							   &writeval[0]);356		_rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]);357	}358}359EXPORT_SYMBOL_GPL(rtl92d_phy_rf6052_set_ofdm_txpower);360