xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c (revision f1d2b4d338bf090296f67830025228872fd52513)
1*f1d2b4d3SLarry Finger /******************************************************************************
2*f1d2b4d3SLarry Finger  *
3*f1d2b4d3SLarry Finger  * Copyright(c) 2009-2013  Realtek Corporation.
4*f1d2b4d3SLarry Finger  *
5*f1d2b4d3SLarry Finger  * This program is free software; you can redistribute it and/or modify it
6*f1d2b4d3SLarry Finger  * under the terms of version 2 of the GNU General Public License as
7*f1d2b4d3SLarry Finger  * published by the Free Software Foundation.
8*f1d2b4d3SLarry Finger  *
9*f1d2b4d3SLarry Finger  * This program is distributed in the hope that it will be useful, but WITHOUT
10*f1d2b4d3SLarry Finger  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*f1d2b4d3SLarry Finger  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12*f1d2b4d3SLarry Finger  * more details.
13*f1d2b4d3SLarry Finger  *
14*f1d2b4d3SLarry Finger  * The full GNU General Public License is included in this distribution in the
15*f1d2b4d3SLarry Finger  * file called LICENSE.
16*f1d2b4d3SLarry Finger  *
17*f1d2b4d3SLarry Finger  * Contact Information:
18*f1d2b4d3SLarry Finger  * wlanfae <wlanfae@realtek.com>
19*f1d2b4d3SLarry Finger  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20*f1d2b4d3SLarry Finger  * Hsinchu 300, Taiwan.
21*f1d2b4d3SLarry Finger  *
22*f1d2b4d3SLarry Finger  * Larry Finger <Larry.Finger@lwfinger.net>
23*f1d2b4d3SLarry Finger  *
24*f1d2b4d3SLarry Finger  *****************************************************************************/
25*f1d2b4d3SLarry Finger 
26*f1d2b4d3SLarry Finger #include "../wifi.h"
27*f1d2b4d3SLarry Finger #include "reg.h"
28*f1d2b4d3SLarry Finger #include "def.h"
29*f1d2b4d3SLarry Finger #include "phy.h"
30*f1d2b4d3SLarry Finger #include "rf.h"
31*f1d2b4d3SLarry Finger #include "dm.h"
32*f1d2b4d3SLarry Finger 
33*f1d2b4d3SLarry Finger static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
34*f1d2b4d3SLarry Finger 
35*f1d2b4d3SLarry Finger void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
36*f1d2b4d3SLarry Finger {
37*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
38*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
39*f1d2b4d3SLarry Finger 
40*f1d2b4d3SLarry Finger 	switch (bandwidth) {
41*f1d2b4d3SLarry Finger 	case HT_CHANNEL_WIDTH_20:
42*f1d2b4d3SLarry Finger 		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
43*f1d2b4d3SLarry Finger 					     0xfffff3ff) | BIT(10) | BIT(11));
44*f1d2b4d3SLarry Finger 		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
45*f1d2b4d3SLarry Finger 			      rtlphy->rfreg_chnlval[0]);
46*f1d2b4d3SLarry Finger 		break;
47*f1d2b4d3SLarry Finger 	case HT_CHANNEL_WIDTH_20_40:
48*f1d2b4d3SLarry Finger 		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
49*f1d2b4d3SLarry Finger 					     0xfffff3ff) | BIT(10));
50*f1d2b4d3SLarry Finger 		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
51*f1d2b4d3SLarry Finger 			      rtlphy->rfreg_chnlval[0]);
52*f1d2b4d3SLarry Finger 		break;
53*f1d2b4d3SLarry Finger 	default:
54*f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
55*f1d2b4d3SLarry Finger 			 "unknown bandwidth: %#X\n", bandwidth);
56*f1d2b4d3SLarry Finger 		break;
57*f1d2b4d3SLarry Finger 	}
58*f1d2b4d3SLarry Finger }
59*f1d2b4d3SLarry Finger 
60*f1d2b4d3SLarry Finger void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
61*f1d2b4d3SLarry Finger 				       u8 *ppowerlevel)
62*f1d2b4d3SLarry Finger {
63*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
64*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
65*f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
66*f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
67*f1d2b4d3SLarry Finger 	u32 tx_agc[2] = {0, 0}, tmpval;
68*f1d2b4d3SLarry Finger 	bool turbo_scanoff = false;
69*f1d2b4d3SLarry Finger 	u8 idx1, idx2;
70*f1d2b4d3SLarry Finger 	u8 *ptr;
71*f1d2b4d3SLarry Finger 	u8 direction;
72*f1d2b4d3SLarry Finger 	u32 pwrtrac_value;
73*f1d2b4d3SLarry Finger 
74*f1d2b4d3SLarry Finger 	if (rtlefuse->eeprom_regulatory != 0)
75*f1d2b4d3SLarry Finger 		turbo_scanoff = true;
76*f1d2b4d3SLarry Finger 
77*f1d2b4d3SLarry Finger 	if (mac->act_scanning == true) {
78*f1d2b4d3SLarry Finger 		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
79*f1d2b4d3SLarry Finger 		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
80*f1d2b4d3SLarry Finger 
81*f1d2b4d3SLarry Finger 		if (turbo_scanoff) {
82*f1d2b4d3SLarry Finger 			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
83*f1d2b4d3SLarry Finger 				tx_agc[idx1] = ppowerlevel[idx1] |
84*f1d2b4d3SLarry Finger 				    (ppowerlevel[idx1] << 8) |
85*f1d2b4d3SLarry Finger 				    (ppowerlevel[idx1] << 16) |
86*f1d2b4d3SLarry Finger 				    (ppowerlevel[idx1] << 24);
87*f1d2b4d3SLarry Finger 			}
88*f1d2b4d3SLarry Finger 		}
89*f1d2b4d3SLarry Finger 	} else {
90*f1d2b4d3SLarry Finger 		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
91*f1d2b4d3SLarry Finger 			tx_agc[idx1] = ppowerlevel[idx1] |
92*f1d2b4d3SLarry Finger 			    (ppowerlevel[idx1] << 8) |
93*f1d2b4d3SLarry Finger 			    (ppowerlevel[idx1] << 16) |
94*f1d2b4d3SLarry Finger 			    (ppowerlevel[idx1] << 24);
95*f1d2b4d3SLarry Finger 		}
96*f1d2b4d3SLarry Finger 
97*f1d2b4d3SLarry Finger 		if (rtlefuse->eeprom_regulatory == 0) {
98*f1d2b4d3SLarry Finger 			tmpval =
99*f1d2b4d3SLarry Finger 			    (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
100*f1d2b4d3SLarry Finger 			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
101*f1d2b4d3SLarry Finger 			     8);
102*f1d2b4d3SLarry Finger 			tx_agc[RF90_PATH_A] += tmpval;
103*f1d2b4d3SLarry Finger 
104*f1d2b4d3SLarry Finger 			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
105*f1d2b4d3SLarry Finger 			    (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
106*f1d2b4d3SLarry Finger 			     24);
107*f1d2b4d3SLarry Finger 			tx_agc[RF90_PATH_B] += tmpval;
108*f1d2b4d3SLarry Finger 		}
109*f1d2b4d3SLarry Finger 	}
110*f1d2b4d3SLarry Finger 
111*f1d2b4d3SLarry Finger 	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
112*f1d2b4d3SLarry Finger 		ptr = (u8 *)(&tx_agc[idx1]);
113*f1d2b4d3SLarry Finger 		for (idx2 = 0; idx2 < 4; idx2++) {
114*f1d2b4d3SLarry Finger 			if (*ptr > RF6052_MAX_TX_PWR)
115*f1d2b4d3SLarry Finger 				*ptr = RF6052_MAX_TX_PWR;
116*f1d2b4d3SLarry Finger 			ptr++;
117*f1d2b4d3SLarry Finger 		}
118*f1d2b4d3SLarry Finger 	}
119*f1d2b4d3SLarry Finger 	rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
120*f1d2b4d3SLarry Finger 	if (direction == 1) {
121*f1d2b4d3SLarry Finger 		tx_agc[0] += pwrtrac_value;
122*f1d2b4d3SLarry Finger 		tx_agc[1] += pwrtrac_value;
123*f1d2b4d3SLarry Finger 	} else if (direction == 2) {
124*f1d2b4d3SLarry Finger 		tx_agc[0] -= pwrtrac_value;
125*f1d2b4d3SLarry Finger 		tx_agc[1] -= pwrtrac_value;
126*f1d2b4d3SLarry Finger 	}
127*f1d2b4d3SLarry Finger 	tmpval = tx_agc[RF90_PATH_A] & 0xff;
128*f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
129*f1d2b4d3SLarry Finger 
130*f1d2b4d3SLarry Finger 	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
131*f1d2b4d3SLarry Finger 		"CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
132*f1d2b4d3SLarry Finger 		 RTXAGC_A_CCK1_MCS32);
133*f1d2b4d3SLarry Finger 
134*f1d2b4d3SLarry Finger 	tmpval = tx_agc[RF90_PATH_A] >> 8;
135*f1d2b4d3SLarry Finger 
136*f1d2b4d3SLarry Finger 	/*tmpval = tmpval & 0xff00ffff;*/
137*f1d2b4d3SLarry Finger 
138*f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
139*f1d2b4d3SLarry Finger 
140*f1d2b4d3SLarry Finger 	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
141*f1d2b4d3SLarry Finger 		"CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
142*f1d2b4d3SLarry Finger 		 RTXAGC_B_CCK11_A_CCK2_11);
143*f1d2b4d3SLarry Finger 
144*f1d2b4d3SLarry Finger 	tmpval = tx_agc[RF90_PATH_B] >> 24;
145*f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
146*f1d2b4d3SLarry Finger 
147*f1d2b4d3SLarry Finger 	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
148*f1d2b4d3SLarry Finger 		"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
149*f1d2b4d3SLarry Finger 		 RTXAGC_B_CCK11_A_CCK2_11);
150*f1d2b4d3SLarry Finger 
151*f1d2b4d3SLarry Finger 	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
152*f1d2b4d3SLarry Finger 	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
153*f1d2b4d3SLarry Finger 
154*f1d2b4d3SLarry Finger 	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
155*f1d2b4d3SLarry Finger 		"CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
156*f1d2b4d3SLarry Finger 		 RTXAGC_B_CCK1_55_MCS32);
157*f1d2b4d3SLarry Finger }
158*f1d2b4d3SLarry Finger 
159*f1d2b4d3SLarry Finger static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw,
160*f1d2b4d3SLarry Finger 				      u8 *ppowerlevel_ofdm,
161*f1d2b4d3SLarry Finger 				      u8 *ppowerlevel_bw20,
162*f1d2b4d3SLarry Finger 				      u8 *ppowerlevel_bw40, u8 channel,
163*f1d2b4d3SLarry Finger 				      u32 *ofdmbase, u32 *mcsbase)
164*f1d2b4d3SLarry Finger {
165*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
166*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
167*f1d2b4d3SLarry Finger 	u32 powerbase0, powerbase1;
168*f1d2b4d3SLarry Finger 	u8 i, powerlevel[2];
169*f1d2b4d3SLarry Finger 
170*f1d2b4d3SLarry Finger 	for (i = 0; i < 2; i++) {
171*f1d2b4d3SLarry Finger 		powerbase0 = ppowerlevel_ofdm[i];
172*f1d2b4d3SLarry Finger 
173*f1d2b4d3SLarry Finger 		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
174*f1d2b4d3SLarry Finger 		    (powerbase0 << 8) | powerbase0;
175*f1d2b4d3SLarry Finger 		*(ofdmbase + i) = powerbase0;
176*f1d2b4d3SLarry Finger 		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
177*f1d2b4d3SLarry Finger 			" [OFDM power base index rf(%c) = 0x%x]\n",
178*f1d2b4d3SLarry Finger 			 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
179*f1d2b4d3SLarry Finger 	}
180*f1d2b4d3SLarry Finger 
181*f1d2b4d3SLarry Finger 	for (i = 0; i < 2; i++) {
182*f1d2b4d3SLarry Finger 		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
183*f1d2b4d3SLarry Finger 			powerlevel[i] = ppowerlevel_bw20[i];
184*f1d2b4d3SLarry Finger 		else
185*f1d2b4d3SLarry Finger 			powerlevel[i] = ppowerlevel_bw40[i];
186*f1d2b4d3SLarry Finger 
187*f1d2b4d3SLarry Finger 		powerbase1 = powerlevel[i];
188*f1d2b4d3SLarry Finger 		powerbase1 = (powerbase1 << 24) |
189*f1d2b4d3SLarry Finger 		    (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
190*f1d2b4d3SLarry Finger 
191*f1d2b4d3SLarry Finger 		*(mcsbase + i) = powerbase1;
192*f1d2b4d3SLarry Finger 
193*f1d2b4d3SLarry Finger 		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
194*f1d2b4d3SLarry Finger 			" [MCS power base index rf(%c) = 0x%x]\n",
195*f1d2b4d3SLarry Finger 			 ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
196*f1d2b4d3SLarry Finger 	}
197*f1d2b4d3SLarry Finger }
198*f1d2b4d3SLarry Finger 
199*f1d2b4d3SLarry Finger static void _rtl88e_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
200*f1d2b4d3SLarry Finger 						       u8 channel, u8 index,
201*f1d2b4d3SLarry Finger 						       u32 *powerbase0,
202*f1d2b4d3SLarry Finger 						       u32 *powerbase1,
203*f1d2b4d3SLarry Finger 						       u32 *p_outwriteval)
204*f1d2b4d3SLarry Finger {
205*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
206*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
207*f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
208*f1d2b4d3SLarry Finger 	u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff;
209*f1d2b4d3SLarry Finger 	u32 writeval, customer_limit, rf;
210*f1d2b4d3SLarry Finger 
211*f1d2b4d3SLarry Finger 	for (rf = 0; rf < 2; rf++) {
212*f1d2b4d3SLarry Finger 		switch (rtlefuse->eeprom_regulatory) {
213*f1d2b4d3SLarry Finger 		case 0:
214*f1d2b4d3SLarry Finger 			chnlgroup = 0;
215*f1d2b4d3SLarry Finger 
216*f1d2b4d3SLarry Finger 			writeval =
217*f1d2b4d3SLarry Finger 			    rtlphy->mcs_txpwrlevel_origoffset
218*f1d2b4d3SLarry Finger 				[chnlgroup][index + (rf ? 8 : 0)]
219*f1d2b4d3SLarry Finger 			    + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
220*f1d2b4d3SLarry Finger 
221*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
222*f1d2b4d3SLarry Finger 				"RTK better performance, writeval(%c) = 0x%x\n",
223*f1d2b4d3SLarry Finger 				((rf == 0) ? 'A' : 'B'), writeval);
224*f1d2b4d3SLarry Finger 			break;
225*f1d2b4d3SLarry Finger 		case 1:
226*f1d2b4d3SLarry Finger 			if (rtlphy->pwrgroup_cnt == 1) {
227*f1d2b4d3SLarry Finger 				chnlgroup = 0;
228*f1d2b4d3SLarry Finger 			} else {
229*f1d2b4d3SLarry Finger 				if (channel < 3)
230*f1d2b4d3SLarry Finger 					chnlgroup = 0;
231*f1d2b4d3SLarry Finger 				else if (channel < 6)
232*f1d2b4d3SLarry Finger 					chnlgroup = 1;
233*f1d2b4d3SLarry Finger 				else if (channel < 9)
234*f1d2b4d3SLarry Finger 					chnlgroup = 2;
235*f1d2b4d3SLarry Finger 				else if (channel < 12)
236*f1d2b4d3SLarry Finger 					chnlgroup = 3;
237*f1d2b4d3SLarry Finger 				else if (channel < 14)
238*f1d2b4d3SLarry Finger 					chnlgroup = 4;
239*f1d2b4d3SLarry Finger 				else if (channel == 14)
240*f1d2b4d3SLarry Finger 					chnlgroup = 5;
241*f1d2b4d3SLarry Finger 			}
242*f1d2b4d3SLarry Finger 
243*f1d2b4d3SLarry Finger 			writeval =
244*f1d2b4d3SLarry Finger 			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
245*f1d2b4d3SLarry Finger 			    [index + (rf ? 8 : 0)] + ((index < 2) ?
246*f1d2b4d3SLarry Finger 						      powerbase0[rf] :
247*f1d2b4d3SLarry Finger 						      powerbase1[rf]);
248*f1d2b4d3SLarry Finger 
249*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
250*f1d2b4d3SLarry Finger 				"Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
251*f1d2b4d3SLarry Finger 				 ((rf == 0) ? 'A' : 'B'), writeval);
252*f1d2b4d3SLarry Finger 
253*f1d2b4d3SLarry Finger 			break;
254*f1d2b4d3SLarry Finger 		case 2:
255*f1d2b4d3SLarry Finger 			writeval =
256*f1d2b4d3SLarry Finger 			    ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
257*f1d2b4d3SLarry Finger 
258*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
259*f1d2b4d3SLarry Finger 				"Better regulatory, writeval(%c) = 0x%x\n",
260*f1d2b4d3SLarry Finger 				((rf == 0) ? 'A' : 'B'), writeval);
261*f1d2b4d3SLarry Finger 			break;
262*f1d2b4d3SLarry Finger 		case 3:
263*f1d2b4d3SLarry Finger 			chnlgroup = 0;
264*f1d2b4d3SLarry Finger 
265*f1d2b4d3SLarry Finger 			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
266*f1d2b4d3SLarry Finger 				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
267*f1d2b4d3SLarry Finger 					"customer's limit, 40MHz rf(%c) = 0x%x\n",
268*f1d2b4d3SLarry Finger 					((rf == 0) ? 'A' : 'B'),
269*f1d2b4d3SLarry Finger 					rtlefuse->pwrgroup_ht40[rf][channel -
270*f1d2b4d3SLarry Finger 								    1]);
271*f1d2b4d3SLarry Finger 			} else {
272*f1d2b4d3SLarry Finger 				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
273*f1d2b4d3SLarry Finger 					"customer's limit, 20MHz rf(%c) = 0x%x\n",
274*f1d2b4d3SLarry Finger 					((rf == 0) ? 'A' : 'B'),
275*f1d2b4d3SLarry Finger 					rtlefuse->pwrgroup_ht20[rf][channel -
276*f1d2b4d3SLarry Finger 								    1]);
277*f1d2b4d3SLarry Finger 			}
278*f1d2b4d3SLarry Finger 
279*f1d2b4d3SLarry Finger 			if (index < 2)
280*f1d2b4d3SLarry Finger 				pwr_diff =
281*f1d2b4d3SLarry Finger 				   rtlefuse->txpwr_legacyhtdiff[rf][channel-1];
282*f1d2b4d3SLarry Finger 			else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
283*f1d2b4d3SLarry Finger 				pwr_diff =
284*f1d2b4d3SLarry Finger 					rtlefuse->txpwr_ht20diff[rf][channel-1];
285*f1d2b4d3SLarry Finger 
286*f1d2b4d3SLarry Finger 			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
287*f1d2b4d3SLarry Finger 				customer_pwr_diff =
288*f1d2b4d3SLarry Finger 					rtlefuse->pwrgroup_ht40[rf][channel-1];
289*f1d2b4d3SLarry Finger 			else
290*f1d2b4d3SLarry Finger 				customer_pwr_diff =
291*f1d2b4d3SLarry Finger 					rtlefuse->pwrgroup_ht20[rf][channel-1];
292*f1d2b4d3SLarry Finger 
293*f1d2b4d3SLarry Finger 			if (pwr_diff > customer_pwr_diff)
294*f1d2b4d3SLarry Finger 				pwr_diff = 0;
295*f1d2b4d3SLarry Finger 			else
296*f1d2b4d3SLarry Finger 				pwr_diff = customer_pwr_diff - pwr_diff;
297*f1d2b4d3SLarry Finger 
298*f1d2b4d3SLarry Finger 			for (i = 0; i < 4; i++) {
299*f1d2b4d3SLarry Finger 				pwr_diff_limit[i] =
300*f1d2b4d3SLarry Finger 				    (u8)((rtlphy->mcs_txpwrlevel_origoffset
301*f1d2b4d3SLarry Finger 					  [chnlgroup][index +
302*f1d2b4d3SLarry Finger 					  (rf ? 8 : 0)] & (0x7f <<
303*f1d2b4d3SLarry Finger 					  (i * 8))) >> (i * 8));
304*f1d2b4d3SLarry Finger 
305*f1d2b4d3SLarry Finger 				if (pwr_diff_limit[i] > pwr_diff)
306*f1d2b4d3SLarry Finger 					pwr_diff_limit[i] = pwr_diff;
307*f1d2b4d3SLarry Finger 			}
308*f1d2b4d3SLarry Finger 
309*f1d2b4d3SLarry Finger 			customer_limit = (pwr_diff_limit[3] << 24) |
310*f1d2b4d3SLarry Finger 			    (pwr_diff_limit[2] << 16) |
311*f1d2b4d3SLarry Finger 			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
312*f1d2b4d3SLarry Finger 
313*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
314*f1d2b4d3SLarry Finger 				"Customer's limit rf(%c) = 0x%x\n",
315*f1d2b4d3SLarry Finger 				 ((rf == 0) ? 'A' : 'B'), customer_limit);
316*f1d2b4d3SLarry Finger 
317*f1d2b4d3SLarry Finger 			writeval = customer_limit +
318*f1d2b4d3SLarry Finger 			    ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
319*f1d2b4d3SLarry Finger 
320*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
321*f1d2b4d3SLarry Finger 				"Customer, writeval rf(%c)= 0x%x\n",
322*f1d2b4d3SLarry Finger 				 ((rf == 0) ? 'A' : 'B'), writeval);
323*f1d2b4d3SLarry Finger 			break;
324*f1d2b4d3SLarry Finger 		default:
325*f1d2b4d3SLarry Finger 			chnlgroup = 0;
326*f1d2b4d3SLarry Finger 			writeval =
327*f1d2b4d3SLarry Finger 			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
328*f1d2b4d3SLarry Finger 			    [index + (rf ? 8 : 0)]
329*f1d2b4d3SLarry Finger 			    + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
330*f1d2b4d3SLarry Finger 
331*f1d2b4d3SLarry Finger 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
332*f1d2b4d3SLarry Finger 				"RTK better performance, writeval rf(%c) = 0x%x\n",
333*f1d2b4d3SLarry Finger 				 ((rf == 0) ? 'A' : 'B'), writeval);
334*f1d2b4d3SLarry Finger 			break;
335*f1d2b4d3SLarry Finger 		}
336*f1d2b4d3SLarry Finger 
337*f1d2b4d3SLarry Finger 		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
338*f1d2b4d3SLarry Finger 			writeval = writeval - 0x06060606;
339*f1d2b4d3SLarry Finger 		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
340*f1d2b4d3SLarry Finger 			 TXHIGHPWRLEVEL_BT2)
341*f1d2b4d3SLarry Finger 			writeval = writeval - 0x0c0c0c0c;
342*f1d2b4d3SLarry Finger 		*(p_outwriteval + rf) = writeval;
343*f1d2b4d3SLarry Finger 	}
344*f1d2b4d3SLarry Finger }
345*f1d2b4d3SLarry Finger 
346*f1d2b4d3SLarry Finger static void _rtl88e_write_ofdm_power_reg(struct ieee80211_hw *hw,
347*f1d2b4d3SLarry Finger 					 u8 index, u32 *value)
348*f1d2b4d3SLarry Finger {
349*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
350*f1d2b4d3SLarry Finger 	u16 regoffset_a[6] = {
351*f1d2b4d3SLarry Finger 		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
352*f1d2b4d3SLarry Finger 		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
353*f1d2b4d3SLarry Finger 		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
354*f1d2b4d3SLarry Finger 	};
355*f1d2b4d3SLarry Finger 	u16 regoffset_b[6] = {
356*f1d2b4d3SLarry Finger 		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
357*f1d2b4d3SLarry Finger 		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
358*f1d2b4d3SLarry Finger 		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
359*f1d2b4d3SLarry Finger 	};
360*f1d2b4d3SLarry Finger 	u8 i, rf, pwr_val[4];
361*f1d2b4d3SLarry Finger 	u32 writeval;
362*f1d2b4d3SLarry Finger 	u16 regoffset;
363*f1d2b4d3SLarry Finger 
364*f1d2b4d3SLarry Finger 	for (rf = 0; rf < 2; rf++) {
365*f1d2b4d3SLarry Finger 		writeval = value[rf];
366*f1d2b4d3SLarry Finger 		for (i = 0; i < 4; i++) {
367*f1d2b4d3SLarry Finger 			pwr_val[i] = (u8)((writeval & (0x7f <<
368*f1d2b4d3SLarry Finger 					   (i * 8))) >> (i * 8));
369*f1d2b4d3SLarry Finger 
370*f1d2b4d3SLarry Finger 			if (pwr_val[i] > RF6052_MAX_TX_PWR)
371*f1d2b4d3SLarry Finger 				pwr_val[i] = RF6052_MAX_TX_PWR;
372*f1d2b4d3SLarry Finger 		}
373*f1d2b4d3SLarry Finger 		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
374*f1d2b4d3SLarry Finger 		    (pwr_val[1] << 8) | pwr_val[0];
375*f1d2b4d3SLarry Finger 
376*f1d2b4d3SLarry Finger 		if (rf == 0)
377*f1d2b4d3SLarry Finger 			regoffset = regoffset_a[index];
378*f1d2b4d3SLarry Finger 		else
379*f1d2b4d3SLarry Finger 			regoffset = regoffset_b[index];
380*f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
381*f1d2b4d3SLarry Finger 
382*f1d2b4d3SLarry Finger 		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
383*f1d2b4d3SLarry Finger 			"Set 0x%x = %08x\n", regoffset, writeval);
384*f1d2b4d3SLarry Finger 	}
385*f1d2b4d3SLarry Finger }
386*f1d2b4d3SLarry Finger 
387*f1d2b4d3SLarry Finger void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
388*f1d2b4d3SLarry Finger 					u8 *ppowerlevel_ofdm,
389*f1d2b4d3SLarry Finger 					u8 *ppowerlevel_bw20,
390*f1d2b4d3SLarry Finger 					u8 *ppowerlevel_bw40, u8 channel)
391*f1d2b4d3SLarry Finger {
392*f1d2b4d3SLarry Finger 	u32 writeval[2], powerbase0[2], powerbase1[2];
393*f1d2b4d3SLarry Finger 	u8 index;
394*f1d2b4d3SLarry Finger 	u8 direction;
395*f1d2b4d3SLarry Finger 	u32 pwrtrac_value;
396*f1d2b4d3SLarry Finger 
397*f1d2b4d3SLarry Finger 	rtl88e_phy_get_power_base(hw, ppowerlevel_ofdm,
398*f1d2b4d3SLarry Finger 				  ppowerlevel_bw20, ppowerlevel_bw40,
399*f1d2b4d3SLarry Finger 				  channel, &powerbase0[0], &powerbase1[0]);
400*f1d2b4d3SLarry Finger 
401*f1d2b4d3SLarry Finger 	rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
402*f1d2b4d3SLarry Finger 
403*f1d2b4d3SLarry Finger 	for (index = 0; index < 6; index++) {
404*f1d2b4d3SLarry Finger 		_rtl88e_get_txpower_writeval_by_regulatory(hw,
405*f1d2b4d3SLarry Finger 							   channel, index,
406*f1d2b4d3SLarry Finger 							   &powerbase0[0],
407*f1d2b4d3SLarry Finger 							   &powerbase1[0],
408*f1d2b4d3SLarry Finger 							   &writeval[0]);
409*f1d2b4d3SLarry Finger 		if (direction == 1) {
410*f1d2b4d3SLarry Finger 			writeval[0] += pwrtrac_value;
411*f1d2b4d3SLarry Finger 			writeval[1] += pwrtrac_value;
412*f1d2b4d3SLarry Finger 		} else if (direction == 2) {
413*f1d2b4d3SLarry Finger 			writeval[0] -= pwrtrac_value;
414*f1d2b4d3SLarry Finger 			writeval[1] -= pwrtrac_value;
415*f1d2b4d3SLarry Finger 		}
416*f1d2b4d3SLarry Finger 		_rtl88e_write_ofdm_power_reg(hw, index, &writeval[0]);
417*f1d2b4d3SLarry Finger 	}
418*f1d2b4d3SLarry Finger }
419*f1d2b4d3SLarry Finger 
420*f1d2b4d3SLarry Finger bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw)
421*f1d2b4d3SLarry Finger {
422*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
423*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
424*f1d2b4d3SLarry Finger 
425*f1d2b4d3SLarry Finger 	if (rtlphy->rf_type == RF_1T1R)
426*f1d2b4d3SLarry Finger 		rtlphy->num_total_rfpath = 1;
427*f1d2b4d3SLarry Finger 	else
428*f1d2b4d3SLarry Finger 		rtlphy->num_total_rfpath = 2;
429*f1d2b4d3SLarry Finger 
430*f1d2b4d3SLarry Finger 	return _rtl88e_phy_rf6052_config_parafile(hw);
431*f1d2b4d3SLarry Finger }
432*f1d2b4d3SLarry Finger 
433*f1d2b4d3SLarry Finger static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
434*f1d2b4d3SLarry Finger {
435*f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
436*f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &rtlpriv->phy;
437*f1d2b4d3SLarry Finger 	u32 u4_regvalue = 0;
438*f1d2b4d3SLarry Finger 	u8 rfpath;
439*f1d2b4d3SLarry Finger 	bool rtstatus = true;
440*f1d2b4d3SLarry Finger 	struct bb_reg_def *pphyreg;
441*f1d2b4d3SLarry Finger 
442*f1d2b4d3SLarry Finger 	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
443*f1d2b4d3SLarry Finger 		pphyreg = &rtlphy->phyreg_def[rfpath];
444*f1d2b4d3SLarry Finger 
445*f1d2b4d3SLarry Finger 		switch (rfpath) {
446*f1d2b4d3SLarry Finger 		case RF90_PATH_A:
447*f1d2b4d3SLarry Finger 		case RF90_PATH_C:
448*f1d2b4d3SLarry Finger 			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
449*f1d2b4d3SLarry Finger 						    BRFSI_RFENV);
450*f1d2b4d3SLarry Finger 			break;
451*f1d2b4d3SLarry Finger 		case RF90_PATH_B:
452*f1d2b4d3SLarry Finger 		case RF90_PATH_D:
453*f1d2b4d3SLarry Finger 			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
454*f1d2b4d3SLarry Finger 						    BRFSI_RFENV << 16);
455*f1d2b4d3SLarry Finger 			break;
456*f1d2b4d3SLarry Finger 		}
457*f1d2b4d3SLarry Finger 
458*f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
459*f1d2b4d3SLarry Finger 		udelay(1);
460*f1d2b4d3SLarry Finger 
461*f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
462*f1d2b4d3SLarry Finger 		udelay(1);
463*f1d2b4d3SLarry Finger 
464*f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
465*f1d2b4d3SLarry Finger 			      B3WIREADDREAALENGTH, 0x0);
466*f1d2b4d3SLarry Finger 		udelay(1);
467*f1d2b4d3SLarry Finger 
468*f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
469*f1d2b4d3SLarry Finger 		udelay(1);
470*f1d2b4d3SLarry Finger 
471*f1d2b4d3SLarry Finger 		switch (rfpath) {
472*f1d2b4d3SLarry Finger 		case RF90_PATH_A:
473*f1d2b4d3SLarry Finger 			rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
474*f1d2b4d3SLarry Finger 						(enum radio_path)rfpath);
475*f1d2b4d3SLarry Finger 			break;
476*f1d2b4d3SLarry Finger 		case RF90_PATH_B:
477*f1d2b4d3SLarry Finger 			rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
478*f1d2b4d3SLarry Finger 						(enum radio_path)rfpath);
479*f1d2b4d3SLarry Finger 			break;
480*f1d2b4d3SLarry Finger 		case RF90_PATH_C:
481*f1d2b4d3SLarry Finger 			break;
482*f1d2b4d3SLarry Finger 		case RF90_PATH_D:
483*f1d2b4d3SLarry Finger 			break;
484*f1d2b4d3SLarry Finger 		}
485*f1d2b4d3SLarry Finger 
486*f1d2b4d3SLarry Finger 		switch (rfpath) {
487*f1d2b4d3SLarry Finger 		case RF90_PATH_A:
488*f1d2b4d3SLarry Finger 		case RF90_PATH_C:
489*f1d2b4d3SLarry Finger 			rtl_set_bbreg(hw, pphyreg->rfintfs,
490*f1d2b4d3SLarry Finger 				      BRFSI_RFENV, u4_regvalue);
491*f1d2b4d3SLarry Finger 			break;
492*f1d2b4d3SLarry Finger 		case RF90_PATH_B:
493*f1d2b4d3SLarry Finger 		case RF90_PATH_D:
494*f1d2b4d3SLarry Finger 			rtl_set_bbreg(hw, pphyreg->rfintfs,
495*f1d2b4d3SLarry Finger 				      BRFSI_RFENV << 16, u4_regvalue);
496*f1d2b4d3SLarry Finger 			break;
497*f1d2b4d3SLarry Finger 		}
498*f1d2b4d3SLarry Finger 
499*f1d2b4d3SLarry Finger 		if (rtstatus != true) {
500*f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
501*f1d2b4d3SLarry Finger 				 "Radio[%d] Fail!!", rfpath);
502*f1d2b4d3SLarry Finger 			return false;
503*f1d2b4d3SLarry Finger 		}
504*f1d2b4d3SLarry Finger 
505*f1d2b4d3SLarry Finger 	}
506*f1d2b4d3SLarry Finger 
507*f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
508*f1d2b4d3SLarry Finger 	return rtstatus;
509*f1d2b4d3SLarry Finger }
510