• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 
26 /*@************************************************************
27  * include files
28  ***************************************************************/
29 
30 #include "mp_precomp.h"
31 #include "phydm_precomp.h"
32 #ifdef CONFIG_DIRECTIONAL_BF
33 #ifdef PHYDM_COMPILE_IC_2SS
phydm_iq_gen_en(void * dm_void)34 void phydm_iq_gen_en(void *dm_void)
35 {
36 	struct dm_struct *dm = (struct dm_struct *)dm_void;
37 	enum rf_path i = RF_PATH_A;
38 	enum rf_path path = RF_PATH_A;
39 
40 	#if (ODM_IC_11AC_SERIES_SUPPORT)
41 	if (dm->support_ic_type & ODM_RTL8822B) {
42 		for (i = RF_PATH_A; i <= RF_PATH_B; i++) {
43 			/*RF mode table write enable*/
44 			odm_set_rf_reg(dm, path, RF_0xef, BIT(19), 0x1);
45 			/*Select RX mode*/
46 			odm_set_rf_reg(dm, path, RF_0x33, 0xF, 3);
47 			/*Set Table data*/
48 			odm_set_rf_reg(dm, path, RF_0x3e, 0xfffff, 0x00036);
49 			/*Set Table data*/
50 			odm_set_rf_reg(dm, path, RF_0x3f, 0xfffff, 0x5AFCE);
51 			/*RF mode table write disable*/
52 			odm_set_rf_reg(dm, path, RF_0xef, BIT(19), 0x0);
53 		}
54 	}
55 	#endif
56 
57 	#if (ODM_IC_11N_SERIES_SUPPORT)
58 	if (dm->support_ic_type & ODM_RTL8192F) {
59 		/*RF mode table write enable*/
60 		odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, 0x80000, 0x1);
61 		odm_set_rf_reg(dm, RF_PATH_B, RF_0xef, 0x80000, 0x1);
62 		/* Path A */
63 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x30, 0xfffff, 0x08000);
64 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x31, 0xfffff, 0x0005f);
65 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x32, 0xfffff, 0x01042);
66 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x30, 0xfffff, 0x18000);
67 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x31, 0xfffff, 0x0004f);
68 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x32, 0xfffff, 0x71fc2);
69 		/* Path B */
70 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x30, 0xfffff, 0x08000);
71 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x31, 0xfffff, 0x00050);
72 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x32, 0xfffff, 0x01042);
73 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x30, 0xfffff, 0x18000);
74 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x31, 0xfffff, 0x00040);
75 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x32, 0xfffff, 0x71fc2);
76 		/*RF mode table write disable*/
77 		odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, 0x80000, 0x0);
78 		odm_set_rf_reg(dm, RF_PATH_B, RF_0xef, 0x80000, 0x0);
79 	}
80 	#endif
81 
82 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
83 	if (dm->support_ic_type & ODM_RTL8197G) {
84 		/*RF mode table write enable*/
85 		/* Path A */
86 		odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, 0x80000, 0x1);
87 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x30, 0xfffff, 0x18000);
88 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x31, 0xfffff, 0x000cf);
89 		odm_set_rf_reg(dm, RF_PATH_A, RF_0x32, 0xfffff, 0x71fc2);
90 		odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, 0x80000, 0x0);
91 
92 		/* Path B */
93 		odm_set_rf_reg(dm, RF_PATH_B, RF_0xef, 0x80000, 0x1);
94 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x30, 0xfffff, 0x18000);
95 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x31, 0xfffff, 0x000cf);
96 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x32, 0xfffff, 0x71fc2);
97 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x30, 0xfffff, 0x08000);
98 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x31, 0xfffff, 0x000ef);
99 		odm_set_rf_reg(dm, RF_PATH_B, RF_0x32, 0xfffff, 0x01042);
100 		odm_set_rf_reg(dm, RF_PATH_B, RF_0xef, 0x80000, 0x0);
101 	}
102 	#endif
103 
104 }
105 
phydm_dis_cdd(void * dm_void)106 void phydm_dis_cdd(void *dm_void)
107 {
108 	struct dm_struct *dm = (struct dm_struct *)dm_void;
109 
110 	#if (ODM_IC_11AC_SERIES_SUPPORT)
111 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
112 		odm_set_bb_reg(dm, R_0x808, 0x3ffff00, 0);
113 		odm_set_bb_reg(dm, R_0x9ac, 0x1fff, 0);
114 		odm_set_bb_reg(dm, R_0x9ac, BIT(13), 1);
115 	}
116 	#endif
117 	#if (ODM_IC_11N_SERIES_SUPPORT)
118 	if (dm->support_ic_type & ODM_IC_11N_SERIES) {
119 		odm_set_bb_reg(dm, R_0x90c, 0xffffffff, 0x83321333);
120 		/* Set Tx delay setting for CCK pathA,B*/
121 		odm_set_bb_reg(dm, R_0xa2c, 0xf0000000, 0);
122 		/*Enable Tx CDD for HT part when spatial expansion is applied*/
123 		odm_set_bb_reg(dm, R_0xd00, BIT(8), 0);
124 		/* Tx CDD for Legacy*/
125 		odm_set_bb_reg(dm, R_0xd04, 0xf0000, 0);
126 		/* Tx CDD for non-HT*/
127 		odm_set_bb_reg(dm, R_0xd0c, 0x3c0, 0);
128 		/* Tx CDD for HT SS1*/
129 		odm_set_bb_reg(dm, R_0xd0c, 0xf8000, 0);
130 	}
131 	#endif
132 	#ifdef PHYDM_IC_JGR3_SERIES_SUPPORT
133 	if (dm->support_ic_type & ODM_IC_JGR3_SERIES) {
134 		/* Tx CDD for Legacy Preamble*/
135 		odm_set_bb_reg(dm, R_0x1cc0, 0xffffffff, 0x24800000);
136 		/* Tx CDD for HT Preamble*/
137 		odm_set_bb_reg(dm, R_0x1cb0, 0xffffffff, 0);
138 	}
139 	#endif
140 }
141 
phydm_pathb_q_matrix_rotate_en(void * dm_void)142 void phydm_pathb_q_matrix_rotate_en(void *dm_void)
143 {
144 	struct dm_struct *dm = (struct dm_struct *)dm_void;
145 
146 	phydm_iq_gen_en(dm);
147 
148 	/*#ifdef PHYDM_COMMON_API_SUPPORT*/
149 	/*path selection is controlled by driver*/
150 	#if 0
151 	if (!phydm_api_trx_mode(dm, BB_PATH_AB, BB_PATH_AB, BB_PATH_AB))
152 		return;
153 	#endif
154 
155 	phydm_dis_cdd(dm);
156 	phydm_pathb_q_matrix_rotate(dm, 0);
157 
158 	#if (ODM_IC_11AC_SERIES_SUPPORT)
159 	if (dm->support_ic_type & ODM_IC_11AC_SERIES) {
160 		/*Set Q matrix r_v11 =1*/
161 		odm_set_bb_reg(dm, R_0x195c, MASKDWORD, 0x40000);
162 		/*Set Q matrix enable*/
163 		odm_set_bb_reg(dm, R_0x191c, BIT(7), 1);
164 	}
165 	#endif
166 }
167 
phydm_pathb_q_matrix_rotate(void * dm_void,u16 idx)168 void phydm_pathb_q_matrix_rotate(void *dm_void, u16 idx)
169 {
170 	struct dm_struct *dm = (struct dm_struct *)dm_void;
171 	#if (ODM_IC_11AC_SERIES_SUPPORT)
172 	u32 phase_table_0[ANGLE_NUM] = {0x40000, 0x376CF, 0x20000, 0x00000,
173 					0xFE0000, 0xFC8930, 0xFC0000,
174 					0xFC8930, 0xFDFFFF, 0x000000,
175 					0x020000, 0x0376CF};
176 	u32 phase_table_1[ANGLE_NUM] = {0x00000, 0x1FFFF, 0x376CF, 0x40000,
177 					0x0376CF, 0x01FFFF, 0x000000,
178 					0xFDFFFF, 0xFC8930, 0xFC0000,
179 					0xFC8930, 0xFDFFFF};
180 	#endif
181 	#if (ODM_IC_11N_SERIES_SUPPORT)
182 	u32 phase_table_n_0[ANGLE_NUM] = {0x00, 0x0B, 0x02, 0x00, 0x02, 0x02,
183 					  0x04, 0x02, 0x0D, 0x09, 0x04, 0x0B};
184 	u32 phase_table_n_1[ANGLE_NUM] = {0x40000100, 0x377F00DD, 0x201D8880,
185 					  0x00000000, 0xE01D8B80, 0xC8BF0322,
186 					  0xC000FF00, 0xC8BF0322, 0xDFE2777F,
187 					  0xFFC003FF, 0x20227480, 0x377F00DD};
188 	u32 phase_table_n_2[ANGLE_NUM] = {0x00, 0x1E, 0x3C, 0x4C, 0x3C, 0x1E,
189 					  0x0F, 0xD2, 0xC3, 0xC4, 0xC3, 0xD2};
190 	#endif
191 	if (idx >= ANGLE_NUM) {
192 		pr_debug("[%s]warning Phase Set Error: %d\n", __func__, idx);
193 		return;
194 	}
195 
196 	switch (dm->ic_ip_series) {
197 	#if (ODM_IC_11AC_SERIES_SUPPORT == 1)
198 	case PHYDM_IC_AC:
199 		/*Set Q matrix r_v21*/
200 		odm_set_bb_reg(dm, R_0x1954, 0xffffff, phase_table_0[idx]);
201 		odm_set_bb_reg(dm, R_0x1950, 0xffffff, phase_table_1[idx]);
202 		break;
203 	#endif
204 
205 	#if (ODM_IC_11N_SERIES_SUPPORT == 1)
206 	case PHYDM_IC_N:
207 		/*Set Q matrix r_v21*/
208 		odm_set_bb_reg(dm, R_0xc4c, 0xff000000, phase_table_n_0[idx]);
209 		odm_set_bb_reg(dm, R_0xc88, 0xffffffff, phase_table_n_1[idx]);
210 		odm_set_bb_reg(dm, R_0xc9c, 0xff000000, phase_table_n_2[idx]);
211 		break;
212 	#endif
213 
214 	default:
215 		break;
216 	}
217 }
218 
219 /*Before use this API, Fill correct Tx Des. and Disable STBC in advance*/
phydm_set_direct_bfer(void * dm_void,u16 phs_idx,u8 su_idx)220 void phydm_set_direct_bfer(void *dm_void, u16 phs_idx, u8 su_idx)
221 {
222 	struct dm_struct *dm = (struct dm_struct *)dm_void;
223 #if (RTL8822B_SUPPORT)
224 	if (dm->support_ic_type & ODM_RTL8822B) {
225 #if 0
226 		u8 phi[13] = {0x0, 0x5, 0xa, 0xf, 0x15, 0x1a, 0x1f, 0x25,
227 			      0x2a, 0x2f, 0x35, 0x3a, 0x0};
228 		u8 psi[13] = {0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
229 			      0x7, 0x7, 0x7, 0x7};
230 		u16 psiphi[13] = {0x1c0, 0x1c5, 0x1ca, 0x1cf, 0x1d5, 0x1da,
231 				  0x1df, 0x1e5, 0x1ea, 0x1ef, 0x1f5, 0x1fa,
232 				  0x1c0}; //{Psi_4bit, Phi_6bit} of 0~360
233 #endif
234 		u16 ns[3] = {52, 108, 234}; //20/40/80 MHz subcarrier number
235 		u16 psiphi[13] = {0x1c0, 0x1c5, 0x1ca, 0x1cf, 0x1d5, 0x1da,
236 				  0x1df, 0x1e5, 0x1ea, 0x1ef, 0x1f5, 0x1fa,
237 				  0x1c0}; //{Psi_4bit, Phi_6bit} of 0~360
238 		u16 psiphiR;
239 		u8 i;
240 		u8 snr = 0x12; // for 1SS BF
241 		u8 nc = 0x0; //bit 2-0
242 		u8 nr = 0x1; //bit 5-3
243 		u8 ng = 0x0; //bit 7-6
244 		u8 cb = 0x1; //bit 9-8; 1 => phi:6, psi:4;
245 		u32 bw = odm_get_bb_reg(dm, R_0x8ac, 0x3); //bit 11-10
246 		u8 userid = su_idx; //bit 12
247 		u32 csi_report = 0x0;
248 		u32 ndp_bw = odm_get_bb_reg(dm, R_0x8ac, 0x3); //bit 11-10
249 		u8 ndp_sc = 0; //bit 11-10
250 		u32 ndp_info = 0x0;
251 
252 		u16 mem_num = 0;
253 		u8 mem_move = 0;
254 		u8 mem_sel = 0;
255 		u16 mem_addr = 0;
256 		u32 dw0, dw1;
257 		u64 vm_info = 0;
258 		u64 temp = 0;
259 		u8 vm_cnt = 0;
260 
261 		mem_num = ((8 + (6 + 4) * ns[bw]) >> 6) + 1; // SU codebook 1
262 
263 		/* setting NDP BW/SC info*/
264 		ndp_info = (ndp_bw & 0x3)  | (ndp_bw & 0x3) << 6 |
265 			   (ndp_bw & 0x3) << 12 | (ndp_sc & 0xf) << 2 |
266 			   (ndp_sc & 0xf) << 8 | (ndp_sc & 0xf) << 14;
267 		odm_set_bb_reg(dm, R_0xb58, 0x000FFFFC, ndp_info);
268 		odm_set_bb_reg(dm, R_0x19f8, 0x00010000, 1);
269 		ODM_delay_ms(1); // delay 1ms
270 		odm_set_bb_reg(dm, R_0x19f8, 0x00010000, 0);
271 
272 		/* setting CSI report info*/
273 		csi_report = (userid & 0x1) << 12 | (bw & 0x3) << 10 |
274 			     (cb & 0x3) << 8 | (ng & 0x3) << 6 |
275 			     (nr & 0x7) << 3 | (nc & 0x7);
276 		odm_set_bb_reg(dm, R_0x72c, 0x1FFF, csi_report);
277 		odm_set_bb_reg(dm, R_0x71c, 0x80000000, 1);
278 		PHYDM_DBG(dm, DBG_TXBF, "[%s] direct BF csi report 0x%x\n",
279 			  __func__, csi_report);
280 		/*========================*/
281 
282 		odm_set_bb_reg(dm, R_0x19b8, 0x40, 1); //0x19b8[6]:1 to csi_rpt
283 		odm_set_bb_reg(dm, R_0x19e0, 0x3FC0, 0xFF); //gated_clk off
284 		odm_set_bb_reg(dm, R_0x9e8, 0x2000000, 1); //abnormal txbf
285 		odm_set_bb_reg(dm, R_0x9e8, 0x1000000, 0); //read phi psi
286 		odm_set_bb_reg(dm, R_0x9e8, 0x70000000, su_idx); //SU user 0
287 		odm_set_bb_reg(dm, R_0x1910, 0x8000, 0); //BFer
288 
289 		dw0 = 0; // for 0x9ec
290 		dw1 = 0; // for 0x1900
291 		mem_addr = 0;
292 		mem_sel = 0;
293 		mem_move = 0;
294 		vm_info = vm_info | (snr & 0xff); //V matrix info
295 		vm_cnt = 8; // V matrix length counter
296 		psiphiR = (psiphi[phs_idx] & 0x3ff);
297 
298 		while (mem_addr < mem_num) {
299 			while (vm_cnt <= 32) {
300 				// shift only max. 32 bit
301 				if (vm_cnt >= 20) {
302 					temp = psiphiR << 20;
303 					temp = temp << (vm_cnt - 20);
304 				} else {
305 					temp = psiphiR << vm_cnt;
306 				}
307 				vm_info |= temp;
308 				vm_cnt += 10;
309 			}
310 			if (mem_sel == 0) {
311 				dw0 = vm_info & 0xffffffff;
312 				vm_info = vm_info >> 32;
313 				vm_cnt -= 32;
314 				mem_sel = 1;
315 				mem_move = 0;
316 			} else {
317 				dw1 = vm_info & 0xffffffff;
318 				vm_info = vm_info >> 32;
319 				vm_cnt -= 32;
320 				mem_sel = 0;
321 				mem_move = 1;
322 			}
323 			if (mem_move == 1) {
324 				odm_set_bb_reg(dm, 0x9e8, 0x1000000, 0);
325 					       //read phi psi
326 				odm_set_bb_reg(dm, 0x1910, 0x3FF0000,
327 					       mem_addr);
328 				odm_set_bb_reg(dm, 0x09ec, 0xFFFFFFFF, dw0);
329 				odm_set_bb_reg(dm, 0x1900, 0xFFFFFFFF, dw1);
330 				odm_set_bb_reg(dm, 0x9e8, 0x1000000, 1);
331 					       //write phi psi
332 				mem_move = 0;
333 				mem_addr += 1;
334 			}
335 		}
336 		odm_set_bb_reg(dm, 0x9e8, 0x2000000, 0); //normal txbf
337 	}
338 #endif
339 } //end function
340 
341 /*Before use this API, Disable STBC in advance*/
342 /*only 1SS rate can improve performance*/
phydm_set_direct_bfer_txdesc_en(void * dm_void,u8 enable)343 void phydm_set_direct_bfer_txdesc_en(void *dm_void, u8 enable)
344 {
345 	struct dm_struct *dm = (struct dm_struct *)dm_void;
346 #if (RTL8197G_SUPPORT)
347 	if (dm->support_ic_type & ODM_RTL8197G) {
348 		phydm_iq_gen_en(dm);
349 
350 		/*#ifdef PHYDM_COMMON_API_SUPPORT*/
351 		/*path selection is controlled by driver, use 1ss 2Tx*/
352 		#if 0
353 		if (!phydm_api_trx_mode(dm, BB_PATH_AB, BB_PATH_AB, BB_PATH_AB))
354 			return;
355 		#endif
356 
357 		phydm_dis_cdd(dm);
358 		if (enable)
359 			odm_set_bb_reg(dm, R_0x1d90, 0x8000, 1);
360 		else
361 			odm_set_bb_reg(dm, R_0x1d90, 0x8000, 0);
362 	}
363 #endif
364 } //end function
365 #endif
366 #endif
367