1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 
8 #include "odm_precomp.h"
9 
10 /*  This function is for inband noise test utility only */
11 /*  To obtain the inband noise level(dbm), do the following. */
12 /*  1. disable DIG and Power Saving */
13 /*  2. Set initial gain = 0x1a */
14 /*  3. Stop updating idle time pwer report (for driver read) */
15 /* - 0x80c[25] */
16 
17 #define Valid_Min				-35
18 #define Valid_Max			10
19 #define ValidCnt				5
20 
odm_InbandNoise_Monitor_NSeries(struct dm_odm_t * pDM_Odm,u8 bPauseDIG,u8 IGIValue,u32 max_time)21 static s16 odm_InbandNoise_Monitor_NSeries(
22 	struct dm_odm_t *pDM_Odm,
23 	u8 bPauseDIG,
24 	u8 IGIValue,
25 	u32 max_time
26 )
27 {
28 	u32 tmp4b;
29 	u8 max_rf_path = 0, rf_path;
30 	u8 reg_c50, reg_c58, valid_done = 0;
31 	struct noise_level noise_data;
32 	u32 start  = 0, func_start = 0, func_end = 0;
33 
34 	func_start = jiffies;
35 	pDM_Odm->noise_level.noise_all = 0;
36 
37 	if ((pDM_Odm->RFType == ODM_1T2R) || (pDM_Odm->RFType == ODM_2T2R))
38 		max_rf_path = 2;
39 	else
40 		max_rf_path = 1;
41 
42 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() ==>\n"));
43 
44 	memset(&noise_data, 0, sizeof(struct noise_level));
45 
46 	/*  */
47 	/*  Step 1. Disable DIG && Set initial gain. */
48 	/*  */
49 
50 	if (bPauseDIG)
51 		odm_PauseDIG(pDM_Odm, ODM_PAUSE_DIG, IGIValue);
52 	/*  */
53 	/*  Step 2. Disable all power save for read registers */
54 	/*  */
55 	/* dcmd_DebugControlPowerSave(padapter, PSDisable); */
56 
57 	/*  */
58 	/*  Step 3. Get noise power level */
59 	/*  */
60 	start = jiffies;
61 	while (1) {
62 
63 		/* Stop updating idle time pwer report (for driver read) */
64 		PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_TxGainStage, BIT25, 1);
65 
66 		/* Read Noise Floor Report */
67 		tmp4b = PHY_QueryBBReg(pDM_Odm->Adapter, 0x8f8, bMaskDWord);
68 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Noise Floor Report (0x8f8) = 0x%08x\n", tmp4b));
69 
70 		/* PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0, TestInitialGain); */
71 		/* if (max_rf_path == 2) */
72 		/* PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBAGCCore1, bMaskByte0, TestInitialGain); */
73 
74 		/* update idle time pwer report per 5us */
75 		PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_TxGainStage, BIT25, 0);
76 
77 		noise_data.value[ODM_RF_PATH_A] = (u8)(tmp4b&0xff);
78 		noise_data.value[ODM_RF_PATH_B]  = (u8)((tmp4b&0xff00)>>8);
79 
80 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("value_a = 0x%x(%d), value_b = 0x%x(%d)\n",
81 			noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_B], noise_data.value[ODM_RF_PATH_B]));
82 
83 		for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
84 			noise_data.sval[rf_path] = (s8)noise_data.value[rf_path];
85 			noise_data.sval[rf_path] /= 2;
86 		}
87 
88 
89 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("sval_a = %d, sval_b = %d\n",
90 			noise_data.sval[ODM_RF_PATH_A], noise_data.sval[ODM_RF_PATH_B]));
91 		/* mdelay(10); */
92 		/* msleep(10); */
93 
94 		for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
95 			if ((noise_data.valid_cnt[rf_path] < ValidCnt) && (noise_data.sval[rf_path] < Valid_Max && noise_data.sval[rf_path] >= Valid_Min)) {
96 				noise_data.valid_cnt[rf_path]++;
97 				noise_data.sum[rf_path] += noise_data.sval[rf_path];
98 				ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RF_Path:%d Valid sval = %d\n", rf_path, noise_data.sval[rf_path]));
99 				ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Sum of sval = %d,\n", noise_data.sum[rf_path]));
100 				if (noise_data.valid_cnt[rf_path] == ValidCnt) {
101 					valid_done++;
102 					ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("After divided, RF_Path:%d , sum = %d\n", rf_path, noise_data.sum[rf_path]));
103 				}
104 
105 			}
106 
107 		}
108 
109 		/* printk("####### valid_done:%d #############\n", valid_done); */
110 		if ((valid_done == max_rf_path) || (jiffies_to_msecs(jiffies - start) > max_time)) {
111 			for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
112 				/* printk("%s PATH_%d - sum = %d, valid_cnt = %d\n", __func__, rf_path, noise_data.sum[rf_path], noise_data.valid_cnt[rf_path]); */
113 				if (noise_data.valid_cnt[rf_path])
114 					noise_data.sum[rf_path] /= noise_data.valid_cnt[rf_path];
115 				else
116 					noise_data.sum[rf_path]  = 0;
117 			}
118 			break;
119 		}
120 	}
121 	reg_c50 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0);
122 	reg_c50 &= ~BIT7;
123 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", rOFDM0_XAAGCCore1, reg_c50, reg_c50));
124 	pDM_Odm->noise_level.noise[ODM_RF_PATH_A] = -110 + reg_c50 + noise_data.sum[ODM_RF_PATH_A];
125 	pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_A];
126 
127 	if (max_rf_path == 2) {
128 		reg_c58 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBAGCCore1, bMaskByte0);
129 		reg_c58 &= ~BIT7;
130 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", rOFDM0_XBAGCCore1, reg_c58, reg_c58));
131 		pDM_Odm->noise_level.noise[ODM_RF_PATH_B] = -110 + reg_c58 + noise_data.sum[ODM_RF_PATH_B];
132 		pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_B];
133 	}
134 	pDM_Odm->noise_level.noise_all /= max_rf_path;
135 
136 	ODM_RT_TRACE(
137 		pDM_Odm,
138 		ODM_COMP_COMMON,
139 		ODM_DBG_LOUD,
140 		(
141 			"noise_a = %d, noise_b = %d\n",
142 			pDM_Odm->noise_level.noise[ODM_RF_PATH_A],
143 			pDM_Odm->noise_level.noise[ODM_RF_PATH_B]
144 		)
145 	);
146 
147 	/*  */
148 	/*  Step 4. Recover the Dig */
149 	/*  */
150 	if (bPauseDIG)
151 		odm_PauseDIG(pDM_Odm, ODM_RESUME_DIG, IGIValue);
152 
153 	func_end = jiffies_to_msecs(jiffies - func_start);
154 	/* printk("%s noise_a = %d, noise_b = %d noise_all:%d (%d ms)\n", __func__, */
155 	/* pDM_Odm->noise_level.noise[ODM_RF_PATH_A], */
156 	/* pDM_Odm->noise_level.noise[ODM_RF_PATH_B], */
157 	/* pDM_Odm->noise_level.noise_all, func_end); */
158 
159 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() <==\n"));
160 	return pDM_Odm->noise_level.noise_all;
161 
162 }
163 
ODM_InbandNoise_Monitor(void * pDM_VOID,u8 bPauseDIG,u8 IGIValue,u32 max_time)164 s16 ODM_InbandNoise_Monitor(void *pDM_VOID, u8 bPauseDIG, u8 IGIValue, u32 max_time)
165 {
166 	return odm_InbandNoise_Monitor_NSeries(pDM_VOID, bPauseDIG, IGIValue, max_time);
167 }
168