brintos

brintos / linux-shallow public Read only

0
0
Text · 11.6 KiB · e339f23 Raw
441 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2010  Realtek Corporation.*/3 4#include "../wifi.h"5#include "reg.h"6#include "def.h"7#include "phy.h"8#include "rf.h"9#include "dm.h"10 11static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw);12 13void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)14{15	switch (bandwidth) {16	case HT_CHANNEL_WIDTH_20:17		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3);18		rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3);19		break;20	case HT_CHANNEL_WIDTH_20_40:21		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1);22		rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1);23		break;24	case HT_CHANNEL_WIDTH_80:25		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0);26		rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0);27		break;28	default:29		pr_err("unknown bandwidth: %#X\n", bandwidth);30		break;31	}32}33 34void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,35					  u8 *ppowerlevel)36{37	struct rtl_priv *rtlpriv = rtl_priv(hw);38	struct rtl_phy *rtlphy = &rtlpriv->phy;39	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));40	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));41	u32 tx_agc[2] = {0, 0}, tmpval;42	bool turbo_scanoff = false;43	u8 idx1, idx2;44	u8 *ptr;45	u8 direction;46	u32 pwrtrac_value;47 48	if (rtlefuse->eeprom_regulatory != 0)49		turbo_scanoff = true;50 51	if (mac->act_scanning) {52		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;53		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;54 55		if (turbo_scanoff) {56			for (idx1 = RF90_PATH_A;57				idx1 <= RF90_PATH_B;58				idx1++) {59				tx_agc[idx1] = ppowerlevel[idx1] |60				    (ppowerlevel[idx1] << 8) |61				    (ppowerlevel[idx1] << 16) |62				    (ppowerlevel[idx1] << 24);63			}64		}65	} else {66		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {67			tx_agc[idx1] = ppowerlevel[idx1] |68			    (ppowerlevel[idx1] << 8) |69			    (ppowerlevel[idx1] << 16) |70			    (ppowerlevel[idx1] << 24);71		}72 73		if (rtlefuse->eeprom_regulatory == 0) {74			tmpval =75			    (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +76			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<77			     8);78			tx_agc[RF90_PATH_A] += tmpval;79 80			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +81			    (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<82			     24);83			tx_agc[RF90_PATH_B] += tmpval;84		}85	}86 87	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {88		ptr = (u8 *)(&tx_agc[idx1]);89		for (idx2 = 0; idx2 < 4; idx2++) {90			if (*ptr > RF6052_MAX_TX_PWR)91				*ptr = RF6052_MAX_TX_PWR;92			ptr++;93		}94	}95	rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);96	if (direction == 1) {97		tx_agc[0] += pwrtrac_value;98		tx_agc[1] += pwrtrac_value;99	} else if (direction == 2) {100		tx_agc[0] -= pwrtrac_value;101		tx_agc[1] -= pwrtrac_value;102	}103	tmpval = tx_agc[RF90_PATH_A];104	rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval);105 106	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,107		"CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,108		 RTXAGC_A_CCK11_CCK1);109 110	tmpval = tx_agc[RF90_PATH_B];111	rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval);112 113	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,114		"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,115		 RTXAGC_B_CCK11_CCK1);116}117 118static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw,119					 u8 *ppowerlevel_ofdm,120					 u8 *ppowerlevel_bw20,121					 u8 *ppowerlevel_bw40, u8 channel,122					 u32 *ofdmbase, u32 *mcsbase)123{124	struct rtl_priv *rtlpriv = rtl_priv(hw);125	struct rtl_phy *rtlphy = &rtlpriv->phy;126	u32 powerbase0, powerbase1;127	u8 i, powerlevel[2];128 129	for (i = 0; i < 2; i++) {130		powerbase0 = ppowerlevel_ofdm[i];131 132		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |133		    (powerbase0 << 8) | powerbase0;134		*(ofdmbase + i) = powerbase0;135		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,136			" [OFDM power base index rf(%c) = 0x%x]\n",137			 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));138	}139 140	for (i = 0; i < 2; i++) {141		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)142			powerlevel[i] = ppowerlevel_bw20[i];143		else144			powerlevel[i] = ppowerlevel_bw40[i];145 146		powerbase1 = powerlevel[i];147		powerbase1 = (powerbase1 << 24) |148		    (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;149 150		*(mcsbase + i) = powerbase1;151 152		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,153			" [MCS power base index rf(%c) = 0x%x]\n",154			 ((i == 0) ? 'A' : 'B'), *(mcsbase + i));155	}156}157 158static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,159					       u8 channel, u8 index,160					       u32 *powerbase0,161					       u32 *powerbase1,162					       u32 *p_outwriteval)163{164	struct rtl_priv *rtlpriv = rtl_priv(hw);165	struct rtl_phy *rtlphy = &rtlpriv->phy;166	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));167	u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff;168	u32 writeval, customer_limit, rf;169 170	for (rf = 0; rf < 2; rf++) {171		switch (rtlefuse->eeprom_regulatory) {172		case 0:173			chnlgroup = 0;174 175			writeval =176			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +177							(rf ? 8 : 0)]178			    + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);179 180			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,181				"RTK better performance, writeval(%c) = 0x%x\n",182				 ((rf == 0) ? 'A' : 'B'), writeval);183			break;184		case 1:185			if (rtlphy->pwrgroup_cnt == 1) {186				chnlgroup = 0;187			} else {188				if (channel < 3)189					chnlgroup = 0;190				else if (channel < 6)191					chnlgroup = 1;192				else if (channel < 9)193					chnlgroup = 2;194				else if (channel < 12)195					chnlgroup = 3;196				else if (channel < 14)197					chnlgroup = 4;198				else if (channel == 14)199					chnlgroup = 5;200			}201 202			writeval =203			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]204			    [index + (rf ? 8 : 0)] + ((index < 2) ?205						      powerbase0[rf] :206						      powerbase1[rf]);207 208			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,209				"Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",210				 ((rf == 0) ? 'A' : 'B'), writeval);211 212			break;213		case 2:214			writeval =215			    ((index < 2) ? powerbase0[rf] : powerbase1[rf]);216 217			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,218				"Better regulatory, writeval(%c) = 0x%x\n",219				 ((rf == 0) ? 'A' : 'B'), writeval);220			break;221		case 3:222			chnlgroup = 0;223 224			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {225				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,226					"customer's limit, 40MHz rf(%c) = 0x%x\n",227					 ((rf == 0) ? 'A' : 'B'),228					 rtlefuse->pwrgroup_ht40[rf][channel -229								     1]);230			} else {231				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,232					"customer's limit, 20MHz rf(%c) = 0x%x\n",233					 ((rf == 0) ? 'A' : 'B'),234					 rtlefuse->pwrgroup_ht20[rf][channel -235								     1]);236			}237 238			if (index < 2)239				pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1];240			else if (rtlphy->current_chan_bw ==  HT_CHANNEL_WIDTH_20)241				pwr_diff =242				  rtlefuse->txpwr_ht20diff[rf][channel-1];243 244			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)245				customer_pwr_diff =246				  rtlefuse->pwrgroup_ht40[rf][channel-1];247			else248				customer_pwr_diff =249				  rtlefuse->pwrgroup_ht20[rf][channel-1];250 251			if (pwr_diff > customer_pwr_diff)252				pwr_diff = 0;253			else254				pwr_diff = customer_pwr_diff - pwr_diff;255 256			for (i = 0; i < 4; i++) {257				pwr_diff_limit[i] =258				    (u8)((rtlphy->mcs_txpwrlevel_origoffset259				    [chnlgroup][index + (rf ? 8 : 0)] &260				    (0x7f << (i * 8))) >> (i * 8));261 262				if (pwr_diff_limit[i] > pwr_diff)263					pwr_diff_limit[i] = pwr_diff;264			}265 266			customer_limit = (pwr_diff_limit[3] << 24) |267			    (pwr_diff_limit[2] << 16) |268			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);269 270			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,271				"Customer's limit rf(%c) = 0x%x\n",272				 ((rf == 0) ? 'A' : 'B'), customer_limit);273 274			writeval = customer_limit +275			    ((index < 2) ? powerbase0[rf] : powerbase1[rf]);276 277			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,278				"Customer, writeval rf(%c)= 0x%x\n",279				 ((rf == 0) ? 'A' : 'B'), writeval);280			break;281		default:282			chnlgroup = 0;283			writeval =284			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]285			    [index + (rf ? 8 : 0)]286			    + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);287 288			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,289				"RTK better performance, writeval rf(%c) = 0x%x\n",290				 ((rf == 0) ? 'A' : 'B'), writeval);291			break;292		}293 294		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)295			writeval = writeval - 0x06060606;296		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==297			 TXHIGHPWRLEVEL_BT2)298			writeval = writeval - 0x0c0c0c0c;299		*(p_outwriteval + rf) = writeval;300	}301}302 303static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw,304					    u8 index, u32 *pvalue)305{306	struct rtl_priv *rtlpriv = rtl_priv(hw);307	u16 regoffset_a[6] = {308		RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24,309		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,310		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12311	};312	u16 regoffset_b[6] = {313		RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24,314		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,315		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12316	};317	u8 i, rf, pwr_val[4];318	u32 writeval;319	u16 regoffset;320 321	for (rf = 0; rf < 2; rf++) {322		writeval = pvalue[rf];323		for (i = 0; i < 4; i++) {324			pwr_val[i] = (u8)((writeval & (0x7f <<325							(i * 8))) >> (i * 8));326 327			if (pwr_val[i] > RF6052_MAX_TX_PWR)328				pwr_val[i] = RF6052_MAX_TX_PWR;329		}330		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |331		    (pwr_val[1] << 8) | pwr_val[0];332 333		if (rf == 0)334			regoffset = regoffset_a[index];335		else336			regoffset = regoffset_b[index];337		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);338 339		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,340			"Set 0x%x = %08x\n", regoffset, writeval);341	}342}343 344void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,345					   u8 *ppowerlevel_ofdm,346					   u8 *ppowerlevel_bw20,347					   u8 *ppowerlevel_bw40,348					   u8 channel)349{350	u32 writeval[2], powerbase0[2], powerbase1[2];351	u8 index;352	u8 direction;353	u32 pwrtrac_value;354 355	rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm,356				     ppowerlevel_bw20,357				     ppowerlevel_bw40,358				     channel,359				     &powerbase0[0],360				     &powerbase1[0]);361 362	rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);363 364	for (index = 0; index < 6; index++) {365		get_txpower_writeval_by_regulatory(hw, channel, index,366						   &powerbase0[0],367						   &powerbase1[0],368						   &writeval[0]);369		if (direction == 1) {370			writeval[0] += pwrtrac_value;371			writeval[1] += pwrtrac_value;372		} else if (direction == 2) {373			writeval[0] -= pwrtrac_value;374			writeval[1] -= pwrtrac_value;375		}376		_rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]);377	}378}379 380bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw)381{382	struct rtl_priv *rtlpriv = rtl_priv(hw);383	struct rtl_phy *rtlphy = &rtlpriv->phy;384 385	if (rtlphy->rf_type == RF_1T1R)386		rtlphy->num_total_rfpath = 1;387	else388		rtlphy->num_total_rfpath = 2;389 390	return _rtl8821ae_phy_rf6052_config_parafile(hw);391}392 393static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)394{395	struct rtl_priv *rtlpriv = rtl_priv(hw);396	struct rtl_phy *rtlphy = &rtlpriv->phy;397	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));398	u8 rfpath;399	bool rtstatus = true;400 401	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {402		switch (rfpath) {403		case RF90_PATH_A: {404			if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)405				rtstatus =406				  rtl8812ae_phy_config_rf_with_headerfile(hw,407							(enum radio_path)rfpath);408			else409				rtstatus =410				  rtl8821ae_phy_config_rf_with_headerfile(hw,411							(enum radio_path)rfpath);412			break;413			}414		case RF90_PATH_B:415			if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)416				rtstatus =417				  rtl8812ae_phy_config_rf_with_headerfile(hw,418							(enum radio_path)rfpath);419			else420				rtstatus =421				  rtl8821ae_phy_config_rf_with_headerfile(hw,422							(enum radio_path)rfpath);423			break;424		case RF90_PATH_C:425			break;426		case RF90_PATH_D:427			break;428		}429 430		if (!rtstatus) {431			rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,432				"Radio[%d] Fail!!\n", rfpath);433			return false;434		}435	}436 437	/*put arrays in dm.c*/438	rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "\n");439	return rtstatus;440}441