Linux Audio

Check our new training course

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