Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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 _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
 38
 39void rtl92cu_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 rtl92cu_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_hal *rtlhal = rtl_hal(rtlpriv);
 70	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 71	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 72	u32 tx_agc[2] = { 0, 0 }, tmpval = 0;
 73	bool turbo_scanoff = false;
 74	u8 idx1, idx2;
 75	u8 *ptr;
 76
 77	if (rtlhal->interface == INTF_PCI) {
 78		if (rtlefuse->eeprom_regulatory != 0)
 79			turbo_scanoff = true;
 80	} else {
 81		if ((rtlefuse->eeprom_regulatory != 0) ||
 82		    (rtlefuse->external_pa))
 83			turbo_scanoff = true;
 84	}
 85	if (mac->act_scanning) {
 86		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
 87		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
 88		if (turbo_scanoff) {
 89			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
 90				tx_agc[idx1] = ppowerlevel[idx1] |
 91				    (ppowerlevel[idx1] << 8) |
 92				    (ppowerlevel[idx1] << 16) |
 93				    (ppowerlevel[idx1] << 24);
 94				if (rtlhal->interface == INTF_USB) {
 95					if (tx_agc[idx1] > 0x20 &&
 96					    rtlefuse->external_pa)
 97						tx_agc[idx1] = 0x20;
 98				}
 99			}
100		}
101	} else {
102		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
103		    TXHIGHPWRLEVEL_LEVEL1) {
104			tx_agc[RF90_PATH_A] = 0x10101010;
105			tx_agc[RF90_PATH_B] = 0x10101010;
106		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
107			   TXHIGHPWRLEVEL_LEVEL2) {
108			tx_agc[RF90_PATH_A] = 0x00000000;
109			tx_agc[RF90_PATH_B] = 0x00000000;
110		} else{
111			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
112				tx_agc[idx1] = ppowerlevel[idx1] |
113				    (ppowerlevel[idx1] << 8) |
114				    (ppowerlevel[idx1] << 16) |
115				    (ppowerlevel[idx1] << 24);
116			}
117			if (rtlefuse->eeprom_regulatory == 0) {
118				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
119					[0][6]) +
120					(rtlphy->mcs_txpwrlevel_origoffset
121					[0][7] <<  8);
122				tx_agc[RF90_PATH_A] += tmpval;
123				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
124					[0][14]) +
125					(rtlphy->mcs_txpwrlevel_origoffset
126					[0][15] << 24);
127				tx_agc[RF90_PATH_B] += tmpval;
128			}
129		}
130	}
131	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
132		ptr = (u8 *) (&(tx_agc[idx1]));
133		for (idx2 = 0; idx2 < 4; idx2++) {
134			if (*ptr > RF6052_MAX_TX_PWR)
135				*ptr = RF6052_MAX_TX_PWR;
136			ptr++;
137		}
138	}
139	tmpval = tx_agc[RF90_PATH_A] & 0xff;
140	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
141
142	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
143		("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
144		 RTXAGC_A_CCK1_MCS32));
145
146	tmpval = tx_agc[RF90_PATH_A] >> 8;
147	if (mac->mode == WIRELESS_MODE_B)
148		tmpval = tmpval & 0xff00ffff;
149	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
150	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
151		("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
152		 RTXAGC_B_CCK11_A_CCK2_11));
153	tmpval = tx_agc[RF90_PATH_B] >> 24;
154	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
155	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
156		("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
157		 RTXAGC_B_CCK11_A_CCK2_11));
158	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
159	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
160	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
161		("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
162		 RTXAGC_B_CCK1_55_MCS32));
163}
164
165static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
166				      u8 *ppowerlevel, u8 channel,
167				      u32 *ofdmbase, u32 *mcsbase)
168{
169	struct rtl_priv *rtlpriv = rtl_priv(hw);
170	struct rtl_phy *rtlphy = &(rtlpriv->phy);
171	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
172	u32 powerBase0, powerBase1;
173	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
174	u8 i, powerlevel[2];
175
176	for (i = 0; i < 2; i++) {
177		powerlevel[i] = ppowerlevel[i];
178		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
179		powerBase0 = powerlevel[i] + legacy_pwrdiff;
180		powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
181		    (powerBase0 << 8) | powerBase0;
182		*(ofdmbase + i) = powerBase0;
183		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
184			(" [OFDM power base index rf(%c) = 0x%x]\n",
185			 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
186	}
187	for (i = 0; i < 2; i++) {
188		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
189			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
190			powerlevel[i] += ht20_pwrdiff;
191		}
192		powerBase1 = powerlevel[i];
193		powerBase1 = (powerBase1 << 24) |
194		    (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
195		*(mcsbase + i) = powerBase1;
196		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
197			(" [MCS power base index rf(%c) = 0x%x]\n",
198			 ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
199	}
200}
201
202static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
203						       u8 channel, u8 index,
204						       u32 *powerBase0,
205						       u32 *powerBase1,
206						       u32 *p_outwriteval)
207{
208	struct rtl_priv *rtlpriv = rtl_priv(hw);
209	struct rtl_phy *rtlphy = &(rtlpriv->phy);
210	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
211	u8 i, chnlgroup = 0, pwr_diff_limit[4];
212	u32 writeVal, customer_limit, rf;
213
214	for (rf = 0; rf < 2; rf++) {
215		switch (rtlefuse->eeprom_regulatory) {
216		case 0:
217			chnlgroup = 0;
218			writeVal = rtlphy->mcs_txpwrlevel_origoffset
219			    [chnlgroup][index + (rf ? 8 : 0)]
220			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
221			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
222				("RTK better performance,writeVal(%c) = 0x%x\n",
223				((rf == 0) ? 'A' : 'B'), writeVal));
224			break;
225		case 1:
226			if (rtlphy->pwrgroup_cnt == 1)
227				chnlgroup = 0;
228			if (rtlphy->pwrgroup_cnt >= 3) {
229				if (channel <= 3)
230					chnlgroup = 0;
231				else if (channel >= 4 && channel <= 9)
232					chnlgroup = 1;
233				else if (channel > 9)
234					chnlgroup = 2;
235				if (rtlphy->current_chan_bw ==
236				    HT_CHANNEL_WIDTH_20)
237					chnlgroup++;
238				else
239					chnlgroup += 4;
240			}
241			writeVal = rtlphy->mcs_txpwrlevel_origoffset
242					[chnlgroup][index +
243					(rf ? 8 : 0)] +
244					((index < 2) ? powerBase0[rf] :
245					powerBase1[rf]);
246			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
247				("Realtek regulatory, 20MHz, "
248				"writeVal(%c) = 0x%x\n",
249				((rf == 0) ? 'A' : 'B'), writeVal));
250			break;
251		case 2:
252			writeVal = ((index < 2) ? powerBase0[rf] :
253				   powerBase1[rf]);
254			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
255				("Better regulatory,writeVal(%c) = 0x%x\n",
256				 ((rf == 0) ? 'A' : 'B'), writeVal));
257			break;
258		case 3:
259			chnlgroup = 0;
260			if (rtlphy->current_chan_bw ==
261			    HT_CHANNEL_WIDTH_20_40) {
262				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
263					("customer's limit, 40MHzrf(%c) = "
264					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
265					rtlefuse->pwrgroup_ht40[rf]
266					[channel - 1]));
267			} else {
268				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
269					("customer's limit, 20MHz rf(%c) = "
270					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
271					rtlefuse->pwrgroup_ht20[rf]
272					[channel - 1]));
273			}
274			for (i = 0; i < 4; i++) {
275				pwr_diff_limit[i] =
276				    (u8) ((rtlphy->mcs_txpwrlevel_origoffset
277				    [chnlgroup][index + (rf ? 8 : 0)]
278				    & (0x7f << (i * 8))) >> (i * 8));
279				if (rtlphy->current_chan_bw ==
280				    HT_CHANNEL_WIDTH_20_40) {
281					if (pwr_diff_limit[i] >
282					    rtlefuse->pwrgroup_ht40[rf]
283						[channel - 1])
284						pwr_diff_limit[i] = rtlefuse->
285						    pwrgroup_ht40[rf]
286						    [channel - 1];
287				} else {
288					if (pwr_diff_limit[i] >
289					    rtlefuse->pwrgroup_ht20[rf]
290						[channel - 1])
291						pwr_diff_limit[i] =
292						    rtlefuse->pwrgroup_ht20[rf]
293						    [channel - 1];
294				}
295			}
296			customer_limit = (pwr_diff_limit[3] << 24) |
297			    (pwr_diff_limit[2] << 16) |
298			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
299			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
300				("Customer's limit rf(%c) = 0x%x\n",
301				 ((rf == 0) ? 'A' : 'B'), customer_limit));
302			writeVal = customer_limit + ((index < 2) ?
303				   powerBase0[rf] : powerBase1[rf]);
304			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
305				("Customer, writeVal rf(%c)= 0x%x\n",
306				 ((rf == 0) ? 'A' : 'B'), writeVal));
307			break;
308		default:
309			chnlgroup = 0;
310			writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
311				   [index + (rf ? 8 : 0)] + ((index < 2) ?
312				   powerBase0[rf] : powerBase1[rf]);
313			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
314				"performance, writeValrf(%c) = 0x%x\n",
315				((rf == 0) ? 'A' : 'B'), writeVal));
316			break;
317		}
318		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
319		    TXHIGHPWRLEVEL_LEVEL1)
320			writeVal = 0x14141414;
321		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
322			 TXHIGHPWRLEVEL_LEVEL2)
323			writeVal = 0x00000000;
324		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
325			writeVal = writeVal - 0x06060606;
326		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
327			 TXHIGHPWRLEVEL_BT2)
328			writeVal = writeVal;
329		*(p_outwriteval + rf) = writeVal;
330	}
331}
332
333static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
334					 u8 index, u32 *pValue)
335{
336	struct rtl_priv *rtlpriv = rtl_priv(hw);
337	struct rtl_phy *rtlphy = &(rtlpriv->phy);
338	u16 regoffset_a[6] = {
339		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
340		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
341		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
342	};
343	u16 regoffset_b[6] = {
344		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
345		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
346		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
347	};
348	u8 i, rf, pwr_val[4];
349	u32 writeVal;
350	u16 regoffset;
351
352	for (rf = 0; rf < 2; rf++) {
353		writeVal = pValue[rf];
354		for (i = 0; i < 4; i++) {
355			pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >>
356					  (i * 8));
357			if (pwr_val[i] > RF6052_MAX_TX_PWR)
358				pwr_val[i] = RF6052_MAX_TX_PWR;
359		}
360		writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
361		    (pwr_val[1] << 8) | pwr_val[0];
362		if (rf == 0)
363			regoffset = regoffset_a[index];
364		else
365			regoffset = regoffset_b[index];
366		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
367		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
368			("Set 0x%x = %08x\n", regoffset, writeVal));
369		if (((get_rf_type(rtlphy) == RF_2T2R) &&
370		     (regoffset == RTXAGC_A_MCS15_MCS12 ||
371		      regoffset == RTXAGC_B_MCS15_MCS12)) ||
372		    ((get_rf_type(rtlphy) != RF_2T2R) &&
373		     (regoffset == RTXAGC_A_MCS07_MCS04 ||
374		      regoffset == RTXAGC_B_MCS07_MCS04))) {
375			writeVal = pwr_val[3];
376			if (regoffset == RTXAGC_A_MCS15_MCS12 ||
377			    regoffset == RTXAGC_A_MCS07_MCS04)
378				regoffset = 0xc90;
379			if (regoffset == RTXAGC_B_MCS15_MCS12 ||
380			    regoffset == RTXAGC_B_MCS07_MCS04)
381				regoffset = 0xc98;
382			for (i = 0; i < 3; i++) {
383				writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
384				rtl_write_byte(rtlpriv, (u32)(regoffset + i),
385					      (u8)writeVal);
386			}
387		}
388	}
389}
390
391void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
392					 u8 *ppowerlevel, u8 channel)
393{
394	u32 writeVal[2], powerBase0[2], powerBase1[2];
395	u8 index = 0;
396
397	rtl92c_phy_get_power_base(hw, ppowerlevel,
398				  channel, &powerBase0[0], &powerBase1[0]);
399	for (index = 0; index < 6; index++) {
400		_rtl92c_get_txpower_writeval_by_regulatory(hw,
401							   channel, index,
402							   &powerBase0[0],
403							   &powerBase1[0],
404							   &writeVal[0]);
405		_rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
406	}
407}
408
409bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw)
410{
411	struct rtl_priv *rtlpriv = rtl_priv(hw);
412	struct rtl_phy *rtlphy = &(rtlpriv->phy);
413	bool rtstatus = true;
414	u8 b_reg_hwparafile = 1;
415
416	if (rtlphy->rf_type == RF_1T1R)
417		rtlphy->num_total_rfpath = 1;
418	else
419		rtlphy->num_total_rfpath = 2;
420	if (b_reg_hwparafile == 1)
421		rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);
422	return rtstatus;
423}
424
425static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
426{
427	struct rtl_priv *rtlpriv = rtl_priv(hw);
428	struct rtl_phy *rtlphy = &(rtlpriv->phy);
429	u32 u4_regvalue = 0;
430	u8 rfpath;
431	bool rtstatus = true;
432	struct bb_reg_def *pphyreg;
433
434	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
435		pphyreg = &rtlphy->phyreg_def[rfpath];
436		switch (rfpath) {
437		case RF90_PATH_A:
438		case RF90_PATH_C:
439			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
440						    BRFSI_RFENV);
441			break;
442		case RF90_PATH_B:
443		case RF90_PATH_D:
444			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
445						    BRFSI_RFENV << 16);
446			break;
447		}
448		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
449		udelay(1);
450		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
451		udelay(1);
452		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
453			      B3WIREADDREAALENGTH, 0x0);
454		udelay(1);
455		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
456		udelay(1);
457		switch (rfpath) {
458		case RF90_PATH_A:
459			rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
460					(enum radio_path) rfpath);
461			break;
462		case RF90_PATH_B:
463			rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
464					(enum radio_path) rfpath);
465			break;
466		case RF90_PATH_C:
467			break;
468		case RF90_PATH_D:
469			break;
470		}
471		switch (rfpath) {
472		case RF90_PATH_A:
473		case RF90_PATH_C:
474			rtl_set_bbreg(hw, pphyreg->rfintfs,
475				      BRFSI_RFENV, u4_regvalue);
476			break;
477		case RF90_PATH_B:
478		case RF90_PATH_D:
479			rtl_set_bbreg(hw, pphyreg->rfintfs,
480				      BRFSI_RFENV << 16, u4_regvalue);
481			break;
482		}
483		if (rtstatus != true) {
484			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
485				 ("Radio[%d] Fail!!", rfpath));
486			goto phy_rf_cfg_fail;
487		}
488	}
489	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
490	return rtstatus;
491phy_rf_cfg_fail:
492	return rtstatus;
493}