brintos

brintos / linux-shallow public Read only

0
0
Text · 12.9 KiB · 288033f Raw
443 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2012  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 _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw);12 13void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)14{15	struct rtl_priv *rtlpriv = rtl_priv(hw);16	struct rtl_phy *rtlphy = &(rtlpriv->phy);17 18	switch (bandwidth) {19	case HT_CHANNEL_WIDTH_20:20		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &21					     0xfffff3ff) | 0x0400);22		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,23			      rtlphy->rfreg_chnlval[0]);24		break;25	case HT_CHANNEL_WIDTH_20_40:26		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &27					     0xfffff3ff));28		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,29			      rtlphy->rfreg_chnlval[0]);30		break;31	default:32		pr_err("unknown bandwidth: %#X\n", bandwidth);33		break;34	}35}36 37void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,38					u8 *ppowerlevel)39{40	struct rtl_priv *rtlpriv = rtl_priv(hw);41	struct rtl_phy *rtlphy = &(rtlpriv->phy);42	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));43	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));44	u32 tx_agc[2] = { 0, 0 }, tmpval = 0;45	u8 idx1, idx2;46	u8 *ptr;47 48	if (mac->act_scanning) {49		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;50		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;51		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {52			tx_agc[idx1] = ppowerlevel[idx1] |53			    (ppowerlevel[idx1] << 8) |54			    (ppowerlevel[idx1] << 16) |55			    (ppowerlevel[idx1] << 24);56			if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa)57				tx_agc[idx1] = 0x20;58		}59	} else {60		if (rtlpriv->dm.dynamic_txhighpower_lvl ==61		    TXHIGHPWRLEVEL_LEVEL1) {62			tx_agc[RF90_PATH_A] = 0x10101010;63			tx_agc[RF90_PATH_B] = 0x10101010;64		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==65			   TXHIGHPWRLEVEL_LEVEL2) {66			tx_agc[RF90_PATH_A] = 0x00000000;67			tx_agc[RF90_PATH_B] = 0x00000000;68		} else {69			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {70				tx_agc[idx1] = ppowerlevel[idx1] |71				    (ppowerlevel[idx1] << 8) |72				    (ppowerlevel[idx1] << 16) |73				    (ppowerlevel[idx1] << 24);74			}75			if (rtlefuse->eeprom_regulatory == 0) {76				tmpval = (rtlphy->mcs_offset[0][6]) +77					(rtlphy->mcs_offset[0][7] <<  8);78				tx_agc[RF90_PATH_A] += tmpval;79				tmpval = (rtlphy->mcs_offset[0][14]) +80					(rtlphy->mcs_offset[0][15] << 24);81				tx_agc[RF90_PATH_B] += tmpval;82			}83		}84	}85	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {86		ptr = (u8 *) (&(tx_agc[idx1]));87		for (idx2 = 0; idx2 < 4; idx2++) {88			if (*ptr > RF6052_MAX_TX_PWR)89				*ptr = RF6052_MAX_TX_PWR;90			ptr++;91		}92	}93	tmpval = tx_agc[RF90_PATH_A] & 0xff;94	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);95 96	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,97		"CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n",98		tmpval, RTXAGC_A_CCK1_MCS32);99 100	tmpval = tx_agc[RF90_PATH_A] >> 8;101	if (mac->mode == WIRELESS_MODE_B)102		tmpval = tmpval & 0xff00ffff;103	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);104	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,105		"CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n",106		tmpval, RTXAGC_B_CCK11_A_CCK2_11);107	tmpval = tx_agc[RF90_PATH_B] >> 24;108	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);109	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,110		"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n",111		tmpval, RTXAGC_B_CCK11_A_CCK2_11);112	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;113	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);114	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,115		"CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n",116		tmpval, RTXAGC_B_CCK1_55_MCS32);117}118 119static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,120				      u8 *ppowerlevel, u8 channel,121				      u32 *ofdmbase, u32 *mcsbase)122{123	struct rtl_priv *rtlpriv = rtl_priv(hw);124	struct rtl_phy *rtlphy = &(rtlpriv->phy);125	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));126	u32 powerbase0, powerbase1;127	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;128	u8 i, powerlevel[2];129 130	for (i = 0; i < 2; i++) {131		powerlevel[i] = ppowerlevel[i];132		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];133		powerbase0 = powerlevel[i] + legacy_pwrdiff;134		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |135		    (powerbase0 << 8) | powerbase0;136		*(ofdmbase + i) = powerbase0;137		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,138			" [OFDM power base index rf(%c) = 0x%x]\n",139			i == 0 ? 'A' : 'B', *(ofdmbase + i));140	}141	for (i = 0; i < 2; i++) {142		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {143			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];144			powerlevel[i] += ht20_pwrdiff;145		}146		powerbase1 = powerlevel[i];147		powerbase1 = (powerbase1 << 24) |148		    (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;149		*(mcsbase + i) = powerbase1;150		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,151			" [MCS power base index rf(%c) = 0x%x]\n",152			i == 0 ? 'A' : 'B', *(mcsbase + i));153	}154}155 156static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,157						       u8 channel, u8 index,158						       u32 *powerbase0,159						       u32 *powerbase1,160						       u32 *p_outwriteval)161{162	struct rtl_priv *rtlpriv = rtl_priv(hw);163	struct rtl_phy *rtlphy = &(rtlpriv->phy);164	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));165	u8 i, chnlgroup = 0, pwr_diff_limit[4];166	u32 writeval, customer_limit, rf;167 168	for (rf = 0; rf < 2; rf++) {169		switch (rtlefuse->eeprom_regulatory) {170		case 0:171			chnlgroup = 0;172			writeval = rtlphy->mcs_offset173			    [chnlgroup][index + (rf ? 8 : 0)]174			    + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);175			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,176				"RTK better performance,writeval(%c) = 0x%x\n",177				rf == 0 ? 'A' : 'B', writeval);178			break;179		case 1:180			if (rtlphy->pwrgroup_cnt == 1)181				chnlgroup = 0;182			if (rtlphy->pwrgroup_cnt >= 3) {183				if (channel <= 3)184					chnlgroup = 0;185				else if (channel >= 4 && channel <= 9)186					chnlgroup = 1;187				else if (channel > 9)188					chnlgroup = 2;189				if (rtlphy->current_chan_bw ==190				    HT_CHANNEL_WIDTH_20)191					chnlgroup++;192				else193					chnlgroup += 4;194			}195			writeval = rtlphy->mcs_offset[chnlgroup][index +196					(rf ? 8 : 0)] +197					((index < 2) ? powerbase0[rf] :198					powerbase1[rf]);199			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,200				"Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",201				rf == 0 ? 'A' : 'B', writeval);202			break;203		case 2:204			writeval = ((index < 2) ? powerbase0[rf] :205				   powerbase1[rf]);206			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,207				"Better regulatory,writeval(%c) = 0x%x\n",208				rf == 0 ? 'A' : 'B', writeval);209			break;210		case 3:211			chnlgroup = 0;212			if (rtlphy->current_chan_bw ==213			    HT_CHANNEL_WIDTH_20_40) {214				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,215					"customer's limit, 40MHzrf(%c) = 0x%x\n",216					rf == 0 ? 'A' : 'B',217					rtlefuse->pwrgroup_ht40[rf]218					[channel - 1]);219			} else {220				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,221					"customer's limit, 20MHz rf(%c) = 0x%x\n",222					rf == 0 ? 'A' : 'B',223					rtlefuse->pwrgroup_ht20[rf]224					[channel - 1]);225			}226			for (i = 0; i < 4; i++) {227				pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset228				    [chnlgroup][index + (rf ? 8 : 0)]229				    & (0x7f << (i * 8))) >> (i * 8));230				if (rtlphy->current_chan_bw ==231				    HT_CHANNEL_WIDTH_20_40) {232					if (pwr_diff_limit[i] >233					    rtlefuse->pwrgroup_ht40[rf]234						[channel - 1])235						pwr_diff_limit[i] = rtlefuse->236						    pwrgroup_ht40[rf]237						    [channel - 1];238				} else {239					if (pwr_diff_limit[i] >240					    rtlefuse->pwrgroup_ht20[rf]241						[channel - 1])242						pwr_diff_limit[i] =243						    rtlefuse->pwrgroup_ht20[rf]244						    [channel - 1];245				}246			}247			customer_limit = (pwr_diff_limit[3] << 24) |248			    (pwr_diff_limit[2] << 16) |249			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);250			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,251				"Customer's limit rf(%c) = 0x%x\n",252				rf == 0 ? 'A' : 'B', customer_limit);253			writeval = customer_limit + ((index < 2) ?254				   powerbase0[rf] : powerbase1[rf]);255			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,256				"Customer, writeval rf(%c)= 0x%x\n",257				rf == 0 ? 'A' : 'B', writeval);258			break;259		default:260			chnlgroup = 0;261			writeval = rtlphy->mcs_offset[chnlgroup]262				   [index + (rf ? 8 : 0)] + ((index < 2) ?263				   powerbase0[rf] : powerbase1[rf]);264			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,265				"RTK better performance, writevalrf(%c) = 0x%x\n",266				rf == 0 ? 'A' : 'B', writeval);267			break;268		}269		if (rtlpriv->dm.dynamic_txhighpower_lvl ==270		    TXHIGHPWRLEVEL_LEVEL1)271			writeval = 0x14141414;272		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==273			 TXHIGHPWRLEVEL_LEVEL2)274			writeval = 0x00000000;275		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)276			writeval = writeval - 0x06060606;277		*(p_outwriteval + rf) = writeval;278	}279}280 281static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,282					 u8 index, u32 *value)283{284	struct rtl_priv *rtlpriv = rtl_priv(hw);285	struct rtl_phy *rtlphy = &(rtlpriv->phy);286	u16 regoffset_a[6] = {287		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,288		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,289		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12290	};291	u16 regoffset_b[6] = {292		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,293		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,294		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12295	};296	u8 i, rf, pwr_val[4];297	u32 writeval;298	u16 regoffset;299 300	for (rf = 0; rf < 2; rf++) {301		writeval = value[rf];302		for (i = 0; i < 4; i++) {303			pwr_val[i] = (u8)((writeval & (0x7f << (i * 8))) >>304					  (i * 8));305			if (pwr_val[i] > RF6052_MAX_TX_PWR)306				pwr_val[i] = RF6052_MAX_TX_PWR;307		}308		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |309		    (pwr_val[1] << 8) | pwr_val[0];310		if (rf == 0)311			regoffset = regoffset_a[index];312		else313			regoffset = regoffset_b[index];314		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);315		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,316			"Set 0x%x = %08x\n", regoffset, writeval);317		if (((get_rf_type(rtlphy) == RF_2T2R) &&318		     (regoffset == RTXAGC_A_MCS15_MCS12 ||319		      regoffset == RTXAGC_B_MCS15_MCS12)) ||320		    ((get_rf_type(rtlphy) != RF_2T2R) &&321		     (regoffset == RTXAGC_A_MCS07_MCS04 ||322		      regoffset == RTXAGC_B_MCS07_MCS04))) {323			writeval = pwr_val[3];324			if (regoffset == RTXAGC_A_MCS15_MCS12 ||325			    regoffset == RTXAGC_A_MCS07_MCS04)326				regoffset = 0xc90;327			if (regoffset == RTXAGC_B_MCS15_MCS12 ||328			    regoffset == RTXAGC_B_MCS07_MCS04)329				regoffset = 0xc98;330			for (i = 0; i < 3; i++) {331				if (i != 2)332					writeval = (writeval > 8) ?333						   (writeval - 8) : 0;334				else335					writeval = (writeval > 6) ?336						   (writeval - 6) : 0;337				rtl_write_byte(rtlpriv, (u32)(regoffset + i),338					      (u8)writeval);339			}340		}341	}342}343 344void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,345					 u8 *ppowerlevel, u8 channel)346{347	u32 writeval[2], powerbase0[2], powerbase1[2];348	u8 index = 0;349 350	rtl92c_phy_get_power_base(hw, ppowerlevel,351				  channel, &powerbase0[0], &powerbase1[0]);352	for (index = 0; index < 6; index++) {353		_rtl92c_get_txpower_writeval_by_regulatory(hw,354							   channel, index,355							   &powerbase0[0],356							   &powerbase1[0],357							   &writeval[0]);358		_rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]);359	}360}361 362bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw)363{364	struct rtl_priv *rtlpriv = rtl_priv(hw);365	struct rtl_phy *rtlphy = &(rtlpriv->phy);366	bool rtstatus = true;367	u8 b_reg_hwparafile = 1;368 369	if (rtlphy->rf_type == RF_1T1R)370		rtlphy->num_total_rfpath = 1;371	else372		rtlphy->num_total_rfpath = 2;373	if (b_reg_hwparafile == 1)374		rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);375	return rtstatus;376}377 378static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)379{380	struct rtl_priv *rtlpriv = rtl_priv(hw);381	struct rtl_phy *rtlphy = &(rtlpriv->phy);382	u32 u4_regvalue = 0;383	u8 rfpath;384	bool rtstatus = true;385	struct bb_reg_def *pphyreg;386 387	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {388		pphyreg = &rtlphy->phyreg_def[rfpath];389		switch (rfpath) {390		case RF90_PATH_A:391		case RF90_PATH_C:392			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,393						    BRFSI_RFENV);394			break;395		case RF90_PATH_B:396		case RF90_PATH_D:397			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,398						    BRFSI_RFENV << 16);399			break;400		}401		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);402		udelay(1);403		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);404		udelay(1);405		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,406			      B3WIREADDREAALENGTH, 0x0);407		udelay(1);408		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);409		udelay(1);410		switch (rfpath) {411		case RF90_PATH_A:412		case RF90_PATH_B:413			rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,414					(enum radio_path) rfpath);415			break;416		case RF90_PATH_C:417			break;418		case RF90_PATH_D:419			break;420		}421		switch (rfpath) {422		case RF90_PATH_A:423		case RF90_PATH_C:424			rtl_set_bbreg(hw, pphyreg->rfintfs,425				      BRFSI_RFENV, u4_regvalue);426			break;427		case RF90_PATH_B:428		case RF90_PATH_D:429			rtl_set_bbreg(hw, pphyreg->rfintfs,430				      BRFSI_RFENV << 16, u4_regvalue);431			break;432		}433		if (!rtstatus) {434			rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,435				"Radio[%d] Fail!!\n", rfpath);436			goto phy_rf_cfg_fail;437		}438	}439	rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");440phy_rf_cfg_fail:441	return rtstatus;442}443