1/*++
2Copyright-c Realtek Semiconductor Corp. All rights reserved.
3
4Module Name:
5	r8192U_dm.c
6
7Abstract:
8	HW dynamic mechanism.
9
10Major Change History:
11	When		Who				What
12	----------	--------------- -------------------------------
13	2008-05-14	amy                     create version 0 porting from windows code.
14
15--*/
16#include "r8192U.h"
17#include "r8192U_dm.h"
18#include "r8192U_hw.h"
19#include "r819xU_phy.h"
20#include "r819xU_phyreg.h"
21#include "r8190_rtl8256.h"
22#include "r819xU_cmdpkt.h"
23/*---------------------------Define Local Constant---------------------------*/
24/* Indicate different AP vendor for IOT issue. */
25static u32 edca_setting_DL[HT_IOT_PEER_MAX] = {
26	0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0x00a44f, 0x5ea44f
27};
28static u32 edca_setting_UL[HT_IOT_PEER_MAX] = {
29	0x5e4322, 0x00a44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f
30};
31
32#define RTK_UL_EDCA 0xa44f
33#define RTK_DL_EDCA 0x5e4322
34/*---------------------------Define Local Constant---------------------------*/
35
36
37/*------------------------Define global variable-----------------------------*/
38/* Debug variable ? */
39struct dig dm_digtable;
40/* Store current software write register content for MAC PHY. */
41u8		dm_shadow[16][256] = { {0} };
42/* For Dynamic Rx Path Selection by Signal Strength */
43struct dynamic_rx_path_sel DM_RxPathSelTable;
44
45/*------------------------Define global variable-----------------------------*/
46
47
48/*------------------------Define local variable------------------------------*/
49/*------------------------Define local variable------------------------------*/
50
51
52/*--------------------Define export function prototype-----------------------*/
53extern	void dm_check_fsync(struct net_device *dev);
54
55/*--------------------Define export function prototype-----------------------*/
56
57
58/*---------------------Define local function prototype-----------------------*/
59/* DM --> Rate Adaptive */
60static	void	dm_check_rate_adaptive(struct net_device *dev);
61
62/* DM --> Bandwidth switch */
63static	void	dm_init_bandwidth_autoswitch(struct net_device *dev);
64static	void	dm_bandwidth_autoswitch(struct net_device *dev);
65
66/* DM --> TX power control */
67/*static	void	dm_initialize_txpower_tracking(struct net_device *dev);*/
68
69static	void	dm_check_txpower_tracking(struct net_device *dev);
70
71/*static	void	dm_txpower_reset_recovery(struct net_device *dev);*/
72
73/* DM --> Dynamic Init Gain by RSSI */
74static	void	dm_dig_init(struct net_device *dev);
75static	void	dm_ctrl_initgain_byrssi(struct net_device *dev);
76static	void	dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev);
77static	void	dm_ctrl_initgain_byrssi_by_driverrssi(struct net_device *dev);
78static	void	dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev);
79static	void	dm_initial_gain(struct net_device *dev);
80static	void	dm_pd_th(struct net_device *dev);
81static	void	dm_cs_ratio(struct net_device *dev);
82
83static	void dm_init_ctstoself(struct net_device *dev);
84/* DM --> EDCA turbo mode control */
85static	void	dm_check_edca_turbo(struct net_device *dev);
86
87/*static	void	dm_gpio_change_rf(struct net_device *dev);*/
88/* DM --> Check PBC */
89static	void dm_check_pbc_gpio(struct net_device *dev);
90
91/* DM --> Check current RX RF path state */
92static	void	dm_check_rx_path_selection(struct net_device *dev);
93static	void dm_init_rxpath_selection(struct net_device *dev);
94static	void dm_rxpath_sel_byrssi(struct net_device *dev);
95
96/* DM --> Fsync for broadcom ap */
97static void dm_init_fsync(struct net_device *dev);
98static void dm_deInit_fsync(struct net_device *dev);
99
100/* Added by vivi, 20080522 */
101static	void	dm_check_txrateandretrycount(struct net_device *dev);
102
103/*---------------------Define local function prototype-----------------------*/
104
105/*---------------------Define of Tx Power Control For Near/Far Range --------*/   /*Add by Jacken 2008/02/18 */
106static	void	dm_init_dynamic_txpower(struct net_device *dev);
107static	void	dm_dynamic_txpower(struct net_device *dev);
108
109/* DM --> For rate adaptive and DIG, we must send RSSI to firmware */
110static	void dm_send_rssi_tofw(struct net_device *dev);
111static	void	dm_ctstoself(struct net_device *dev);
112/*---------------------------Define function prototype------------------------*/
113/*
114 * ================================================================================
115 *	HW Dynamic mechanism interface.
116 * ================================================================================
117 *
118 *
119 *	Description:
120 *		Prepare SW resource for HW dynamic mechanism.
121 *
122 *	Assumption:
123 *		This function is only invoked at driver intialization once.
124 */
125void init_hal_dm(struct net_device *dev)
126{
127	struct r8192_priv *priv = ieee80211_priv(dev);
128
129	/* Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. */
130	priv->undecorated_smoothed_pwdb = -1;
131
132	/* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */
133	dm_init_dynamic_txpower(dev);
134	init_rate_adaptive(dev);
135	/*dm_initialize_txpower_tracking(dev);*/
136	dm_dig_init(dev);
137	dm_init_edca_turbo(dev);
138	dm_init_bandwidth_autoswitch(dev);
139	dm_init_fsync(dev);
140	dm_init_rxpath_selection(dev);
141	dm_init_ctstoself(dev);
142
143}	/* InitHalDm */
144
145void deinit_hal_dm(struct net_device *dev)
146{
147	dm_deInit_fsync(dev);
148}
149
150#ifdef USB_RX_AGGREGATION_SUPPORT
151void dm_CheckRxAggregation(struct net_device *dev)
152{
153	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
154	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
155	static unsigned long	lastTxOkCnt;
156	static unsigned long	lastRxOkCnt;
157	unsigned long		curTxOkCnt = 0;
158	unsigned long		curRxOkCnt = 0;
159
160/*
161	if (pHalData->bForcedUsbRxAggr) {
162		if (pHalData->ForcedUsbRxAggrInfo == 0) {
163			if (pHalData->bCurrentRxAggrEnable) {
164				Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, FALSE);
165			}
166		} else {
167			if (!pHalData->bCurrentRxAggrEnable || (pHalData->ForcedUsbRxAggrInfo != pHalData->LastUsbRxAggrInfoSetting)) {
168				Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, TRUE);
169			}
170		}
171		return;
172	}
173
174*/
175	curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
176	curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
177
178	if ((curTxOkCnt + curRxOkCnt) < 15000000)
179		return;
180
181	if (curTxOkCnt > 4*curRxOkCnt) {
182		if (priv->bCurrentRxAggrEnable) {
183			write_nic_dword(dev, 0x1a8, 0);
184			priv->bCurrentRxAggrEnable = false;
185		}
186	} else {
187		if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) {
188			u32 ulValue;
189
190			ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
191				(pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
192			/*
193			 * If usb rx firmware aggregation is enabled,
194			 * when anyone of three threshold conditions above is reached,
195			 * firmware will send aggregated packet to driver.
196			 */
197			write_nic_dword(dev, 0x1a8, ulValue);
198			priv->bCurrentRxAggrEnable = true;
199		}
200	}
201
202	lastTxOkCnt = priv->stats.txbytesunicast;
203	lastRxOkCnt = priv->stats.rxbytesunicast;
204}	/* dm_CheckEdcaTurbo */
205#endif
206
207void hal_dm_watchdog(struct net_device *dev)
208{
209	/*struct r8192_priv *priv = ieee80211_priv(dev);*/
210
211	/*static u8	previous_bssid[6] ={0};*/
212
213	/*Add by amy 2008/05/15 ,porting from windows code.*/
214	dm_check_rate_adaptive(dev);
215	dm_dynamic_txpower(dev);
216	dm_check_txrateandretrycount(dev);
217	dm_check_txpower_tracking(dev);
218	dm_ctrl_initgain_byrssi(dev);
219	dm_check_edca_turbo(dev);
220	dm_bandwidth_autoswitch(dev);
221	dm_check_rx_path_selection(dev);
222	dm_check_fsync(dev);
223
224	/* Add by amy 2008-05-15 porting from windows code. */
225	dm_check_pbc_gpio(dev);
226	dm_send_rssi_tofw(dev);
227	dm_ctstoself(dev);
228#ifdef USB_RX_AGGREGATION_SUPPORT
229	dm_CheckRxAggregation(dev);
230#endif
231}	/* HalDmWatchDog */
232
233/*
234 * Decide Rate Adaptive Set according to distance (signal strength)
235 *	01/11/2008	MHC		Modify input arguments and RATR table level.
236 *	01/16/2008	MHC		RF_Type is assigned in ReadAdapterInfo(). We must call
237 *						the function after making sure RF_Type.
238 */
239void init_rate_adaptive(struct net_device *dev)
240{
241	struct r8192_priv *priv = ieee80211_priv(dev);
242	prate_adaptive	pra = (prate_adaptive)&priv->rate_adaptive;
243
244	pra->ratr_state = DM_RATR_STA_MAX;
245	pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
246	pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
247	pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
248
249	pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
250	pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
251	pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
252
253	if (priv->CustomerID == RT_CID_819x_Netcore)
254		pra->ping_rssi_enable = 1;
255	else
256		pra->ping_rssi_enable = 0;
257	pra->ping_rssi_thresh_for_ra = 15;
258
259	if (priv->rf_type == RF_2T4R) {
260		/*
261		 * 07/10/08 MH Modify for RA smooth scheme.
262		 * 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.
263		 */
264		pra->upper_rssi_threshold_ratr		=	0x8f0f0000;
265		pra->middle_rssi_threshold_ratr		=	0x8f0ff000;
266		pra->low_rssi_threshold_ratr		=	0x8f0ff001;
267		pra->low_rssi_threshold_ratr_40M	=	0x8f0ff005;
268		pra->low_rssi_threshold_ratr_20M	=	0x8f0ff001;
269		pra->ping_rssi_ratr	=	0x0000000d;/* cosa add for test */
270	} else if (priv->rf_type == RF_1T2R) {
271		pra->upper_rssi_threshold_ratr		=	0x000f0000;
272		pra->middle_rssi_threshold_ratr		=	0x000ff000;
273		pra->low_rssi_threshold_ratr		=	0x000ff001;
274		pra->low_rssi_threshold_ratr_40M	=	0x000ff005;
275		pra->low_rssi_threshold_ratr_20M	=	0x000ff001;
276		pra->ping_rssi_ratr	=	0x0000000d;/* cosa add for test */
277	}
278
279}	/* InitRateAdaptive */
280
281/*-----------------------------------------------------------------------------
282 * Function:	dm_check_rate_adaptive()
283 *
284 * Overview:
285 *
286 * Input:		NONE
287 *
288 * Output:		NONE
289 *
290 * Return:		NONE
291 *
292 * Revised History:
293 *	When		Who		Remark
294 *	05/26/08	amy	Create version 0 porting from windows code.
295 *
296 *---------------------------------------------------------------------------*/
297static void dm_check_rate_adaptive(struct net_device *dev)
298{
299	struct r8192_priv *priv = ieee80211_priv(dev);
300	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
301	prate_adaptive			pra = (prate_adaptive)&priv->rate_adaptive;
302	u32						currentRATR, targetRATR = 0;
303	u32						LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
304	bool						bshort_gi_enabled = false;
305	static u8					ping_rssi_state;
306
307	if (!priv->up) {
308		RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
309		return;
310	}
311
312	if (pra->rate_adaptive_disabled) /* this variable is set by ioctl. */
313		return;
314
315	/* TODO: Only 11n mode is implemented currently, */
316	if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G ||
317	      priv->ieee80211->mode == WIRELESS_MODE_N_5G))
318		return;
319
320	if (priv->ieee80211->state == IEEE80211_LINKED) {
321		/*RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");*/
322
323		/* Check whether Short GI is enabled */
324		bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
325			(!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
326
327		pra->upper_rssi_threshold_ratr =
328				(pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
329
330		pra->middle_rssi_threshold_ratr =
331				(pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
332
333		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
334			pra->low_rssi_threshold_ratr =
335				(pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
336		} else {
337			pra->low_rssi_threshold_ratr =
338			(pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
339		}
340		/* cosa add for test */
341		pra->ping_rssi_ratr =
342				(pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
343
344		/* 2007/10/08 MH We support RA smooth scheme now. When it is the first
345		   time to link with AP. We will not change upper/lower threshold. If
346		   STA stay in high or low level, we must change two different threshold
347		   to prevent jumping frequently. */
348		if (pra->ratr_state == DM_RATR_STA_HIGH) {
349			HighRSSIThreshForRA	= pra->high2low_rssi_thresh_for_ra;
350			LowRSSIThreshForRA	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
351					(pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
352		} else if (pra->ratr_state == DM_RATR_STA_LOW) {
353			HighRSSIThreshForRA	= pra->high_rssi_thresh_for_ra;
354			LowRSSIThreshForRA	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
355					(pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M);
356		} else {
357			HighRSSIThreshForRA	= pra->high_rssi_thresh_for_ra;
358			LowRSSIThreshForRA	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
359					(pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
360		}
361
362		/*DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA);*/
363		if (priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) {
364			/*DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB);*/
365			pra->ratr_state = DM_RATR_STA_HIGH;
366			targetRATR = pra->upper_rssi_threshold_ratr;
367		} else if (priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) {
368			/*DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB);*/
369			pra->ratr_state = DM_RATR_STA_MIDDLE;
370			targetRATR = pra->middle_rssi_threshold_ratr;
371		} else {
372			/*DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB);*/
373			pra->ratr_state = DM_RATR_STA_LOW;
374			targetRATR = pra->low_rssi_threshold_ratr;
375		}
376
377		/* cosa add for test */
378		if (pra->ping_rssi_enable) {
379			/*pHalData->UndecoratedSmoothedPWDB = 19;*/
380			if (priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) {
381				if ((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
382					ping_rssi_state) {
383					/*DbgPrint("TestRSSI = %d, set RATR to 0x%x\n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);*/
384					pra->ratr_state = DM_RATR_STA_LOW;
385					targetRATR = pra->ping_rssi_ratr;
386					ping_rssi_state = 1;
387				}
388				/*else
389					DbgPrint("TestRSSI is between the range.\n");*/
390			} else {
391				/*DbgPrint("TestRSSI Recover to 0x%x\n", targetRATR);*/
392				ping_rssi_state = 0;
393			}
394		}
395
396		/*
397		 * 2008.04.01
398		 * For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
399		 */
400		if (priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev))
401			targetRATR &= 0xf00fffff;
402
403		/* Check whether updating of RATR0 is required */
404		read_nic_dword(dev, RATR0, &currentRATR);
405		if (targetRATR !=  currentRATR) {
406			u32 ratr_value;
407
408			ratr_value = targetRATR;
409			RT_TRACE(COMP_RATE, "currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);
410			if (priv->rf_type == RF_1T2R)
411				ratr_value &= ~(RATE_ALL_OFDM_2SS);
412			write_nic_dword(dev, RATR0, ratr_value);
413			write_nic_byte(dev, UFWP, 1);
414
415			pra->last_ratr = targetRATR;
416		}
417
418	} else {
419		pra->ratr_state = DM_RATR_STA_MAX;
420	}
421
422}	/* dm_CheckRateAdaptive */
423
424static void dm_init_bandwidth_autoswitch(struct net_device *dev)
425{
426	struct r8192_priv *priv = ieee80211_priv(dev);
427
428	priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
429	priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
430	priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
431	priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false;
432
433}	/* dm_init_bandwidth_autoswitch */
434
435static void dm_bandwidth_autoswitch(struct net_device *dev)
436{
437	struct r8192_priv *priv = ieee80211_priv(dev);
438
439	if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable)
440		return;
441	if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */
442		if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
443			priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
444	} else { /* in force send packets in 20 Mhz in 20/40 */
445		if (priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
446			priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
447	}
448}	/* dm_BandwidthAutoSwitch */
449
450/* OFDM default at 0db, index=6. */
451static u32 OFDMSwingTable[OFDM_Table_Length] = {
452	0x7f8001fe,	/* 0, +6db */
453	0x71c001c7,	/* 1, +5db */
454	0x65400195,	/* 2, +4db */
455	0x5a400169,	/* 3, +3db */
456	0x50800142,	/* 4, +2db */
457	0x47c0011f,	/* 5, +1db */
458	0x40000100,	/* 6, +0db ===> default, upper for higher temperature, lower for low temperature */
459	0x390000e4,	/* 7, -1db */
460	0x32c000cb,	/* 8, -2db */
461	0x2d4000b5,	/* 9, -3db */
462	0x288000a2,	/* 10, -4db */
463	0x24000090,	/* 11, -5db */
464	0x20000080,	/* 12, -6db */
465	0x1c800072,	/* 13, -7db */
466	0x19800066,	/* 14, -8db */
467	0x26c0005b,	/* 15, -9db */
468	0x24400051,	/* 16, -10db */
469	0x12000048,	/* 17, -11db */
470	0x10000040	/* 18, -12db */
471};
472
473static u8	CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
474	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},	/* 0, +0db ===> CCK40M default */
475	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},	/* 1, -1db */
476	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},	/* 2, -2db */
477	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},	/* 3, -3db */
478	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},	/* 4, -4db */
479	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},	/* 5, -5db */
480	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},	/* 6, -6db ===> CCK20M default */
481	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},	/* 7, -7db */
482	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},	/* 8, -8db */
483	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},	/* 9, -9db */
484	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},	/* 10, -10db */
485	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}	/* 11, -11db */
486};
487
488static u8	CCKSwingTable_Ch14[CCK_Table_length][8] = {
489	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},	/* 0, +0db  ===> CCK40M default */
490	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},	/* 1, -1db */
491	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},	/* 2, -2db */
492	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},	/* 3, -3db */
493	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},	/* 4, -4db */
494	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},	/* 5, -5db */
495	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},	/* 6, -6db  ===> CCK20M default */
496	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},	/* 7, -7db */
497	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},	/* 8, -8db */
498	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},	/* 9, -9db */
499	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},	/* 10, -10db */
500	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}	/* 11, -11db */
501};
502
503static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
504{
505	struct r8192_priv *priv = ieee80211_priv(dev);
506	bool						bHighpowerstate, viviflag = false;
507	DCMD_TXCMD_T			tx_cmd;
508	u8						powerlevelOFDM24G;
509	int						i = 0, j = 0, k = 0;
510	u8						RF_Type, tmp_report[5] = {0, 0, 0, 0, 0};
511	u32						Value;
512	u8						Pwr_Flag;
513	u16						Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver = 0;
514	/*RT_STATUS				rtStatus = RT_STATUS_SUCCESS;*/
515	bool rtStatus = true;
516	u32						delta = 0;
517
518	write_nic_byte(dev, 0x1ba, 0);
519
520	priv->ieee80211->bdynamic_txpower_enable = false;
521	bHighpowerstate = priv->bDynamicTxHighPower;
522
523	powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24);
524	RF_Type = priv->rf_type;
525	Value = (RF_Type<<8) | powerlevelOFDM24G;
526
527	RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G);
528
529	for (j = 0; j <= 30; j++) { /* fill tx_cmd */
530		tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
531		tx_cmd.Length = 4;
532		tx_cmd.Value = Value;
533		rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12);
534		if (rtStatus == RT_STATUS_FAILURE)
535			RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n");
536		mdelay(1);
537		/*DbgPrint("hi, vivi, strange\n");*/
538		for (i = 0; i <= 30; i++) {
539			read_nic_byte(dev, 0x1ba, &Pwr_Flag);
540
541			if (Pwr_Flag == 0) {
542				mdelay(1);
543				continue;
544			}
545			read_nic_word(dev, 0x13c, &Avg_TSSI_Meas);
546			if (Avg_TSSI_Meas == 0) {
547				write_nic_byte(dev, 0x1ba, 0);
548				break;
549			}
550
551			for (k = 0; k < 5; k++) {
552				if (k != 4)
553					read_nic_byte(dev, 0x134+k, &tmp_report[k]);
554				else
555					read_nic_byte(dev, 0x13e, &tmp_report[k]);
556				RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
557			}
558
559			/* check if the report value is right */
560			for (k = 0; k < 5; k++) {
561				if (tmp_report[k] <= 20) {
562					viviflag = true;
563					break;
564				}
565			}
566			if (viviflag == true) {
567				write_nic_byte(dev, 0x1ba, 0);
568				viviflag = false;
569				RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n");
570				for (k = 0; k < 5; k++)
571					tmp_report[k] = 0;
572				break;
573			}
574
575			for (k = 0; k < 5; k++)
576				Avg_TSSI_Meas_from_driver += tmp_report[k];
577
578			Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
579			RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver);
580			TSSI_13dBm = priv->TSSI_13dBm;
581			RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
582
583			/*if (abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)*/
584			/* For MacOS-compatible */
585			if (Avg_TSSI_Meas_from_driver > TSSI_13dBm)
586				delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
587			else
588				delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
589
590			if (delta <= E_FOR_TX_POWER_TRACK) {
591				priv->ieee80211->bdynamic_txpower_enable = true;
592				write_nic_byte(dev, 0x1ba, 0);
593				RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
594				RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
595				RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
596				RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
597				RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
598				return;
599			}
600			if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) {
601				if (priv->rfa_txpowertrackingindex > 0) {
602					priv->rfa_txpowertrackingindex--;
603					if (priv->rfa_txpowertrackingindex_real > 4) {
604						priv->rfa_txpowertrackingindex_real--;
605						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
606					}
607				}
608			} else {
609				if (priv->rfa_txpowertrackingindex < 36) {
610					priv->rfa_txpowertrackingindex++;
611					priv->rfa_txpowertrackingindex_real++;
612					rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
613
614				}
615			}
616			priv->cck_present_attentuation_difference
617				= priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
618
619			if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
620				priv->cck_present_attentuation
621					= priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference;
622			else
623				priv->cck_present_attentuation
624					= priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference;
625
626			if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) {
627				if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) {
628					priv->bcck_in_ch14 = true;
629					dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
630				} else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) {
631					priv->bcck_in_ch14 = false;
632					dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
633				} else
634					dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
635			}
636			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
637			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
638			RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
639			RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
640
641			if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) {
642				priv->ieee80211->bdynamic_txpower_enable = true;
643				write_nic_byte(dev, 0x1ba, 0);
644				RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
645				return;
646			}
647
648			write_nic_byte(dev, 0x1ba, 0);
649			Avg_TSSI_Meas_from_driver = 0;
650			for (k = 0; k < 5; k++)
651				tmp_report[k] = 0;
652			break;
653		}
654	}
655	priv->ieee80211->bdynamic_txpower_enable = true;
656	write_nic_byte(dev, 0x1ba, 0);
657}
658
659static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
660{
661#define ThermalMeterVal	9
662	struct r8192_priv *priv = ieee80211_priv(dev);
663	u32 tmpRegA, TempCCk;
664	u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
665	int i = 0, CCKSwingNeedUpdate = 0;
666
667	if (!priv->btxpower_trackingInit) {
668		/* Query OFDM default setting */
669		tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
670		for (i = 0; i < OFDM_Table_Length; i++) { /* find the index */
671			if (tmpRegA == OFDMSwingTable[i]) {
672				priv->OFDM_index = (u8)i;
673				RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n",
674					rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index);
675			}
676		}
677
678		/* Query CCK default setting From 0xa22 */
679		TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
680		for (i = 0; i < CCK_Table_length; i++) {
681			if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
682				priv->CCK_index = (u8) i;
683				RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n",
684					rCCK0_TxFilter1, TempCCk, priv->CCK_index);
685				break;
686			}
687		}
688		priv->btxpower_trackingInit = true;
689		/*pHalData->TXPowercount = 0;*/
690		return;
691	}
692
693	/*
694	 * ==========================
695	 * this is only for test, should be masked
696	 * ==========================
697	 */
698
699	/* read and filter out unreasonable value */
700	tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);	/* 0x12: RF Reg[10:7] */
701	RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
702	if (tmpRegA < 3 || tmpRegA > 13)
703		return;
704	if (tmpRegA >= 12)	/* if over 12, TP will be bad when high temperature */
705		tmpRegA = 12;
706	RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA);
707	priv->ThermalMeter[0] = ThermalMeterVal;	/* We use fixed value by Bryant's suggestion */
708	priv->ThermalMeter[1] = ThermalMeterVal;	/* We use fixed value by Bryant's suggestion */
709
710	/* Get current RF-A temperature index */
711	if (priv->ThermalMeter[0] >= (u8)tmpRegA) {	/* lower temperature */
712		tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
713		tmpCCK40Mindex = tmpCCK20Mindex - 6;
714		if (tmpOFDMindex >= OFDM_Table_Length)
715			tmpOFDMindex = OFDM_Table_Length-1;
716		if (tmpCCK20Mindex >= CCK_Table_length)
717			tmpCCK20Mindex = CCK_Table_length-1;
718		if (tmpCCK40Mindex >= CCK_Table_length)
719			tmpCCK40Mindex = CCK_Table_length-1;
720	} else {
721		tmpval = (u8)tmpRegA - priv->ThermalMeter[0];
722
723		if (tmpval >= 6) /* higher temperature */
724			tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */
725		else
726			tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
727		tmpCCK40Mindex = 0;
728	}
729	/*DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d",
730		((u1Byte)tmpRegA - pHalData->ThermalMeter[0]),
731		tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex);*/
732	if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)	/* 40M */
733		tmpCCKindex = tmpCCK40Mindex;
734	else
735		tmpCCKindex = tmpCCK20Mindex;
736
737	if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) {
738		priv->bcck_in_ch14 = true;
739		CCKSwingNeedUpdate = 1;
740	} else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) {
741		priv->bcck_in_ch14 = false;
742		CCKSwingNeedUpdate = 1;
743	}
744
745	if (priv->CCK_index != tmpCCKindex) {
746		priv->CCK_index = tmpCCKindex;
747		CCKSwingNeedUpdate = 1;
748	}
749
750	if (CCKSwingNeedUpdate) {
751		/*DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index);*/
752		dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
753	}
754	if (priv->OFDM_index != tmpOFDMindex) {
755		priv->OFDM_index = tmpOFDMindex;
756		rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
757		RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
758			priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
759	}
760	priv->txpower_count = 0;
761}
762
763void dm_txpower_trackingcallback(struct work_struct *work)
764{
765	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
766	struct r8192_priv *priv = container_of(dwork, struct r8192_priv, txpower_tracking_wq);
767	struct net_device *dev = priv->ieee80211->dev;
768
769	if (priv->bDcut == true)
770		dm_TXPowerTrackingCallback_TSSI(dev);
771	else
772		dm_TXPowerTrackingCallback_ThermalMeter(dev);
773}
774
775static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
776{
777	struct r8192_priv *priv = ieee80211_priv(dev);
778
779	/* Initial the Tx BB index and mapping value */
780	priv->txbbgain_table[0].txbb_iq_amplifygain =			12;
781	priv->txbbgain_table[0].txbbgain_value = 0x7f8001fe;
782	priv->txbbgain_table[1].txbb_iq_amplifygain =			11;
783	priv->txbbgain_table[1].txbbgain_value = 0x788001e2;
784	priv->txbbgain_table[2].txbb_iq_amplifygain =			10;
785	priv->txbbgain_table[2].txbbgain_value = 0x71c001c7;
786	priv->txbbgain_table[3].txbb_iq_amplifygain =			9;
787	priv->txbbgain_table[3].txbbgain_value = 0x6b8001ae;
788	priv->txbbgain_table[4].txbb_iq_amplifygain =		       8;
789	priv->txbbgain_table[4].txbbgain_value = 0x65400195;
790	priv->txbbgain_table[5].txbb_iq_amplifygain =		       7;
791	priv->txbbgain_table[5].txbbgain_value = 0x5fc0017f;
792	priv->txbbgain_table[6].txbb_iq_amplifygain =		       6;
793	priv->txbbgain_table[6].txbbgain_value = 0x5a400169;
794	priv->txbbgain_table[7].txbb_iq_amplifygain =		       5;
795	priv->txbbgain_table[7].txbbgain_value = 0x55400155;
796	priv->txbbgain_table[8].txbb_iq_amplifygain =		       4;
797	priv->txbbgain_table[8].txbbgain_value = 0x50800142;
798	priv->txbbgain_table[9].txbb_iq_amplifygain =		       3;
799	priv->txbbgain_table[9].txbbgain_value = 0x4c000130;
800	priv->txbbgain_table[10].txbb_iq_amplifygain =		       2;
801	priv->txbbgain_table[10].txbbgain_value = 0x47c0011f;
802	priv->txbbgain_table[11].txbb_iq_amplifygain =		       1;
803	priv->txbbgain_table[11].txbbgain_value = 0x43c0010f;
804	priv->txbbgain_table[12].txbb_iq_amplifygain =		       0;
805	priv->txbbgain_table[12].txbbgain_value = 0x40000100;
806	priv->txbbgain_table[13].txbb_iq_amplifygain =		       -1;
807	priv->txbbgain_table[13].txbbgain_value = 0x3c8000f2;
808	priv->txbbgain_table[14].txbb_iq_amplifygain =		     -2;
809	priv->txbbgain_table[14].txbbgain_value = 0x390000e4;
810	priv->txbbgain_table[15].txbb_iq_amplifygain =		     -3;
811	priv->txbbgain_table[15].txbbgain_value = 0x35c000d7;
812	priv->txbbgain_table[16].txbb_iq_amplifygain =		     -4;
813	priv->txbbgain_table[16].txbbgain_value = 0x32c000cb;
814	priv->txbbgain_table[17].txbb_iq_amplifygain =		     -5;
815	priv->txbbgain_table[17].txbbgain_value = 0x300000c0;
816	priv->txbbgain_table[18].txbb_iq_amplifygain =			    -6;
817	priv->txbbgain_table[18].txbbgain_value = 0x2d4000b5;
818	priv->txbbgain_table[19].txbb_iq_amplifygain =		     -7;
819	priv->txbbgain_table[19].txbbgain_value = 0x2ac000ab;
820	priv->txbbgain_table[20].txbb_iq_amplifygain =		     -8;
821	priv->txbbgain_table[20].txbbgain_value = 0x288000a2;
822	priv->txbbgain_table[21].txbb_iq_amplifygain =		     -9;
823	priv->txbbgain_table[21].txbbgain_value = 0x26000098;
824	priv->txbbgain_table[22].txbb_iq_amplifygain =		     -10;
825	priv->txbbgain_table[22].txbbgain_value = 0x24000090;
826	priv->txbbgain_table[23].txbb_iq_amplifygain =		     -11;
827	priv->txbbgain_table[23].txbbgain_value = 0x22000088;
828	priv->txbbgain_table[24].txbb_iq_amplifygain =		     -12;
829	priv->txbbgain_table[24].txbbgain_value = 0x20000080;
830	priv->txbbgain_table[25].txbb_iq_amplifygain =		     -13;
831	priv->txbbgain_table[25].txbbgain_value = 0x1a00006c;
832	priv->txbbgain_table[26].txbb_iq_amplifygain =		     -14;
833	priv->txbbgain_table[26].txbbgain_value = 0x1c800072;
834	priv->txbbgain_table[27].txbb_iq_amplifygain =		     -15;
835	priv->txbbgain_table[27].txbbgain_value = 0x18000060;
836	priv->txbbgain_table[28].txbb_iq_amplifygain =		     -16;
837	priv->txbbgain_table[28].txbbgain_value = 0x19800066;
838	priv->txbbgain_table[29].txbb_iq_amplifygain =		     -17;
839	priv->txbbgain_table[29].txbbgain_value = 0x15800056;
840	priv->txbbgain_table[30].txbb_iq_amplifygain =		     -18;
841	priv->txbbgain_table[30].txbbgain_value = 0x26c0005b;
842	priv->txbbgain_table[31].txbb_iq_amplifygain =		     -19;
843	priv->txbbgain_table[31].txbbgain_value = 0x14400051;
844	priv->txbbgain_table[32].txbb_iq_amplifygain =		     -20;
845	priv->txbbgain_table[32].txbbgain_value = 0x24400051;
846	priv->txbbgain_table[33].txbb_iq_amplifygain =		     -21;
847	priv->txbbgain_table[33].txbbgain_value = 0x1300004c;
848	priv->txbbgain_table[34].txbb_iq_amplifygain =		     -22;
849	priv->txbbgain_table[34].txbbgain_value = 0x12000048;
850	priv->txbbgain_table[35].txbb_iq_amplifygain =		     -23;
851	priv->txbbgain_table[35].txbbgain_value = 0x11000044;
852	priv->txbbgain_table[36].txbb_iq_amplifygain =		     -24;
853	priv->txbbgain_table[36].txbbgain_value = 0x10000040;
854
855	/*
856	 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
857	 * This Table is for CH1~CH13
858	 */
859	priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36;
860	priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35;
861	priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e;
862	priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25;
863	priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c;
864	priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12;
865	priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09;
866	priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04;
867
868	priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33;
869	priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32;
870	priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b;
871	priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23;
872	priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a;
873	priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11;
874	priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08;
875	priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04;
876
877	priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30;
878	priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f;
879	priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29;
880	priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21;
881	priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19;
882	priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10;
883	priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08;
884	priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03;
885
886	priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d;
887	priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d;
888	priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27;
889	priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f;
890	priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18;
891	priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f;
892	priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08;
893	priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03;
894
895	priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b;
896	priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a;
897	priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25;
898	priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e;
899	priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16;
900	priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e;
901	priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07;
902	priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03;
903
904	priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28;
905	priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28;
906	priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22;
907	priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c;
908	priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15;
909	priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d;
910	priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07;
911	priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03;
912
913	priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26;
914	priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25;
915	priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21;
916	priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b;
917	priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14;
918	priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d;
919	priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06;
920	priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03;
921
922	priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24;
923	priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23;
924	priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f;
925	priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19;
926	priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13;
927	priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c;
928	priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06;
929	priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03;
930
931	priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22;
932	priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21;
933	priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d;
934	priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18;
935	priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11;
936	priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b;
937	priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06;
938	priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02;
939
940	priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20;
941	priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20;
942	priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b;
943	priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16;
944	priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11;
945	priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08;
946	priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05;
947	priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02;
948
949	priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f;
950	priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e;
951	priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a;
952	priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15;
953	priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10;
954	priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a;
955	priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05;
956	priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02;
957
958	priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d;
959	priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c;
960	priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18;
961	priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14;
962	priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f;
963	priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a;
964	priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05;
965	priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02;
966
967	priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b;
968	priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a;
969	priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17;
970	priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13;
971	priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e;
972	priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09;
973	priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04;
974	priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02;
975
976	priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a;
977	priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19;
978	priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16;
979	priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12;
980	priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d;
981	priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09;
982	priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04;
983	priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02;
984
985	priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18;
986	priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17;
987	priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15;
988	priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11;
989	priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c;
990	priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08;
991	priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04;
992	priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02;
993
994	priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17;
995	priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16;
996	priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13;
997	priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10;
998	priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c;
999	priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08;
1000	priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04;
1001	priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02;
1002
1003	priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16;
1004	priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15;
1005	priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12;
1006	priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f;
1007	priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b;
1008	priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07;
1009	priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04;
1010	priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01;
1011
1012	priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14;
1013	priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14;
1014	priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11;
1015	priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e;
1016	priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b;
1017	priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07;
1018	priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03;
1019	priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02;
1020
1021	priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13;
1022	priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13;
1023	priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10;
1024	priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d;
1025	priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a;
1026	priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06;
1027	priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03;
1028	priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01;
1029
1030	priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12;
1031	priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12;
1032	priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f;
1033	priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c;
1034	priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09;
1035	priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06;
1036	priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03;
1037	priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01;
1038
1039	priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11;
1040	priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11;
1041	priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f;
1042	priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c;
1043	priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09;
1044	priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06;
1045	priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03;
1046	priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01;
1047
1048	priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10;
1049	priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10;
1050	priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e;
1051	priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b;
1052	priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08;
1053	priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05;
1054	priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03;
1055	priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01;
1056
1057	priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f;
1058	priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f;
1059	priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d;
1060	priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b;
1061	priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08;
1062	priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05;
1063	priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03;
1064	priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01;
1065
1066	/*
1067	 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
1068	 * This Table is for CH14
1069	 */
1070	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36;
1071	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35;
1072	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e;
1073	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b;
1074	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00;
1075	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00;
1076	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00;
1077	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00;
1078
1079	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33;
1080	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32;
1081	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b;
1082	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19;
1083	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00;
1084	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00;
1085	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00;
1086	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00;
1087
1088	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30;
1089	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f;
1090	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29;
1091	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18;
1092	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00;
1093	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00;
1094	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00;
1095	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00;
1096
1097	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d;
1098	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d;
1099	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27;
1100	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17;
1101	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00;
1102	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00;
1103	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00;
1104	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00;
1105
1106	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b;
1107	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a;
1108	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25;
1109	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15;
1110	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00;
1111	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00;
1112	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00;
1113	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00;
1114
1115	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28;
1116	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28;
1117	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22;
1118	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14;
1119	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00;
1120	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00;
1121	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00;
1122	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00;
1123
1124	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26;
1125	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25;
1126	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21;
1127	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13;
1128	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00;
1129	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00;
1130	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00;
1131	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00;
1132
1133	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24;
1134	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23;
1135	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f;
1136	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12;
1137	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00;
1138	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00;
1139	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00;
1140	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00;
1141
1142	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22;
1143	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21;
1144	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d;
1145	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11;
1146	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00;
1147	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00;
1148	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00;
1149	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00;
1150
1151	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20;
1152	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20;
1153	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b;
1154	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10;
1155	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00;
1156	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00;
1157	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00;
1158	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00;
1159
1160	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f;
1161	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e;
1162	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a;
1163	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f;
1164	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00;
1165	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00;
1166	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00;
1167	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00;
1168
1169	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d;
1170	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c;
1171	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18;
1172	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e;
1173	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00;
1174	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00;
1175	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00;
1176	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00;
1177
1178	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b;
1179	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a;
1180	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17;
1181	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e;
1182	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00;
1183	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00;
1184	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00;
1185	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00;
1186
1187	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a;
1188	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19;
1189	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16;
1190	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d;
1191	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00;
1192	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00;
1193	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00;
1194	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00;
1195
1196	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18;
1197	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17;
1198	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15;
1199	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c;
1200	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00;
1201	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00;
1202	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00;
1203	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00;
1204
1205	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17;
1206	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16;
1207	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13;
1208	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b;
1209	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00;
1210	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00;
1211	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00;
1212	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00;
1213
1214	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16;
1215	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15;
1216	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12;
1217	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b;
1218	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00;
1219	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00;
1220	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00;
1221	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00;
1222
1223	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14;
1224	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14;
1225	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11;
1226	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a;
1227	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00;
1228	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00;
1229	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00;
1230	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00;
1231
1232	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13;
1233	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13;
1234	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10;
1235	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a;
1236	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00;
1237	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00;
1238	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00;
1239	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00;
1240
1241	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12;
1242	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12;
1243	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f;
1244	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09;
1245	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00;
1246	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00;
1247	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00;
1248	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00;
1249
1250	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11;
1251	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11;
1252	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f;
1253	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09;
1254	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00;
1255	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00;
1256	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00;
1257	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00;
1258
1259	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10;
1260	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10;
1261	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e;
1262	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08;
1263	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00;
1264	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00;
1265	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00;
1266	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00;
1267
1268	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f;
1269	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f;
1270	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d;
1271	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08;
1272	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00;
1273	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00;
1274	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00;
1275	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00;
1276
1277	priv->btxpower_tracking = true;
1278	priv->txpower_count       = 0;
1279	priv->btxpower_trackingInit = false;
1280
1281}
1282
1283static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
1284{
1285	struct r8192_priv *priv = ieee80211_priv(dev);
1286
1287	/*
1288	 * Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism
1289	 * can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
1290	 * 3-wire by driver causes RF to go into a wrong state.
1291	 */
1292	if (priv->ieee80211->FwRWRF)
1293		priv->btxpower_tracking = true;
1294	else
1295		priv->btxpower_tracking = false;
1296	priv->txpower_count       = 0;
1297	priv->btxpower_trackingInit = false;
1298}
1299
1300void dm_initialize_txpower_tracking(struct net_device *dev)
1301{
1302	struct r8192_priv *priv = ieee80211_priv(dev);
1303
1304	if (priv->bDcut == true)
1305		dm_InitializeTXPowerTracking_TSSI(dev);
1306	else
1307		dm_InitializeTXPowerTracking_ThermalMeter(dev);
1308} /* dm_InitializeTXPowerTracking */
1309
1310static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
1311{
1312	struct r8192_priv *priv = ieee80211_priv(dev);
1313	static u32 tx_power_track_counter;
1314
1315	if (!priv->btxpower_tracking)
1316		return;
1317	if ((tx_power_track_counter % 30 == 0) && (tx_power_track_counter != 0))
1318		queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0);
1319	tx_power_track_counter++;
1320}
1321
1322static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
1323{
1324	struct r8192_priv *priv = ieee80211_priv(dev);
1325	static u8	TM_Trigger;
1326	/*DbgPrint("dm_CheckTXPowerTracking()\n");*/
1327	if (!priv->btxpower_tracking)
1328		return;
1329	if (priv->txpower_count  <= 2) {
1330		priv->txpower_count++;
1331		return;
1332	}
1333
1334	if (!TM_Trigger) {
1335		/*
1336		 * Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash
1337		 * actually write reg0x02 bit1=0, then bit1=1.
1338		 * DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n");
1339		 */
1340		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
1341		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
1342		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
1343		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
1344		TM_Trigger = 1;
1345		return;
1346	}
1347	/*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/
1348		queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0);
1349	TM_Trigger = 0;
1350}
1351
1352static void dm_check_txpower_tracking(struct net_device *dev)
1353{
1354	struct r8192_priv *priv = ieee80211_priv(dev);
1355	/*static u32 tx_power_track_counter = 0;*/
1356
1357#ifdef RTL8190P
1358	dm_CheckTXPowerTracking_TSSI(dev);
1359#else
1360	if (priv->bDcut == true)
1361		dm_CheckTXPowerTracking_TSSI(dev);
1362	else
1363		dm_CheckTXPowerTracking_ThermalMeter(dev);
1364#endif
1365
1366}	/* dm_CheckTXPowerTracking */
1367
1368static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
1369{
1370	u32 TempVal;
1371	struct r8192_priv *priv = ieee80211_priv(dev);
1372
1373	/* Write 0xa22 0xa23 */
1374	TempVal = 0;
1375	if (!bInCH14) {
1376		/* Write 0xa22 0xa23 */
1377		TempVal =	priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] +
1378					(priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8);
1379
1380		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1381		/* Write 0xa24 ~ 0xa27 */
1382		TempVal =	priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] +
1383					(priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) +
1384					(priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+
1385					(priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24);
1386		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1387		/* Write 0xa28  0xa29 */
1388		TempVal =	priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] +
1389					(priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8);
1390
1391		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1392	} else {
1393		TempVal =	priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] +
1394					(priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8);
1395
1396		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1397		/* Write 0xa24 ~ 0xa27 */
1398		TempVal =	priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] +
1399					(priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) +
1400					(priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+
1401					(priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24);
1402		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1403		/* Write 0xa28  0xa29 */
1404		TempVal =	priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] +
1405					(priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8);
1406
1407		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1408	}
1409}
1410
1411static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool  bInCH14)
1412{
1413	u32 TempVal;
1414	struct r8192_priv *priv = ieee80211_priv(dev);
1415
1416	TempVal = 0;
1417	if (!bInCH14) {
1418		/* Write 0xa22 0xa23 */
1419		TempVal =	CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
1420					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8);
1421		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1422		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1423			rCCK0_TxFilter1, TempVal);
1424		/* Write 0xa24 ~ 0xa27 */
1425		TempVal =	CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
1426					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
1427					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16)+
1428					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
1429		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1430		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1431			rCCK0_TxFilter2, TempVal);
1432		/* Write 0xa28  0xa29 */
1433		TempVal =	CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
1434					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8);
1435
1436		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1437		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1438			rCCK0_DebugPort, TempVal);
1439	} else {
1440		/*priv->CCKTxPowerAdjustCntNotCh14++;	cosa add for debug.*/
1441		/* Write 0xa22 0xa23 */
1442		TempVal =	CCKSwingTable_Ch14[priv->CCK_index][0] +
1443					(CCKSwingTable_Ch14[priv->CCK_index][1]<<8);
1444
1445		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1446		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1447			rCCK0_TxFilter1, TempVal);
1448		/* Write 0xa24 ~ 0xa27 */
1449		TempVal =	CCKSwingTable_Ch14[priv->CCK_index][2] +
1450					(CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
1451					(CCKSwingTable_Ch14[priv->CCK_index][4]<<16)+
1452					(CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
1453		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1454		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1455			rCCK0_TxFilter2, TempVal);
1456		/* Write 0xa28  0xa29 */
1457		TempVal =	CCKSwingTable_Ch14[priv->CCK_index][6] +
1458					(CCKSwingTable_Ch14[priv->CCK_index][7]<<8);
1459
1460		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1461		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1462			rCCK0_DebugPort, TempVal);
1463	}
1464}
1465
1466void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
1467{	/*  dm_CCKTxPowerAdjust */
1468	struct r8192_priv *priv = ieee80211_priv(dev);
1469
1470	if (priv->bDcut == true)
1471		dm_CCKTxPowerAdjust_TSSI(dev, binch14);
1472	else
1473		dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
1474}
1475
1476#ifndef RTL8192U
1477static void dm_txpower_reset_recovery(
1478	struct net_device *dev
1479)
1480{
1481	struct r8192_priv *priv = ieee80211_priv(dev);
1482
1483	RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
1484	rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
1485	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
1486	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n", priv->rfa_txpowertrackingindex);
1487	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain);
1488	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n", priv->cck_present_attentuation);
1489	dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
1490
1491	rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
1492	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
1493	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n", priv->rfc_txpowertrackingindex);
1494	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain);
1495
1496}	/* dm_TXPowerResetRecovery */
1497
1498void dm_restore_dynamic_mechanism_state(struct net_device *dev)
1499{
1500	struct r8192_priv *priv = ieee80211_priv(dev);
1501	u32	reg_ratr = priv->rate_adaptive.last_ratr;
1502
1503	if (!priv->up) {
1504		RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
1505		return;
1506	}
1507
1508	/* Restore previous state for rate adaptive */
1509	if (priv->rate_adaptive.rate_adaptive_disabled)
1510		return;
1511	/* TODO: Only 11n mode is implemented currently, */
1512	if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G ||
1513		priv->ieee80211->mode == WIRELESS_MODE_N_5G))
1514		return;
1515
1516	{
1517			/* 2007/11/15 MH Copy from 8190PCI. */
1518			u32 ratr_value;
1519
1520			ratr_value = reg_ratr;
1521			if (priv->rf_type == RF_1T2R) {	/* 1T2R, Spatial Stream 2 should be disabled */
1522				ratr_value &= ~(RATE_ALL_OFDM_2SS);
1523				/*DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value);*/
1524			}
1525			/*DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value);*/
1526			/*cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]);*/
1527			write_nic_dword(dev, RATR0, ratr_value);
1528			write_nic_byte(dev, UFWP, 1);
1529	}
1530	/* Restore TX Power Tracking Index */
1531	if (priv->btxpower_trackingInit && priv->btxpower_tracking)
1532		dm_txpower_reset_recovery(dev);
1533
1534	/* Restore BB Initial Gain */
1535	dm_bb_initialgain_restore(dev);
1536
1537}	/* DM_RestoreDynamicMechanismState */
1538
1539static void dm_bb_initialgain_restore(struct net_device *dev)
1540{
1541	struct r8192_priv *priv = ieee80211_priv(dev);
1542	u32 bit_mask = 0x7f; /* Bit0~ Bit6 */
1543
1544	if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1545		return;
1546
1547	/* Disable Initial Gain */
1548	/*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/
1549	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	/* Only clear byte 1 and rewrite. */
1550	rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1);
1551	rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1);
1552	rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1);
1553	rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1);
1554	bit_mask  = bMaskByte2;
1555	rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca);
1556
1557	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n", priv->initgain_backup.xaagccore1);
1558	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n", priv->initgain_backup.xbagccore1);
1559	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n", priv->initgain_backup.xcagccore1);
1560	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n", priv->initgain_backup.xdagccore1);
1561	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca);
1562	/* Enable Initial Gain */
1563	/*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100);*/
1564	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	/* Only clear byte 1 and rewrite. */
1565
1566}	/* dm_BBInitialGainRestore */
1567
1568void dm_backup_dynamic_mechanism_state(struct net_device *dev)
1569{
1570	struct r8192_priv *priv = ieee80211_priv(dev);
1571
1572	/* Fsync to avoid reset */
1573	priv->bswitch_fsync  = false;
1574	priv->bfsync_processing = false;
1575	/* Backup BB InitialGain */
1576	dm_bb_initialgain_backup(dev);
1577
1578}	/* DM_BackupDynamicMechanismState */
1579
1580static void dm_bb_initialgain_backup(struct net_device *dev)
1581{
1582	struct r8192_priv *priv = ieee80211_priv(dev);
1583	u32 bit_mask = bMaskByte0; /* Bit0~ Bit6 */
1584
1585	if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1586		return;
1587
1588	/*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/
1589	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	/* Only clear byte 1 and rewrite. */
1590	priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
1591	priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
1592	priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
1593	priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
1594	bit_mask  = bMaskByte2;
1595	priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
1596
1597	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n", priv->initgain_backup.xaagccore1);
1598	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n", priv->initgain_backup.xbagccore1);
1599	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n", priv->initgain_backup.xcagccore1);
1600	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n", priv->initgain_backup.xdagccore1);
1601	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n", priv->initgain_backup.cca);
1602
1603}   /* dm_BBInitialGainBakcup */
1604
1605#endif
1606/*-----------------------------------------------------------------------------
1607 * Function:	dm_change_dynamic_initgain_thresh()
1608 *
1609 * Overview:
1610 *
1611 * Input:		NONE
1612 *
1613 * Output:		NONE
1614 *
1615 * Return:		NONE
1616 *
1617 * Revised History:
1618 *	When		Who		Remark
1619 *	05/29/2008	amy		Create Version 0 porting from windows code.
1620 *
1621 *---------------------------------------------------------------------------*/
1622
1623void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type,
1624				       u32 dm_value)
1625{
1626	if (dm_type == DIG_TYPE_THRESH_HIGH) {
1627		dm_digtable.rssi_high_thresh = dm_value;
1628	} else if (dm_type == DIG_TYPE_THRESH_LOW) {
1629		dm_digtable.rssi_low_thresh = dm_value;
1630	} else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) {
1631		dm_digtable.rssi_high_power_highthresh = dm_value;
1632	} else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) {
1633		dm_digtable.rssi_high_power_lowthresh = dm_value;
1634	} else if (dm_type == DIG_TYPE_ENABLE) {
1635		dm_digtable.dig_state		= DM_STA_DIG_MAX;
1636		dm_digtable.dig_enable_flag	= true;
1637	} else if (dm_type == DIG_TYPE_DISABLE) {
1638		dm_digtable.dig_state		= DM_STA_DIG_MAX;
1639		dm_digtable.dig_enable_flag	= false;
1640	} else if (dm_type == DIG_TYPE_DBG_MODE) {
1641		if (dm_value >= DM_DBG_MAX)
1642			dm_value = DM_DBG_OFF;
1643		dm_digtable.dbg_mode		= (u8)dm_value;
1644	} else if (dm_type == DIG_TYPE_RSSI) {
1645		if (dm_value > 100)
1646			dm_value = 30;
1647		dm_digtable.rssi_val			= (long)dm_value;
1648	} else if (dm_type == DIG_TYPE_ALGORITHM) {
1649		if (dm_value >= DIG_ALGO_MAX)
1650			dm_value = DIG_ALGO_BY_FALSE_ALARM;
1651		if (dm_digtable.dig_algorithm != (u8)dm_value)
1652			dm_digtable.dig_algorithm_switch = 1;
1653		dm_digtable.dig_algorithm	= (u8)dm_value;
1654	} else if (dm_type == DIG_TYPE_BACKOFF) {
1655		if (dm_value > 30)
1656			dm_value = 30;
1657		dm_digtable.backoff_val		= (u8)dm_value;
1658	} else if (dm_type == DIG_TYPE_RX_GAIN_MIN) {
1659		if (dm_value == 0)
1660			dm_value = 0x1;
1661		dm_digtable.rx_gain_range_min = (u8)dm_value;
1662	} else if (dm_type == DIG_TYPE_RX_GAIN_MAX) {
1663		if (dm_value > 0x50)
1664			dm_value = 0x50;
1665		dm_digtable.rx_gain_range_max = (u8)dm_value;
1666	}
1667}	/* DM_ChangeDynamicInitGainThresh */
1668
1669/*-----------------------------------------------------------------------------
1670 * Function:	dm_dig_init()
1671 *
1672 * Overview:	Set DIG scheme init value.
1673 *
1674 * Input:		NONE
1675 *
1676 * Output:		NONE
1677 *
1678 * Return:		NONE
1679 *
1680 * Revised History:
1681 *	When		Who		Remark
1682 *	05/15/2008	amy		Create Version 0 porting from windows code.
1683 *
1684 *---------------------------------------------------------------------------*/
1685static void dm_dig_init(struct net_device *dev)
1686{
1687	struct r8192_priv *priv = ieee80211_priv(dev);
1688	/* 2007/10/05 MH Disable DIG scheme now. Not tested. */
1689	dm_digtable.dig_enable_flag	= true;
1690	dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
1691	dm_digtable.dbg_mode = DM_DBG_OFF;	/* off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig */
1692	dm_digtable.dig_algorithm_switch = 0;
1693
1694	/* 2007/10/04 MH Define init gain threshold. */
1695	dm_digtable.dig_state		= DM_STA_DIG_MAX;
1696	dm_digtable.dig_highpwr_state	= DM_STA_DIG_MAX;
1697	dm_digtable.initialgain_lowerbound_state = false;
1698
1699	dm_digtable.rssi_low_thresh	= DM_DIG_THRESH_LOW;
1700	dm_digtable.rssi_high_thresh	= DM_DIG_THRESH_HIGH;
1701
1702	dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
1703	dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
1704
1705	dm_digtable.rssi_val = 50;	/* for new dig debug rssi value */
1706	dm_digtable.backoff_val = DM_DIG_BACKOFF;
1707	dm_digtable.rx_gain_range_max = DM_DIG_MAX;
1708	if (priv->CustomerID == RT_CID_819x_Netcore)
1709		dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;
1710	else
1711		dm_digtable.rx_gain_range_min = DM_DIG_MIN;
1712
1713}	/* dm_dig_init */
1714
1715/*-----------------------------------------------------------------------------
1716 * Function:	dm_ctrl_initgain_byrssi()
1717 *
1718 * Overview:	Driver must monitor RSSI and notify firmware to change initial
1719 *				gain according to different threshold. BB team provide the
1720 *				suggested solution.
1721 *
1722 * Input:			struct net_device *dev
1723 *
1724 * Output:		NONE
1725 *
1726 * Return:		NONE
1727 *
1728 * Revised History:
1729 *	When		Who		Remark
1730 *	05/27/2008	amy		Create Version 0 porting from windows code.
1731 *---------------------------------------------------------------------------*/
1732static void dm_ctrl_initgain_byrssi(struct net_device *dev)
1733{
1734	if (dm_digtable.dig_enable_flag == false)
1735		return;
1736
1737	if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
1738		dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev);
1739	else if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1740		dm_ctrl_initgain_byrssi_by_driverrssi(dev);
1741	/* ; */
1742	else
1743		return;
1744}
1745
1746static void dm_ctrl_initgain_byrssi_by_driverrssi(
1747	struct net_device *dev)
1748{
1749	struct r8192_priv *priv = ieee80211_priv(dev);
1750	u8 i;
1751	static u8	fw_dig;
1752
1753	if (dm_digtable.dig_enable_flag == false)
1754		return;
1755
1756	/*DbgPrint("Dig by Sw Rssi\n");*/
1757	if (dm_digtable.dig_algorithm_switch)	/* if switched algorithm, we have to disable FW Dig. */
1758		fw_dig = 0;
1759
1760	if (fw_dig <= 3) { /* execute several times to make sure the FW Dig is disabled */
1761		/* FW DIG Off */
1762		for (i = 0; i < 3; i++)
1763			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	/* Only clear byte 1 and rewrite. */
1764		fw_dig++;
1765		dm_digtable.dig_state = DM_STA_DIG_OFF;	/* fw dig off. */
1766	}
1767
1768	if (priv->ieee80211->state == IEEE80211_LINKED)
1769		dm_digtable.cur_connect_state = DIG_CONNECT;
1770	else
1771		dm_digtable.cur_connect_state = DIG_DISCONNECT;
1772
1773	/*DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d\n",
1774		DM_DigTable.PreConnectState, DM_DigTable.CurConnectState);*/
1775
1776	if (dm_digtable.dbg_mode == DM_DBG_OFF)
1777		dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
1778	/*DbgPrint("DM_DigTable.Rssi_val = %d\n", DM_DigTable.Rssi_val);*/
1779	dm_initial_gain(dev);
1780	dm_pd_th(dev);
1781	dm_cs_ratio(dev);
1782	if (dm_digtable.dig_algorithm_switch)
1783		dm_digtable.dig_algorithm_switch = 0;
1784	dm_digtable.pre_connect_state = dm_digtable.cur_connect_state;
1785
1786}	/* dm_CtrlInitGainByRssi */
1787
1788static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
1789	struct net_device *dev)
1790{
1791	struct r8192_priv *priv = ieee80211_priv(dev);
1792	static u32 reset_cnt;
1793	u8 i;
1794
1795	if (dm_digtable.dig_enable_flag == false)
1796		return;
1797
1798	if (dm_digtable.dig_algorithm_switch) {
1799		dm_digtable.dig_state = DM_STA_DIG_MAX;
1800		/* Fw DIG On. */
1801		for (i = 0; i < 3; i++)
1802			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	/* Only clear byte 1 and rewrite.*/
1803		dm_digtable.dig_algorithm_switch = 0;
1804	}
1805
1806	if (priv->ieee80211->state != IEEE80211_LINKED)
1807		return;
1808
1809	/* For smooth, we can not change DIG state. */
1810	if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
1811		(priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
1812		return;
1813
1814	/*DbgPrint("Dig by Fw False Alarm\n");*/
1815	/*if (DM_DigTable.Dig_State == DM_STA_DIG_OFF)*/
1816	/*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d",
1817	pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh,
1818	DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/
1819	/* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
1820		  and then execute the step below. */
1821	if (priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh) {
1822		/* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters
1823		   will be reset to init value. We must prevent the condition. */
1824		if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
1825		    (priv->reset_count == reset_cnt)) {
1826			return;
1827		}
1828		reset_cnt = priv->reset_count;
1829
1830		/* If DIG is off, DIG high power state must reset. */
1831		dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
1832		dm_digtable.dig_state = DM_STA_DIG_OFF;
1833
1834		/*  1.1 DIG Off. */
1835		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	/*  Only clear byte 1 and rewrite. */
1836
1837		/*  1.2 Set initial gain. */
1838		write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
1839		write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
1840		write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
1841		write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
1842
1843		/*  1.3 Lower PD_TH for OFDM. */
1844		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
1845			/*
1846			 * 2008/01/11 MH 40MHZ 90/92 register are not the same.
1847			 * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1848			 */
1849			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
1850			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
1851				write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40);
1852			else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E)
1853			else
1854				PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40);
1855			*/
1856		} else
1857			write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
1858
1859		/* 1.4 Lower CS ratio for CCK. */
1860		write_nic_byte(dev, 0xa0a, 0x08);
1861
1862		/* 1.5 Higher EDCCA. */
1863		/*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);*/
1864		return;
1865
1866	}
1867
1868	/* 2. When RSSI increase, We have to judge if it is larger than a threshold
1869		  and then execute the step below.  */
1870	if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
1871		u8 reset_flag = 0;
1872
1873		if (dm_digtable.dig_state == DM_STA_DIG_ON &&
1874			(priv->reset_count == reset_cnt)) {
1875			dm_ctrl_initgain_byrssi_highpwr(dev);
1876			return;
1877		}
1878		if (priv->reset_count != reset_cnt)
1879			reset_flag = 1;
1880
1881		reset_cnt = priv->reset_count;
1882
1883		dm_digtable.dig_state = DM_STA_DIG_ON;
1884		/*DbgPrint("DIG ON\n\r");*/
1885
1886		/*
1887		 * 2.1 Set initial gain.
1888		 * 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment.
1889		 */
1890		if (reset_flag == 1) {
1891			write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
1892			write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
1893			write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
1894			write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
1895		} else {
1896			write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
1897			write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
1898			write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
1899			write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
1900		}
1901
1902		/* 2.2 Higher PD_TH for OFDM. */
1903		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
1904			/*
1905			 * 2008/01/11 MH 40MHZ 90/92 register are not the same.
1906			 * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1907			 */
1908			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
1909			/*
1910			else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
1911				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
1912			else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E)
1913			else
1914				PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42);
1915			*/
1916		} else
1917			write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
1918
1919		/* 2.3 Higher CS ratio for CCK. */
1920		write_nic_byte(dev, 0xa0a, 0xcd);
1921
1922		/*
1923		 * 2.4 Lower EDCCA.
1924		 * 2008/01/11 MH 90/92 series are the same.
1925		 */
1926		/*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);*/
1927
1928		/* 2.5 DIG On. */
1929		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	/*  Only clear byte 1 and rewrite. */
1930
1931	}
1932
1933	dm_ctrl_initgain_byrssi_highpwr(dev);
1934
1935}	/* dm_CtrlInitGainByRssi */
1936
1937/*-----------------------------------------------------------------------------
1938 * Function:	dm_ctrl_initgain_byrssi_highpwr()
1939 *
1940 * Overview:
1941 *
1942 * Input:		NONE
1943 *
1944 * Output:		NONE
1945 *
1946 * Return:		NONE
1947 *
1948 * Revised History:
1949 *	When		Who		Remark
1950 *	05/28/2008	amy		Create Version 0 porting from windows code.
1951 *
1952 *---------------------------------------------------------------------------*/
1953static void dm_ctrl_initgain_byrssi_highpwr(
1954	struct net_device *dev)
1955{
1956	struct r8192_priv *priv = ieee80211_priv(dev);
1957	static u32 reset_cnt_highpwr;
1958
1959	/*  For smooth, we can not change high power DIG state in the range. */
1960	if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
1961		(priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
1962		return;
1963
1964	/*
1965	 * 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if
1966	 *    it is larger than a threshold and then execute the step below.
1967	 *
1968	 * 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue.
1969	 */
1970	if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) {
1971		if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
1972			(priv->reset_count == reset_cnt_highpwr))
1973			return;
1974		dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
1975
1976		/* 3.1 Higher PD_TH for OFDM for high power state. */
1977		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
1978			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
1979
1980			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
1981				write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
1982			*/
1983
1984		} else
1985			write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
1986	} else {
1987		if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF &&
1988			(priv->reset_count == reset_cnt_highpwr))
1989			return;
1990		dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
1991
1992		if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
1993			 priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
1994			/*  3.2 Recover PD_TH for OFDM for normal power region. */
1995			if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
1996				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
1997				/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
1998					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
1999				*/
2000
2001			} else
2002				write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
2003		}
2004	}
2005
2006	reset_cnt_highpwr = priv->reset_count;
2007
2008}	/* dm_CtrlInitGainByRssiHighPwr */
2009
2010static void dm_initial_gain(
2011	struct net_device *dev)
2012{
2013	struct r8192_priv *priv = ieee80211_priv(dev);
2014	u8					initial_gain = 0;
2015	static u8				initialized, force_write;
2016	static u32			reset_cnt;
2017	u8				tmp;
2018
2019	if (dm_digtable.dig_algorithm_switch) {
2020		initialized = 0;
2021		reset_cnt = 0;
2022	}
2023
2024	if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) {
2025		if (dm_digtable.cur_connect_state == DIG_CONNECT) {
2026			if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
2027				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
2028			else if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
2029				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
2030			else
2031				dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
2032		} else {	/* current state is disconnected */
2033			if (dm_digtable.cur_ig_value == 0)
2034				dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
2035			else
2036				dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
2037		}
2038	} else { /*  disconnected -> connected or connected -> disconnected */
2039		dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
2040		dm_digtable.pre_ig_value = 0;
2041	}
2042	/*DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue);*/
2043
2044	/* if silent reset happened, we should rewrite the values back */
2045	if (priv->reset_count != reset_cnt) {
2046		force_write = 1;
2047		reset_cnt = priv->reset_count;
2048	}
2049
2050	read_nic_byte(dev, rOFDM0_XAAGCCore1, &tmp);
2051	if (dm_digtable.pre_ig_value != tmp)
2052		force_write = 1;
2053
2054	{
2055		if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
2056			|| !initialized || force_write) {
2057			initial_gain = (u8)dm_digtable.cur_ig_value;
2058			/*DbgPrint("Write initial gain = 0x%x\n", initial_gain);*/
2059			/*  Set initial gain. */
2060			write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
2061			write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
2062			write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
2063			write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
2064			dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
2065			initialized = 1;
2066			force_write = 0;
2067		}
2068	}
2069}
2070
2071static void dm_pd_th(
2072	struct net_device *dev)
2073{
2074	struct r8192_priv *priv = ieee80211_priv(dev);
2075	static u8				initialized, force_write;
2076	static u32			reset_cnt;
2077
2078	if (dm_digtable.dig_algorithm_switch) {
2079		initialized = 0;
2080		reset_cnt = 0;
2081	}
2082
2083	if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) {
2084		if (dm_digtable.cur_connect_state == DIG_CONNECT) {
2085			if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
2086				dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
2087			else if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
2088				dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
2089			else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
2090					(dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
2091				dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
2092			else
2093				dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
2094		} else {
2095			dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
2096		}
2097	} else { /* disconnected -> connected or connected -> disconnected */
2098		dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
2099	}
2100
2101	/*  if silent reset happened, we should rewrite the values back */
2102	if (priv->reset_count != reset_cnt) {
2103		force_write = 1;
2104		reset_cnt = priv->reset_count;
2105	}
2106
2107	{
2108		if ((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
2109		    (initialized <= 3) || force_write) {
2110			/*DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState);*/
2111			if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) {
2112				/*  Lower PD_TH for OFDM. */
2113				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
2114					/*
2115					 * 2008/01/11 MH 40MHZ 90/92 register are not the same.
2116					 * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
2117					 */
2118					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
2119					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
2120						write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
2121					*/
2122				} else
2123					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
2124			} else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) {
2125				/* Higher PD_TH for OFDM. */
2126				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
2127					/*
2128					 * 2008/01/11 MH 40MHZ 90/92 register are not the same.
2129					 * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
2130					 */
2131					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
2132					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
2133						write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
2134					*/
2135				} else
2136					write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
2137			} else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) {
2138				/* Higher PD_TH for OFDM for high power state. */
2139				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
2140					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
2141					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
2142						write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
2143					*/
2144				} else
2145					write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
2146			}
2147			dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
2148			if (initialized <= 3)
2149				initialized++;
2150			force_write = 0;
2151		}
2152	}
2153}
2154
2155static	void dm_cs_ratio(
2156	struct net_device *dev)
2157{
2158	struct r8192_priv *priv = ieee80211_priv(dev);
2159	static u8				initialized, force_write;
2160	static u32			reset_cnt;
2161
2162	if (dm_digtable.dig_algorithm_switch) {
2163		initialized = 0;
2164		reset_cnt = 0;
2165	}
2166
2167	if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) {
2168		if (dm_digtable.cur_connect_state == DIG_CONNECT) {
2169			if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
2170				dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
2171			else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)
2172				dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
2173			else
2174				dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
2175		} else {
2176			dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
2177		}
2178	} else	/* disconnected -> connected or connected -> disconnected */
2179		dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
2180
2181	/* if silent reset happened, we should rewrite the values back */
2182	if (priv->reset_count != reset_cnt) {
2183		force_write = 1;
2184		reset_cnt = priv->reset_count;
2185	}
2186
2187	{
2188		if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
2189			!initialized || force_write) {
2190			/*DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState);*/
2191			if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) {
2192				/*  Lower CS ratio for CCK. */
2193				write_nic_byte(dev, 0xa0a, 0x08);
2194			} else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) {
2195				/*  Higher CS ratio for CCK. */
2196				write_nic_byte(dev, 0xa0a, 0xcd);
2197			}
2198			dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
2199			initialized = 1;
2200			force_write = 0;
2201		}
2202	}
2203}
2204
2205void dm_init_edca_turbo(struct net_device *dev)
2206{
2207	struct r8192_priv *priv = ieee80211_priv(dev);
2208
2209	priv->bcurrent_turbo_EDCA = false;
2210	priv->ieee80211->bis_any_nonbepkts = false;
2211	priv->bis_cur_rdlstate = false;
2212}	/* dm_init_edca_turbo */
2213
2214static void dm_check_edca_turbo(
2215	struct net_device *dev)
2216{
2217	struct r8192_priv *priv = ieee80211_priv(dev);
2218	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
2219	/*PSTA_QOS			pStaQos = pMgntInfo->pStaQos;*/
2220
2221	/* Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. */
2222	static unsigned long			lastTxOkCnt;
2223	static unsigned long			lastRxOkCnt;
2224	unsigned long				curTxOkCnt = 0;
2225	unsigned long				curRxOkCnt = 0;
2226
2227	/*
2228	 * Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters
2229	 * should follow the settings from QAP. By Bruce, 2007-12-07.
2230	 */
2231	if (priv->ieee80211->state != IEEE80211_LINKED)
2232		goto dm_CheckEdcaTurbo_EXIT;
2233	/* We do not turn on EDCA turbo mode for some AP that has IOT issue */
2234	if (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
2235		goto dm_CheckEdcaTurbo_EXIT;
2236
2237	/*printk("========>%s():bis_any_nonbepkts is %d\n", __func__, priv->bis_any_nonbepkts);*/
2238	/* Check the status for current condition. */
2239	if (!priv->ieee80211->bis_any_nonbepkts) {
2240		curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
2241		curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
2242		/* For RT-AP, we needs to turn it on when Rx>Tx */
2243		if (curRxOkCnt > 4*curTxOkCnt) {
2244			/*printk("%s():curRxOkCnt > 4*curTxOkCnt\n");*/
2245			if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) {
2246				write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
2247				priv->bis_cur_rdlstate = true;
2248			}
2249		} else {
2250			/*printk("%s():curRxOkCnt < 4*curTxOkCnt\n");*/
2251			if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) {
2252				write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
2253				priv->bis_cur_rdlstate = false;
2254			}
2255
2256		}
2257
2258		priv->bcurrent_turbo_EDCA = true;
2259	} else {
2260		/*
2261		 * Turn Off EDCA turbo here.
2262		 * Restore original EDCA according to the declaration of AP.
2263		 */
2264		if (priv->bcurrent_turbo_EDCA) {
2265			{
2266				u8		u1bAIFS;
2267				u32		u4bAcParam;
2268				struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2269				u8 mode = priv->ieee80211->mode;
2270
2271				/*  For Each time updating EDCA parameter, reset EDCA turbo mode status. */
2272				dm_init_edca_turbo(dev);
2273				u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
2274				u4bAcParam = (((u32)(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)|
2275					(((u32)(qos_parameters->cw_max[0])) << AC_PARAM_ECW_MAX_OFFSET)|
2276					(((u32)(qos_parameters->cw_min[0])) << AC_PARAM_ECW_MIN_OFFSET)|
2277					((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET);
2278				/*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/
2279				write_nic_dword(dev, EDCAPARA_BE,  u4bAcParam);
2280
2281				/*
2282				 * Check ACM bit.
2283				 * If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
2284				 */
2285				{
2286					/*  TODO:  Modified this part and try to set acm control in only 1 IO processing!! */
2287
2288					PACI_AIFSN	pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
2289					u8		AcmCtrl;
2290
2291					read_nic_byte(dev, AcmHwCtrl, &AcmCtrl);
2292
2293					if (pAciAifsn->f.ACM) { /*  ACM bit is 1. */
2294						AcmCtrl |= AcmHw_BeqEn;
2295					} else {	/* ACM bit is 0. */
2296						AcmCtrl &= (~AcmHw_BeqEn);
2297					}
2298
2299					RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
2300					write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
2301				}
2302			}
2303			priv->bcurrent_turbo_EDCA = false;
2304		}
2305	}
2306
2307dm_CheckEdcaTurbo_EXIT:
2308	/* Set variables for next time. */
2309	priv->ieee80211->bis_any_nonbepkts = false;
2310	lastTxOkCnt = priv->stats.txbytesunicast;
2311	lastRxOkCnt = priv->stats.rxbytesunicast;
2312}	/* dm_CheckEdcaTurbo */
2313
2314static void dm_init_ctstoself(struct net_device *dev)
2315{
2316	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
2317
2318	priv->ieee80211->bCTSToSelfEnable = true;
2319	priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
2320}
2321
2322static void dm_ctstoself(struct net_device *dev)
2323{
2324	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
2325	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
2326	static unsigned long				lastTxOkCnt;
2327	static unsigned long				lastRxOkCnt;
2328	unsigned long						curTxOkCnt = 0;
2329	unsigned long						curRxOkCnt = 0;
2330
2331	if (priv->ieee80211->bCTSToSelfEnable != true) {
2332		pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
2333		return;
2334	}
2335	/*
2336	1. Uplink
2337	2. Linksys350/Linksys300N
2338	3. <50 disable, >55 enable
2339	*/
2340
2341	if (pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) {
2342		curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
2343		curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
2344		if (curRxOkCnt > 4*curTxOkCnt) { /* downlink, disable CTS to self */
2345			pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
2346			/*DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n");*/
2347		} else { /* uplink */
2348			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
2349		}
2350
2351		lastTxOkCnt = priv->stats.txbytesunicast;
2352		lastRxOkCnt = priv->stats.rxbytesunicast;
2353	}
2354}
2355
2356/*-----------------------------------------------------------------------------
2357 * Function:	dm_check_pbc_gpio()
2358 *
2359 * Overview:	Check if PBC button is pressed.
2360 *
2361 * Input:		NONE
2362 *
2363 * Output:		NONE
2364 *
2365 * Return:		NONE
2366 *
2367 * Revised History:
2368 *	When		Who		Remark
2369 *	05/28/2008	amy	Create Version 0 porting from windows code.
2370 *
2371 *---------------------------------------------------------------------------*/
2372static	void	dm_check_pbc_gpio(struct net_device *dev)
2373{
2374	struct r8192_priv *priv = ieee80211_priv(dev);
2375	u8 tmp1byte;
2376
2377	read_nic_byte(dev, GPI, &tmp1byte);
2378	if (tmp1byte == 0xff)
2379		return;
2380
2381	if (tmp1byte&BIT6 || tmp1byte&BIT0) {
2382		/*
2383		 * Here we only set bPbcPressed to TRUE
2384		 * After trigger PBC, the variable will be set to FALSE
2385		 */
2386		RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n");
2387		priv->bpbc_pressed = true;
2388	}
2389
2390}
2391
2392/*-----------------------------------------------------------------------------
2393 * Function:	DM_RFPathCheckWorkItemCallBack()
2394 *
2395 * Overview:	Check if Current RF RX path is enabled
2396 *
2397 * Input:		NONE
2398 *
2399 * Output:		NONE
2400 *
2401 * Return:		NONE
2402 *
2403 * Revised History:
2404 *	When		Who		Remark
2405 *	01/30/2008	MHC		Create Version 0.
2406 *
2407 *---------------------------------------------------------------------------*/
2408void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
2409{
2410	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2411	struct r8192_priv *priv = container_of(dwork, struct r8192_priv, rfpath_check_wq);
2412	struct net_device *dev = priv->ieee80211->dev;
2413	/*bool bactually_set = false;*/
2414	u8 rfpath = 0, i;
2415
2416	/* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will
2417	   always be the same. We only read 0xc04 now. */
2418	read_nic_byte(dev, 0xc04, &rfpath);
2419
2420	/* Check Bit 0-3, it means if RF A-D is enabled. */
2421	for (i = 0; i < RF90_PATH_MAX; i++) {
2422		if (rfpath & (0x01<<i))
2423			priv->brfpath_rxenable[i] = true;
2424		else
2425			priv->brfpath_rxenable[i] = false;
2426	}
2427	if (!DM_RxPathSelTable.Enable)
2428		return;
2429
2430	dm_rxpath_sel_byrssi(dev);
2431}	/* DM_RFPathCheckWorkItemCallBack */
2432
2433static void dm_init_rxpath_selection(struct net_device *dev)
2434{
2435	u8 i;
2436	struct r8192_priv *priv = ieee80211_priv(dev);
2437
2438	DM_RxPathSelTable.Enable = 1;	/* default enabled */
2439	DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
2440	DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
2441	if (priv->CustomerID == RT_CID_819x_Netcore)
2442		DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
2443	else
2444		DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
2445	DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
2446	DM_RxPathSelTable.disabledRF = 0;
2447	for (i = 0; i < 4; i++) {
2448		DM_RxPathSelTable.rf_rssi[i] = 50;
2449		DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
2450		DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2451	}
2452}
2453
2454static void dm_rxpath_sel_byrssi(struct net_device *dev)
2455{
2456	struct r8192_priv *priv = ieee80211_priv(dev);
2457	u8				i, max_rssi_index = 0, min_rssi_index = 0, sec_rssi_index = 0, rf_num = 0;
2458	u8				tmp_max_rssi = 0, tmp_min_rssi = 0, tmp_sec_rssi = 0;
2459	u8				cck_default_Rx = 0x2;  /* RF-C */
2460	u8				cck_optional_Rx = 0x3; /* RF-D */
2461	long				tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0;
2462	u8				cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0, cck_rx_ver2_sec_index = 0;
2463	u8				cur_rf_rssi;
2464	long				cur_cck_pwdb;
2465	static u8			disabled_rf_cnt, cck_Rx_Path_initialized;
2466	u8				update_cck_rx_path;
2467
2468	if (priv->rf_type != RF_2T4R)
2469		return;
2470
2471	if (!cck_Rx_Path_initialized) {
2472		read_nic_byte(dev, 0xa07, &DM_RxPathSelTable.cck_Rx_path);
2473		DM_RxPathSelTable.cck_Rx_path &= 0xf;
2474		cck_Rx_Path_initialized = 1;
2475	}
2476
2477	read_nic_byte(dev, 0xc04, &DM_RxPathSelTable.disabledRF);
2478	DM_RxPathSelTable.disabledRF = ~DM_RxPathSelTable.disabledRF & 0xf;
2479
2480	if (priv->ieee80211->mode == WIRELESS_MODE_B) {
2481		DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;	/* pure B mode, fixed cck version2 */
2482		/*DbgPrint("Pure B mode, use cck rx version2\n");*/
2483	}
2484
2485	/* decide max/sec/min rssi index */
2486	for (i = 0; i < RF90_PATH_MAX; i++) {
2487		if (!DM_RxPathSelTable.DbgMode)
2488			DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
2489
2490		if (priv->brfpath_rxenable[i]) {
2491			rf_num++;
2492			cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
2493
2494			if (rf_num == 1) { /* find first enabled rf path and the rssi values */
2495				/* initialize, set all rssi index to the same one */
2496				max_rssi_index = min_rssi_index = sec_rssi_index = i;
2497				tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
2498			} else if (rf_num == 2) { /* we pick up the max index first, and let sec and min to be the same one */
2499				if (cur_rf_rssi >= tmp_max_rssi) {
2500					tmp_max_rssi = cur_rf_rssi;
2501					max_rssi_index = i;
2502				} else {
2503					tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
2504					sec_rssi_index = min_rssi_index = i;
2505				}
2506			} else {
2507				if (cur_rf_rssi > tmp_max_rssi) {
2508					tmp_sec_rssi = tmp_max_rssi;
2509					sec_rssi_index = max_rssi_index;
2510					tmp_max_rssi = cur_rf_rssi;
2511					max_rssi_index = i;
2512				} else if (cur_rf_rssi == tmp_max_rssi) {	/* let sec and min point to the different index */
2513					tmp_sec_rssi = cur_rf_rssi;
2514					sec_rssi_index = i;
2515				} else if ((cur_rf_rssi < tmp_max_rssi) && (cur_rf_rssi > tmp_sec_rssi)) {
2516					tmp_sec_rssi = cur_rf_rssi;
2517					sec_rssi_index = i;
2518				} else if (cur_rf_rssi == tmp_sec_rssi) {
2519					if (tmp_sec_rssi == tmp_min_rssi) {
2520						/* let sec and min point to the different index */
2521						tmp_sec_rssi = cur_rf_rssi;
2522						sec_rssi_index = i;
2523					} else {
2524						/* This case we don't need to set any index */
2525					}
2526				} else if ((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) {
2527					/* This case we don't need to set any index */
2528				} else if (cur_rf_rssi == tmp_min_rssi) {
2529					if (tmp_sec_rssi == tmp_min_rssi) {
2530						/* let sec and min point to the different index */
2531						tmp_min_rssi = cur_rf_rssi;
2532						min_rssi_index = i;
2533					} else {
2534						/* This case we don't need to set any index */
2535					}
2536				} else if (cur_rf_rssi < tmp_min_rssi) {
2537					tmp_min_rssi = cur_rf_rssi;
2538					min_rssi_index = i;
2539				}
2540			}
2541		}
2542	}
2543
2544	rf_num = 0;
2545	/* decide max/sec/min cck pwdb index */
2546	if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) {
2547		for (i = 0; i < RF90_PATH_MAX; i++) {
2548			if (priv->brfpath_rxenable[i]) {
2549				rf_num++;
2550				cur_cck_pwdb =  DM_RxPathSelTable.cck_pwdb_sta[i];
2551
2552				if (rf_num == 1) {	/* find first enabled rf path and the rssi values */
2553					/* initialize, set all rssi index to the same one */
2554					cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i;
2555					tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb;
2556				} else if (rf_num == 2) {	/* we pick up the max index first, and let sec and min to be the same one */
2557					if (cur_cck_pwdb >= tmp_cck_max_pwdb) {
2558						tmp_cck_max_pwdb = cur_cck_pwdb;
2559						cck_rx_ver2_max_index = i;
2560					} else {
2561						tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb;
2562						cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i;
2563					}
2564				} else {
2565					if (cur_cck_pwdb > tmp_cck_max_pwdb) {
2566						tmp_cck_sec_pwdb = tmp_cck_max_pwdb;
2567						cck_rx_ver2_sec_index = cck_rx_ver2_max_index;
2568						tmp_cck_max_pwdb = cur_cck_pwdb;
2569						cck_rx_ver2_max_index = i;
2570					} else if (cur_cck_pwdb == tmp_cck_max_pwdb) {
2571						/* let sec and min point to the different index */
2572						tmp_cck_sec_pwdb = cur_cck_pwdb;
2573						cck_rx_ver2_sec_index = i;
2574					} else if ((cur_cck_pwdb < tmp_cck_max_pwdb) && (cur_cck_pwdb > tmp_cck_sec_pwdb)) {
2575						tmp_cck_sec_pwdb = cur_cck_pwdb;
2576						cck_rx_ver2_sec_index = i;
2577					} else if (cur_cck_pwdb == tmp_cck_sec_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) {
2578						/* let sec and min point to the different index */
2579						tmp_cck_sec_pwdb = cur_cck_pwdb;
2580						cck_rx_ver2_sec_index = i;
2581						/* otherwise we don't need to set any index */
2582					} else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) {
2583						/*  This case we don't need to set any index */
2584					} else if (cur_cck_pwdb == tmp_cck_min_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) {
2585						/*  let sec and min point to the different index */
2586						tmp_cck_min_pwdb = cur_cck_pwdb;
2587						cck_rx_ver2_min_index = i;
2588						/* otherwise we don't need to set any index */
2589					} else if (cur_cck_pwdb < tmp_cck_min_pwdb) {
2590						tmp_cck_min_pwdb = cur_cck_pwdb;
2591						cck_rx_ver2_min_index = i;
2592					}
2593				}
2594
2595			}
2596		}
2597	}
2598
2599	/*
2600	 * Set CCK Rx path
2601	 * reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path.
2602	 */
2603	update_cck_rx_path = 0;
2604	if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) {
2605		cck_default_Rx = cck_rx_ver2_max_index;
2606		cck_optional_Rx = cck_rx_ver2_sec_index;
2607		if (tmp_cck_max_pwdb != -64)
2608			update_cck_rx_path = 1;
2609	}
2610
2611	if (tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) {
2612		if ((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) {
2613			/* record the enabled rssi threshold */
2614			DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
2615			/* disable the BB Rx path, OFDM */
2616			rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	/* 0xc04[3:0] */
2617			rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	/* 0xd04[3:0] */
2618			disabled_rf_cnt++;
2619		}
2620		if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) {
2621			cck_default_Rx = max_rssi_index;
2622			cck_optional_Rx = sec_rssi_index;
2623			if (tmp_max_rssi)
2624				update_cck_rx_path = 1;
2625		}
2626	}
2627
2628	if (update_cck_rx_path) {
2629		DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
2630		rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
2631	}
2632
2633	if (DM_RxPathSelTable.disabledRF) {
2634		for (i = 0; i < 4; i++) {
2635			if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) {	/* disabled rf */
2636				if (tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) {
2637					/* enable the BB Rx path */
2638					/*DbgPrint("RF-%d is enabled.\n", 0x1<<i);*/
2639					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);	/* 0xc04[3:0] */
2640					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);	/* 0xd04[3:0] */
2641					DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2642					disabled_rf_cnt--;
2643				}
2644			}
2645		}
2646	}
2647}
2648
2649/*-----------------------------------------------------------------------------
2650 * Function:	dm_check_rx_path_selection()
2651 *
2652 * Overview:	Call a workitem to check current RXRF path and Rx Path selection by RSSI.
2653 *
2654 * Input:		NONE
2655 *
2656 * Output:		NONE
2657 *
2658 * Return:		NONE
2659 *
2660 * Revised History:
2661 *	When		Who		Remark
2662 *	05/28/2008	amy		Create Version 0 porting from windows code.
2663 *
2664 *---------------------------------------------------------------------------*/
2665static void dm_check_rx_path_selection(struct net_device *dev)
2666{
2667	struct r8192_priv *priv = ieee80211_priv(dev);
2668
2669	queue_delayed_work(priv->priv_wq, &priv->rfpath_check_wq, 0);
2670}	/* dm_CheckRxRFPath */
2671
2672static void dm_init_fsync(struct net_device *dev)
2673{
2674	struct r8192_priv *priv = ieee80211_priv(dev);
2675
2676	priv->ieee80211->fsync_time_interval = 500;
2677	priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
2678	priv->ieee80211->fsync_rssi_threshold = 30;
2679	priv->ieee80211->bfsync_enable = false;
2680	priv->ieee80211->fsync_multiple_timeinterval = 3;
2681	priv->ieee80211->fsync_firstdiff_ratethreshold = 100;
2682	priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
2683	priv->ieee80211->fsync_state = Default_Fsync;
2684	priv->framesyncMonitor = 1;	/* current default 0xc38 monitor on */
2685	setup_timer(&priv->fsync_timer, dm_fsync_timer_callback,
2686		    (unsigned long)dev);
2687}
2688
2689static void dm_deInit_fsync(struct net_device *dev)
2690{
2691	struct r8192_priv *priv = ieee80211_priv(dev);
2692
2693	del_timer_sync(&priv->fsync_timer);
2694}
2695
2696void dm_fsync_timer_callback(unsigned long data)
2697{
2698	struct net_device *dev = (struct net_device *)data;
2699	struct r8192_priv *priv = ieee80211_priv((struct net_device *)data);
2700	u32 rate_index, rate_count = 0, rate_count_diff = 0;
2701	bool		bSwitchFromCountDiff = false;
2702	bool		bDoubleTimeInterval = false;
2703
2704	if (priv->ieee80211->state == IEEE80211_LINKED &&
2705		priv->ieee80211->bfsync_enable &&
2706		(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) {
2707		/* Count rate 54, MCS [7], [12, 13, 14, 15] */
2708		u32 rate_bitmap;
2709
2710		for (rate_index = 0; rate_index <= 27; rate_index++) {
2711			rate_bitmap  = 1 << rate_index;
2712			if (priv->ieee80211->fsync_rate_bitmap &  rate_bitmap)
2713				rate_count += priv->stats.received_rate_histogram[1][rate_index];
2714		}
2715
2716		if (rate_count < priv->rate_record)
2717			rate_count_diff = 0xffffffff - rate_count + priv->rate_record;
2718		else
2719			rate_count_diff = rate_count - priv->rate_record;
2720		if (rate_count_diff < priv->rateCountDiffRecord) {
2721			u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
2722			/* Continue count */
2723			if (DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold)
2724				priv->ContinueDiffCount++;
2725			else
2726				priv->ContinueDiffCount = 0;
2727
2728			/* Continue count over */
2729			if (priv->ContinueDiffCount >= 2) {
2730				bSwitchFromCountDiff = true;
2731				priv->ContinueDiffCount = 0;
2732			}
2733		} else {
2734			/* Stop the continued count */
2735			priv->ContinueDiffCount = 0;
2736		}
2737
2738		/* If Count diff <= FsyncRateCountThreshold */
2739		if (rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) {
2740			bSwitchFromCountDiff = true;
2741			priv->ContinueDiffCount = 0;
2742		}
2743		priv->rate_record = rate_count;
2744		priv->rateCountDiffRecord = rate_count_diff;
2745		RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync);
2746		/* if we never receive those mcs rate and rssi > 30 % then switch fsyn */
2747		if (priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) {
2748			bDoubleTimeInterval = true;
2749			priv->bswitch_fsync = !priv->bswitch_fsync;
2750			if (priv->bswitch_fsync) {
2751				write_nic_byte(dev, 0xC36, 0x1c);
2752				write_nic_byte(dev, 0xC3e, 0x90);
2753			} else {
2754				write_nic_byte(dev, 0xC36, 0x5c);
2755				write_nic_byte(dev, 0xC3e, 0x96);
2756			}
2757		} else if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) {
2758			if (priv->bswitch_fsync) {
2759				priv->bswitch_fsync  = false;
2760				write_nic_byte(dev, 0xC36, 0x5c);
2761				write_nic_byte(dev, 0xC3e, 0x96);
2762			}
2763		}
2764		if (bDoubleTimeInterval) {
2765			if (timer_pending(&priv->fsync_timer))
2766				del_timer_sync(&priv->fsync_timer);
2767			priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval);
2768			add_timer(&priv->fsync_timer);
2769		} else {
2770			if (timer_pending(&priv->fsync_timer))
2771				del_timer_sync(&priv->fsync_timer);
2772			priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2773			add_timer(&priv->fsync_timer);
2774		}
2775	} else {
2776		/* Let Register return to default value; */
2777		if (priv->bswitch_fsync) {
2778			priv->bswitch_fsync  = false;
2779			write_nic_byte(dev, 0xC36, 0x5c);
2780			write_nic_byte(dev, 0xC3e, 0x96);
2781		}
2782		priv->ContinueDiffCount = 0;
2783		write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
2784	}
2785	RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
2786	RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync);
2787}
2788
2789static void dm_StartHWFsync(struct net_device *dev)
2790{
2791	RT_TRACE(COMP_HALDM, "%s\n", __func__);
2792	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
2793	write_nic_byte(dev, 0xc3b, 0x41);
2794}
2795
2796static void dm_EndSWFsync(struct net_device *dev)
2797{
2798	struct r8192_priv *priv = ieee80211_priv(dev);
2799
2800	RT_TRACE(COMP_HALDM, "%s\n", __func__);
2801	del_timer_sync(&(priv->fsync_timer));
2802
2803	/* Let Register return to default value; */
2804	if (priv->bswitch_fsync) {
2805		priv->bswitch_fsync  = false;
2806
2807		write_nic_byte(dev, 0xC36, 0x5c);
2808
2809		write_nic_byte(dev, 0xC3e, 0x96);
2810	}
2811
2812	priv->ContinueDiffCount = 0;
2813	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
2814
2815}
2816
2817static void dm_StartSWFsync(struct net_device *dev)
2818{
2819	struct r8192_priv *priv = ieee80211_priv(dev);
2820	u32			rateIndex;
2821	u32			rateBitmap;
2822
2823	RT_TRACE(COMP_HALDM, "%s\n", __func__);
2824	/* Initial rate record to zero, start to record. */
2825	priv->rate_record = 0;
2826	/* Initialize continue diff count to zero, start to record. */
2827	priv->ContinueDiffCount = 0;
2828	priv->rateCountDiffRecord = 0;
2829	priv->bswitch_fsync  = false;
2830
2831	if (priv->ieee80211->mode == WIRELESS_MODE_N_24G) {
2832		priv->ieee80211->fsync_firstdiff_ratethreshold = 600;
2833		priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff;
2834	} else {
2835		priv->ieee80211->fsync_firstdiff_ratethreshold = 200;
2836		priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
2837	}
2838	for (rateIndex = 0; rateIndex <= 27; rateIndex++) {
2839		rateBitmap = 1 << rateIndex;
2840		if (priv->ieee80211->fsync_rate_bitmap &  rateBitmap)
2841			priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
2842	}
2843	if (timer_pending(&priv->fsync_timer))
2844		del_timer_sync(&priv->fsync_timer);
2845	priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2846	add_timer(&priv->fsync_timer);
2847
2848	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
2849
2850}
2851
2852static void dm_EndHWFsync(struct net_device *dev)
2853{
2854	RT_TRACE(COMP_HALDM, "%s\n", __func__);
2855	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
2856	write_nic_byte(dev, 0xc3b, 0x49);
2857
2858}
2859
2860void dm_check_fsync(struct net_device *dev)
2861{
2862#define	RegC38_Default				0
2863#define	RegC38_NonFsync_Other_AP		1
2864#define	RegC38_Fsync_AP_BCM			2
2865	struct r8192_priv *priv = ieee80211_priv(dev);
2866	/*u32			framesyncC34;*/
2867	static u8		reg_c38_State = RegC38_Default;
2868	static u32	reset_cnt;
2869
2870	RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval);
2871	RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold);
2872
2873	if (priv->ieee80211->state == IEEE80211_LINKED &&
2874		(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) {
2875		if (priv->ieee80211->bfsync_enable == 0) {
2876			switch (priv->ieee80211->fsync_state) {
2877			case Default_Fsync:
2878				dm_StartHWFsync(dev);
2879				priv->ieee80211->fsync_state = HW_Fsync;
2880				break;
2881			case SW_Fsync:
2882				dm_EndSWFsync(dev);
2883				dm_StartHWFsync(dev);
2884				priv->ieee80211->fsync_state = HW_Fsync;
2885				break;
2886			case HW_Fsync:
2887			default:
2888				break;
2889			}
2890		} else {
2891			switch (priv->ieee80211->fsync_state) {
2892			case Default_Fsync:
2893				dm_StartSWFsync(dev);
2894				priv->ieee80211->fsync_state = SW_Fsync;
2895				break;
2896			case HW_Fsync:
2897				dm_EndHWFsync(dev);
2898				dm_StartSWFsync(dev);
2899				priv->ieee80211->fsync_state = SW_Fsync;
2900				break;
2901			case SW_Fsync:
2902			default:
2903				break;
2904			}
2905		}
2906		if (priv->framesyncMonitor) {
2907			if (reg_c38_State != RegC38_Fsync_AP_BCM) {
2908				/* For broadcom AP we write different default value */
2909				write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
2910
2911				reg_c38_State = RegC38_Fsync_AP_BCM;
2912			}
2913		}
2914	} else {
2915		switch (priv->ieee80211->fsync_state) {
2916		case HW_Fsync:
2917			dm_EndHWFsync(dev);
2918			priv->ieee80211->fsync_state = Default_Fsync;
2919			break;
2920		case SW_Fsync:
2921			dm_EndSWFsync(dev);
2922			priv->ieee80211->fsync_state = Default_Fsync;
2923			break;
2924		case Default_Fsync:
2925		default:
2926			break;
2927		}
2928
2929		if (priv->framesyncMonitor) {
2930			if (priv->ieee80211->state == IEEE80211_LINKED) {
2931				if (priv->undecorated_smoothed_pwdb <= RegC38_TH) {
2932					if (reg_c38_State != RegC38_NonFsync_Other_AP) {
2933						write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
2934
2935						reg_c38_State = RegC38_NonFsync_Other_AP;
2936					}
2937				} else if (priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) {
2938					if (reg_c38_State) {
2939						write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
2940						reg_c38_State = RegC38_Default;
2941						/*DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x\n", pHalData->framesync);*/
2942					}
2943				}
2944			} else {
2945				if (reg_c38_State) {
2946					write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
2947					reg_c38_State = RegC38_Default;
2948					/*DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x\n", pHalData->framesync);*/
2949				}
2950			}
2951		}
2952	}
2953	if (priv->framesyncMonitor) {
2954		if (priv->reset_count != reset_cnt) { /* After silent reset, the reg_c38_State will be returned to default value */
2955			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
2956			reg_c38_State = RegC38_Default;
2957			reset_cnt = priv->reset_count;
2958			/*DbgPrint("reg_c38_State = 0 for silent reset.\n");*/
2959		}
2960	} else {
2961		if (reg_c38_State) {
2962			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
2963			reg_c38_State = RegC38_Default;
2964			/*DbgPrint("framesync no monitor, write 0xc38 = 0x%x\n", pHalData->framesync);*/
2965		}
2966	}
2967}
2968
2969/*-----------------------------------------------------------------------------
2970 * Function:	dm_shadow_init()
2971 *
2972 * Overview:	Store all NIC MAC/BB register content.
2973 *
2974 * Input:		NONE
2975 *
2976 * Output:		NONE
2977 *
2978 * Return:		NONE
2979 *
2980 * Revised History:
2981 *	When		Who		Remark
2982 *	05/29/2008	amy		Create Version 0 porting from windows code.
2983 *
2984 *---------------------------------------------------------------------------*/
2985void dm_shadow_init(struct net_device *dev)
2986{
2987	u8	page;
2988	u16	offset;
2989
2990	for (page = 0; page < 5; page++)
2991		for (offset = 0; offset < 256; offset++) {
2992			read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]);
2993			/*DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]);*/
2994		}
2995
2996	for (page = 8; page < 11; page++)
2997		for (offset = 0; offset < 256; offset++)
2998			read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]);
2999
3000	for (page = 12; page < 15; page++)
3001		for (offset = 0; offset < 256; offset++)
3002			read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]);
3003
3004}   /* dm_shadow_init */
3005
3006/*---------------------------Define function prototype------------------------*/
3007/*-----------------------------------------------------------------------------
3008 * Function:	DM_DynamicTxPower()
3009 *
3010 * Overview:	Detect Signal strength to control TX Registry
3011			Tx Power Control For Near/Far Range
3012 *
3013 * Input:		NONE
3014 *
3015 * Output:		NONE
3016 *
3017 * Return:		NONE
3018 *
3019 * Revised History:
3020 *	When		Who		Remark
3021 *	03/06/2008	Jacken	Create Version 0.
3022 *
3023 *---------------------------------------------------------------------------*/
3024static void dm_init_dynamic_txpower(struct net_device *dev)
3025{
3026	struct r8192_priv *priv = ieee80211_priv(dev);
3027
3028	/* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */
3029	priv->ieee80211->bdynamic_txpower_enable = true;    /* Default to enable Tx Power Control */
3030	priv->bLastDTPFlag_High = false;
3031	priv->bLastDTPFlag_Low = false;
3032	priv->bDynamicTxHighPower = false;
3033	priv->bDynamicTxLowPower = false;
3034}
3035
3036static void dm_dynamic_txpower(struct net_device *dev)
3037{
3038	struct r8192_priv *priv = ieee80211_priv(dev);
3039	unsigned int txhipower_threshhold = 0;
3040	unsigned int txlowpower_threshold = 0;
3041
3042	if (priv->ieee80211->bdynamic_txpower_enable != true) {
3043		priv->bDynamicTxHighPower = false;
3044		priv->bDynamicTxLowPower = false;
3045		return;
3046	}
3047	/*printk("priv->ieee80211->current_network.unknown_cap_exist is %d , priv->ieee80211->current_network.broadcom_cap_exist is %d\n", priv->ieee80211->current_network.unknown_cap_exist, priv->ieee80211->current_network.broadcom_cap_exist);*/
3048	if ((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)) {
3049		txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
3050		txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
3051	} else {
3052		txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
3053		txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
3054	}
3055
3056	/*printk("=======>%s(): txhipower_threshhold is %d, txlowpower_threshold is %d\n", __func__, txhipower_threshhold, txlowpower_threshold);*/
3057	RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n", priv->undecorated_smoothed_pwdb);
3058
3059	if (priv->ieee80211->state == IEEE80211_LINKED) {
3060		if (priv->undecorated_smoothed_pwdb >= txhipower_threshhold) {
3061			priv->bDynamicTxHighPower = true;
3062			priv->bDynamicTxLowPower = false;
3063		} else {
3064			/* high power state check */
3065			if (priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true)
3066				priv->bDynamicTxHighPower = false;
3067
3068			/* low power state check */
3069			if (priv->undecorated_smoothed_pwdb < 35)
3070				priv->bDynamicTxLowPower = true;
3071			else if (priv->undecorated_smoothed_pwdb >= 40)
3072				priv->bDynamicTxLowPower = false;
3073		}
3074	} else {
3075		/*pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;*/
3076		priv->bDynamicTxHighPower = false;
3077		priv->bDynamicTxLowPower = false;
3078	}
3079
3080	if ((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) ||
3081		(priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) {
3082		RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190()  channel = %d\n", priv->ieee80211->current_network.channel);
3083
3084#if  defined(RTL8190P) || defined(RTL8192E)
3085		SetTxPowerLevel8190(Adapter, pHalData->CurrentChannel);
3086#endif
3087
3088		rtl8192_phy_setTxPower(dev, priv->ieee80211->current_network.channel);
3089		/*pHalData->bStartTxCtrlByTPCNFR = FALSE;    Clear th flag of Set TX Power from Sitesurvey*/
3090	}
3091	priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
3092	priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
3093
3094}	/* dm_dynamic_txpower */
3095
3096/* added by vivi, for read tx rate and retrycount */
3097static void dm_check_txrateandretrycount(struct net_device *dev)
3098{
3099	struct r8192_priv *priv = ieee80211_priv(dev);
3100	struct ieee80211_device *ieee = priv->ieee80211;
3101	/* for 11n tx rate */
3102	/*priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);*/
3103	read_nic_byte(dev, Current_Tx_Rate_Reg, &ieee->softmac_stats.CurrentShowTxate);
3104	/*printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate);*/
3105	/* for initial tx rate */
3106	/*priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg);*/
3107	read_nic_byte(dev, Initial_Tx_Rate_Reg, &ieee->softmac_stats.last_packet_rate);
3108	/* for tx tx retry count */
3109	/*priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);*/
3110	read_nic_dword(dev, Tx_Retry_Count_Reg, &ieee->softmac_stats.txretrycount);
3111}
3112
3113static void dm_send_rssi_tofw(struct net_device *dev)
3114{
3115	struct r8192_priv *priv = ieee80211_priv(dev);
3116
3117	/*
3118	 * If we test chariot, we should stop the TX command ?
3119	 * Because 92E will always silent reset when we send tx command. We use register
3120	 * 0x1e0(byte) to notify driver.
3121	 */
3122	write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
3123}
3124
3125/*---------------------------Define function prototype------------------------*/
3126