1 /******************************************************************************
2 *
3 * Copyright(c) 2016 - 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 *****************************************************************************/
15 /*@============================================================*/
16 /* @Description: */
17 /* @*/
18 /* This file is for 8814A TXBF mechanism */
19 /* @*/
20 /*@============================================================*/
21
22 #include "mp_precomp.h"
23 #include "phydm_precomp.h"
24
25 #if (RTL8822B_SUPPORT == 1)
26 #ifdef PHYDM_BEAMFORMING_SUPPORT
27
hal_txbf_8822b_get_ntx(void * dm_void)28 u8 hal_txbf_8822b_get_ntx(
29 void *dm_void)
30 {
31 struct dm_struct *dm = (struct dm_struct *)dm_void;
32 u8 ntx = 0;
33
34 #if DEV_BUS_TYPE == RT_USB_INTERFACE
35 if (dm->support_interface == ODM_ITRF_USB) {
36 if (*dm->hub_usb_mode == 2) { /*USB3.0*/
37 if (dm->rf_type == RF_4T4R)
38 ntx = 3;
39 else if (dm->rf_type == RF_3T3R)
40 ntx = 2;
41 else
42 ntx = 1;
43 } else if (*dm->hub_usb_mode == 1) /*USB 2.0 always 2Tx*/
44 ntx = 1;
45 else
46 ntx = 1;
47 } else
48 #endif
49 {
50 if (dm->rf_type == RF_4T4R)
51 ntx = 3;
52 else if (dm->rf_type == RF_3T3R)
53 ntx = 2;
54 else
55 ntx = 1;
56 }
57
58 return ntx;
59 }
60
hal_txbf_8822b_get_nrx(void * dm_void)61 u8 hal_txbf_8822b_get_nrx(
62 void *dm_void)
63 {
64 struct dm_struct *dm = (struct dm_struct *)dm_void;
65 u8 nrx = 0;
66
67 if (dm->rf_type == RF_4T4R)
68 nrx = 3;
69 else if (dm->rf_type == RF_3T3R)
70 nrx = 2;
71 else if (dm->rf_type == RF_2T2R)
72 nrx = 1;
73 else if (dm->rf_type == RF_2T3R)
74 nrx = 2;
75 else if (dm->rf_type == RF_2T4R)
76 nrx = 3;
77 else if (dm->rf_type == RF_1T1R)
78 nrx = 0;
79 else if (dm->rf_type == RF_1T2R)
80 nrx = 1;
81 else
82 nrx = 0;
83
84 return nrx;
85 }
86
87 /***************SU & MU BFee Entry********************/
hal_txbf_8822b_rf_mode(void * dm_void,struct _RT_BEAMFORMING_INFO * beamforming_info,u8 idx)88 void hal_txbf_8822b_rf_mode(
89 void *dm_void,
90 struct _RT_BEAMFORMING_INFO *beamforming_info,
91 u8 idx)
92 {
93 #if 0
94 struct dm_struct *dm = (struct dm_struct *)dm_void;
95 u8 i, nr_index = 0;
96 boolean is_self_beamformer = false;
97 boolean is_self_beamformee = false;
98 struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
99
100 if (idx < BEAMFORMEE_ENTRY_NUM)
101 beamformee_entry = beamforming_info->beamformee_entry[idx];
102 else
103 return;
104
105 if (dm->rf_type == RF_1T1R)
106 return;
107
108 for (i = RF_PATH_A; i < RF_PATH_B; i++) {
109 odm_set_rf_reg(dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x1);
110 /*RF mode table write enable*/
111 }
112
113 if (beamforming_info->beamformee_su_cnt > 0 || beamforming_info->beamformee_mu_cnt > 0) {
114 for (i = RF_PATH_A; i < RF_PATH_B; i++) {
115 odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_addr, 0xfffff, 0x18000);
116 /*Select RX mode*/
117 odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_data0, 0xfffff, 0xBE77F);
118 /*Set Table data*/
119 odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_data1, 0xfffff, 0x226BF);
120 /*@Enable TXIQGEN in RX mode*/
121 }
122 odm_set_rf_reg(dm, RF_PATH_A, rf_mode_table_data1, 0xfffff, 0xE26BF);
123 /*@Enable TXIQGEN in RX mode*/
124 }
125
126 for (i = RF_PATH_A; i < RF_PATH_B; i++) {
127 odm_set_rf_reg(dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x0);
128 /*RF mode table write disable*/
129 }
130
131 if (beamforming_info->beamformee_su_cnt > 0) {
132 /*@for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
133 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2); /*@enable BB TxBF ant mapping register*/
134
135 if (idx == 0) {
136 /*Nsts = 2 AB*/
137 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF0_8822B, 0xffff, 0x0433);
138 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
139 /*odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430);*/
140
141 } else {/*@IDX =1*/
142 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
143 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
144 /*odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430;*/
145 }
146 } else {
147 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*@1SS by path-A*/
148 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*@2SS by path-A,B*/
149 }
150
151 if (beamforming_info->beamformee_mu_cnt > 0) {
152 /*@MU STAs share the common setting*/
153 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1);
154 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
155 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
156 }
157 #endif
158 }
159 #if 0
160 void
161 hal_txbf_8822b_download_ndpa(
162 void *adapter,
163 u8 idx
164 )
165 {
166 u8 u1b_tmp = 0, tmp_reg422 = 0;
167 u8 bcn_valid_reg = 0, count = 0, dl_bcn_count = 0;
168 u16 head_page = 0x7FE;
169 boolean is_send_beacon = false;
170 HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
171 u16 tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8814A; /*@default reseved 1 page for the IC type which is undefined.*/
172 struct _RT_BEAMFORMING_INFO *beam_info = GET_BEAMFORM_INFO(adapter);
173 struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = beam_info->beamformee_entry + idx;
174
175 hal_data->is_fw_dw_rsvd_page_in_progress = true;
176 phydm_get_hal_def_var_handler_interface(dm, HAL_DEF_TX_PAGE_BOUNDARY, (u16 *)&tx_page_bndy);
177
178 /*Set REG_CR bit 8. DMA beacon by SW.*/
179 u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1);
180 platform_efio_write_1byte(adapter, REG_CR_8814A + 1, (u1b_tmp | BIT(0)));
181
182
183 /*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/
184 tmp_reg422 = platform_efio_read_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2);
185 platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422 & (~BIT(6)));
186
187 if (tmp_reg422 & BIT(6)) {
188 RT_TRACE(COMP_INIT, DBG_LOUD, ("SetBeamformDownloadNDPA_8814A(): There is an adapter is sending beacon.\n"));
189 is_send_beacon = true;
190 }
191
192 /*@0x204[11:0] Beacon Head for TXDMA*/
193 platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, head_page);
194
195 do {
196 /*@Clear beacon valid check bit.*/
197 bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1);
198 platform_efio_write_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1, (bcn_valid_reg | BIT(7)));
199
200 /*@download NDPA rsvd page.*/
201 if (p_beam_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
202 beamforming_send_vht_ndpa_packet(dm, p_beam_entry->mac_addr, p_beam_entry->AID, p_beam_entry->sound_bw, BEACON_QUEUE);
203 else
204 beamforming_send_ht_ndpa_packet(dm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE);
205
206 /*@check rsvd page download OK.*/
207 bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1);
208 count = 0;
209 while (!(bcn_valid_reg & BIT(7)) && count < 20) {
210 count++;
211 delay_us(10);
212 bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 2);
213 }
214 dl_bcn_count++;
215 } while (!(bcn_valid_reg & BIT(7)) && dl_bcn_count < 5);
216
217 if (!(bcn_valid_reg & BIT(0)))
218 RT_DISP(FBEAM, FBEAM_ERROR, ("%s Download RSVD page failed!\n", __func__));
219
220 /*@0x204[11:0] Beacon Head for TXDMA*/
221 platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, tx_page_bndy);
222
223 /*To make sure that if there exists an adapter which would like to send beacon.*/
224 /*@If exists, the origianl value of 0x422[6] will be 1, we should check this to*/
225 /*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
226 /*the beacon cannot be sent by HW.*/
227 /*@2010.06.23. Added by tynli.*/
228 if (is_send_beacon)
229 platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422);
230
231 /*@Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/
232 /*@Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
233 u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1);
234 platform_efio_write_1byte(adapter, REG_CR_8814A + 1, (u1b_tmp & (~BIT(0))));
235
236 p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
237
238 hal_data->is_fw_dw_rsvd_page_in_progress = false;
239 }
240
241 void
242 hal_txbf_8822b_fw_txbf_cmd(
243 void *adapter
244 )
245 {
246 u8 idx, period = 0;
247 u8 PageNum0 = 0xFF, PageNum1 = 0xFF;
248 u8 u1_tx_bf_parm[3] = {0};
249
250 PMGNT_INFO mgnt_info = &(adapter->MgntInfo);
251 struct _RT_BEAMFORMING_INFO *beam_info = GET_BEAMFORM_INFO(adapter);
252
253 for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
254 if (beam_info->beamformee_entry[idx].is_used && beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
255 if (beam_info->beamformee_entry[idx].is_sound) {
256 PageNum0 = 0xFE;
257 PageNum1 = 0x07;
258 period = (u8)(beam_info->beamformee_entry[idx].sound_period);
259 } else if (PageNum0 == 0xFF) {
260 PageNum0 = 0xFF; /*stop sounding*/
261 PageNum1 = 0x0F;
262 }
263 }
264 }
265
266 u1_tx_bf_parm[0] = PageNum0;
267 u1_tx_bf_parm[1] = PageNum1;
268 u1_tx_bf_parm[2] = period;
269 fill_h2c_cmd(adapter, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm);
270
271 RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, PageNum0 = 0x%x, PageNum1 = 0x%x period = %d", __func__, PageNum0, PageNum1, period));
272 }
273 #endif
274
275 #if 0
276 void
277 hal_txbf_8822b_init(
278 void *dm_void
279 )
280 {
281 struct dm_struct *dm = (struct dm_struct *)dm_void;
282 u8 u1b_tmp;
283 struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
284 void *adapter = dm->adapter;
285
286 odm_set_bb_reg(dm, R_0x14c0, BIT(16), 1); /*@Enable P1 aggr new packet according to P0 transfer time*/
287 odm_set_bb_reg(dm, R_0x14c0, BIT(15) | BIT14 | BIT13 | BIT12, 10); /*@MU Retry Limit*/
288 odm_set_bb_reg(dm, R_0x14c0, BIT(7), 0); /*@Disable Tx MU-MIMO until sounding done*/
289 odm_set_bb_reg(dm, R_0x14c0, 0x3F, 0); /* @Clear validity of MU STAs */
290 odm_write_1byte(dm, 0x167c, 0x70); /*@MU-MIMO Option as default value*/
291 odm_write_2byte(dm, 0x1680, 0); /*@MU-MIMO Control as default value*/
292
293 /* Set MU NDPA rate & BW source */
294 /* @0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */
295 u1b_tmp = odm_read_1byte(dm, 0x42C);
296 odm_write_1byte(dm, REG_TXBF_CTRL_8822B, (u1b_tmp | BIT(6)));
297 /* @0x45F[7:0] = 0x10 (rate=OFDM_6M, BW20) */
298 odm_write_1byte(dm, REG_NDPA_OPT_CTRL_8822B, 0x10);
299
300 /*Temp Settings*/
301 odm_set_bb_reg(dm, R_0x6dc, 0x3F000000, 4); /*STA2's CSI rate is fixed at 6M*/
302 odm_set_bb_reg(dm, R_0x1c94, MASKDWORD, 0xAFFFAFFF); /*@Grouping bitmap parameters*/
303
304 /* @Init HW variable */
305 beamforming_info->reg_mu_tx_ctrl = odm_read_4byte(dm, 0x14c0);
306
307 if (dm->rf_type == RF_2T2R) { /*@2T2R*/
308 PHYDM_DBG(dm, DBG_TXBF, "%s: rf_type is 2T2R\n", __func__);
309 config_phydm_trx_mode_8822b(dm, (enum bb_path)3,
310 (enum bb_path)3, BB_PATH_AB;
311 }
312
313 #if (OMNIPEEK_SNIFFER_ENABLED == 1)
314 /* @Config HW to receive packet on the user position from registry for sniffer mode. */
315 /* odm_set_bb_reg(dm, R_0xb00, BIT(9), 1);*/ /* For A-cut only. RegB00[9] = 1 (enable PMAC Rx) */
316 odm_set_bb_reg(dm, R_0xb54, BIT(30), 1); /* RegB54[30] = 1 (force user position) */
317 odm_set_bb_reg(dm, R_0xb54, (BIT(29) | BIT28), adapter->MgntInfo.sniff_user_position); /* RegB54[29:28] = user position (0~3) */
318 PHYDM_DBG(dm, DBG_TXBF,
319 "Set adapter->MgntInfo.sniff_user_position=%#X\n",
320 adapter->MgntInfo.sniff_user_position);
321 #endif
322 }
323 #endif
324
hal_txbf_8822b_enter(void * dm_void,u8 bfer_bfee_idx)325 void hal_txbf_8822b_enter(
326 void *dm_void,
327 u8 bfer_bfee_idx)
328 {
329 struct dm_struct *dm = (struct dm_struct *)dm_void;
330 u8 i = 0;
331 u8 bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
332 u8 bfee_idx = (bfer_bfee_idx & 0xF);
333 u16 csi_param = 0;
334 struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
335 struct _RT_BEAMFORMEE_ENTRY *p_beamformee_entry;
336 struct _RT_BEAMFORMER_ENTRY *beamformer_entry;
337 u16 value16, sta_id = 0;
338 u8 nc_index = 0, nr_index = 0, grouping = 0, codebookinfo = 0, coefficientsize = 0;
339 u32 gid_valid, user_position_l, user_position_h;
340 u32 mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
341 u8 u1b_tmp;
342 u32 u4b_tmp;
343
344 RT_DISP(FBEAM, FBEAM_FUN, ("%s: bfer_bfee_idx=%d, bfer_idx=%d, bfee_idx=%d\n", __func__, bfer_bfee_idx, bfer_idx, bfee_idx));
345
346 /*************SU BFer Entry Init*************/
347 if (beamforming_info->beamformer_su_cnt > 0 && bfer_idx < BEAMFORMER_ENTRY_NUM) {
348 beamformer_entry = &beamforming_info->beamformer_entry[bfer_idx];
349 beamformer_entry->is_mu_ap = false;
350 /*Sounding protocol control*/
351 odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
352
353 for (i = 0; i < MAX_BEAMFORMER_SU; i++) {
354 if ((beamforming_info->beamformer_su_reg_maping & BIT(i)) == 0) {
355 beamforming_info->beamformer_su_reg_maping |= BIT(i);
356 beamformer_entry->su_reg_index = i;
357 break;
358 }
359 }
360
361 /*@MAC address/Partial AID of Beamformer*/
362 if (beamformer_entry->su_reg_index == 0) {
363 for (i = 0; i < 6; i++)
364 odm_write_1byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), beamformer_entry->mac_addr[i]);
365 } else {
366 for (i = 0; i < 6; i++)
367 odm_write_1byte(dm, (REG_ASSOCIATED_BFMER1_INFO_8822B + i), beamformer_entry->mac_addr[i]);
368 }
369
370 /*@CSI report parameters of Beamformer*/
371 nc_index = hal_txbf_8822b_get_nrx(dm); /*@for 8814A nrx = 3(4 ant), min=0(1 ant)*/
372 nr_index = beamformer_entry->num_of_sounding_dim; /*@0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
373
374 grouping = 0;
375
376 /*@for ac = 1, for n = 3*/
377 if (beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU)
378 codebookinfo = 1;
379 else if (beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
380 codebookinfo = 3;
381
382 coefficientsize = 3;
383
384 csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
385
386 if (bfer_idx == 0)
387 odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B, csi_param);
388 else
389 odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, csi_param);
390 /*ndp_rx_standby_timer, 8814 need > 0x56, suggest from Dvaid*/
391 odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B + 3, 0x70);
392 }
393
394 /*************SU BFee Entry Init*************/
395 if (beamforming_info->beamformee_su_cnt > 0 && bfee_idx < BEAMFORMEE_ENTRY_NUM) {
396 p_beamformee_entry = &beamforming_info->beamformee_entry[bfee_idx];
397 p_beamformee_entry->is_mu_sta = false;
398 hal_txbf_8822b_rf_mode(dm, beamforming_info, bfee_idx);
399
400 if (phydm_acting_determine(dm, phydm_acting_as_ibss))
401 sta_id = p_beamformee_entry->mac_id;
402 else
403 sta_id = p_beamformee_entry->p_aid;
404
405 for (i = 0; i < MAX_BEAMFORMEE_SU; i++) {
406 if ((beamforming_info->beamformee_su_reg_maping & BIT(i)) == 0) {
407 beamforming_info->beamformee_su_reg_maping |= BIT(i);
408 p_beamformee_entry->su_reg_index = i;
409 break;
410 }
411 }
412
413 /*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
414 if (p_beamformee_entry->su_reg_index == 0) {
415 odm_write_2byte(dm, REG_TXBF_CTRL_8822B, sta_id);
416 odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
417 } else
418 odm_write_2byte(dm, REG_TXBF_CTRL_8822B + 2, sta_id | BIT(14) | BIT(15) | BIT(12));
419
420 /*@CSI report parameters of Beamformee*/
421 if (p_beamformee_entry->su_reg_index == 0) {
422 /*@Get BIT24 & BIT25*/
423 u8 tmp = odm_read_1byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3) & 0x3;
424
425 odm_write_1byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3, tmp | 0x60);
426 odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B, sta_id | BIT(9));
427 } else
428 odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2, sta_id | 0xE200); /*Set BIT25*/
429
430 phydm_beamforming_notify(dm);
431 }
432
433 /*************MU BFer Entry Init*************/
434 if (beamforming_info->beamformer_mu_cnt > 0 && bfer_idx < BEAMFORMER_ENTRY_NUM) {
435 beamformer_entry = &beamforming_info->beamformer_entry[bfer_idx];
436 beamforming_info->mu_ap_index = bfer_idx;
437 beamformer_entry->is_mu_ap = true;
438 for (i = 0; i < 8; i++)
439 beamformer_entry->gid_valid[i] = 0;
440 for (i = 0; i < 16; i++)
441 beamformer_entry->user_position[i] = 0;
442
443 /*Sounding protocol control*/
444 odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
445
446 /* @MAC address */
447 for (i = 0; i < 6; i++)
448 odm_write_1byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), beamformer_entry->mac_addr[i]);
449
450 /* Set partial AID */
451 odm_write_2byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + 6), beamformer_entry->p_aid);
452
453 /* @Fill our AID to 0x1680[11:0] and [13:12] = 2b'00, BF report segment select to 3895 bytes*/
454 u1b_tmp = odm_read_1byte(dm, 0x1680);
455 u1b_tmp = (beamformer_entry->p_aid) & 0xFFF;
456 odm_write_1byte(dm, 0x1680, u1b_tmp);
457
458 /* Set 80us for leaving ndp_rx_standby_state */
459 odm_write_1byte(dm, 0x71B, 0x50);
460
461 /* Set 0x6A0[14] = 1 to accept action_no_ack */
462 u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP0_8822B + 1);
463 u1b_tmp |= 0x40;
464 odm_write_1byte(dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
465 /* Set 0x6A2[5:4] = 1 to NDPA and BF report poll */
466 u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP1_8822B);
467 u1b_tmp |= 0x30;
468 odm_write_1byte(dm, REG_RXFLTMAP1_8822B, u1b_tmp);
469
470 /*@CSI report parameters of Beamformer*/
471 nc_index = hal_txbf_8822b_get_nrx(dm); /* @Depend on RF type */
472 nr_index = 1; /*@0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
473 grouping = 0; /*no grouping*/
474 codebookinfo = 1; /*@7 bit for psi, 9 bit for phi*/
475 coefficientsize = 0; /*This is nothing really matter*/
476 csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
477 odm_write_2byte(dm, 0x6F4, csi_param);
478
479 /*@for B-cut*/
480 odm_set_bb_reg(dm, R_0x6a0, BIT(20), 0);
481 odm_set_bb_reg(dm, R_0x688, BIT(20), 0);
482 }
483
484 /*************MU BFee Entry Init*************/
485 if (beamforming_info->beamformee_mu_cnt > 0 && bfee_idx < BEAMFORMEE_ENTRY_NUM) {
486 p_beamformee_entry = &beamforming_info->beamformee_entry[bfee_idx];
487 p_beamformee_entry->is_mu_sta = true;
488 for (i = 0; i < MAX_BEAMFORMEE_MU; i++) {
489 if ((beamforming_info->beamformee_mu_reg_maping & BIT(i)) == 0) {
490 beamforming_info->beamformee_mu_reg_maping |= BIT(i);
491 p_beamformee_entry->mu_reg_index = i;
492 break;
493 }
494 }
495
496 if (p_beamformee_entry->mu_reg_index == 0xFF) {
497 /* There is no valid bit in beamformee_mu_reg_maping */
498 RT_DISP(FBEAM, FBEAM_FUN, ("%s: ERROR! There is no valid bit in beamformee_mu_reg_maping!\n", __func__));
499 return;
500 }
501
502 /*User position table*/
503 switch (p_beamformee_entry->mu_reg_index) {
504 case 0:
505 gid_valid = 0x7fe;
506 user_position_l = 0x111110;
507 user_position_h = 0x0;
508 break;
509 case 1:
510 gid_valid = 0x7f806;
511 user_position_l = 0x11000004;
512 user_position_h = 0x11;
513 break;
514 case 2:
515 gid_valid = 0x1f81818;
516 user_position_l = 0x400040;
517 user_position_h = 0x11100;
518 break;
519 case 3:
520 gid_valid = 0x1e186060;
521 user_position_l = 0x4000400;
522 user_position_h = 0x1100040;
523 break;
524 case 4:
525 gid_valid = 0x66618180;
526 user_position_l = 0x40004000;
527 user_position_h = 0x10040400;
528 break;
529 case 5:
530 gid_valid = 0x79860600;
531 user_position_l = 0x40000;
532 user_position_h = 0x4404004;
533 break;
534 }
535
536 for (i = 0; i < 8; i++) {
537 if (i < 4) {
538 p_beamformee_entry->gid_valid[i] = (u8)(gid_valid & 0xFF);
539 gid_valid = (gid_valid >> 8);
540 } else
541 p_beamformee_entry->gid_valid[i] = 0;
542 }
543 for (i = 0; i < 16; i++) {
544 if (i < 4)
545 p_beamformee_entry->user_position[i] = (u8)((user_position_l >> (i * 8)) & 0xFF);
546 else if (i < 8)
547 p_beamformee_entry->user_position[i] = (u8)((user_position_h >> ((i - 4) * 8)) & 0xFF);
548 else
549 p_beamformee_entry->user_position[i] = 0;
550 }
551
552 /*Sounding protocol control*/
553 odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
554
555 /*select MU STA table*/
556 beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
557 beamforming_info->reg_mu_tx_ctrl |= (p_beamformee_entry->mu_reg_index << 8) & (BIT(8) | BIT(9) | BIT(10));
558 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
559
560 odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, 0); /*Reset gid_valid table*/
561 odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
562 odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
563
564 /*set validity of MU STAs*/
565 beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
566 beamforming_info->reg_mu_tx_ctrl |= beamforming_info->beamformee_mu_reg_maping & 0x3F;
567 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
568
569 PHYDM_DBG(dm, DBG_TXBF,
570 "@%s, reg_mu_tx_ctrl = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
571 __func__, beamforming_info->reg_mu_tx_ctrl,
572 user_position_l, user_position_h);
573
574 value16 = odm_read_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index]);
575 value16 &= 0xFE00; /*@Clear PAID*/
576 value16 |= BIT(9); /*@Enable MU BFee*/
577 value16 |= p_beamformee_entry->p_aid;
578 odm_write_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index], value16);
579
580 /* @0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */
581 u1b_tmp = odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3);
582 u1b_tmp |= 0xD0; /* Set bit 28, 30, 31 to 3b'111*/
583 odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, u1b_tmp);
584 /* Set NDPA to 6M*/
585 odm_write_1byte(dm, REG_NDPA_RATE_8822B, 0x4);
586
587 u1b_tmp = odm_read_1byte(dm, REG_NDPA_OPT_CTRL_8822B);
588 u1b_tmp &= 0xFC; /* @Clear bit 0, 1*/
589 odm_write_1byte(dm, REG_NDPA_OPT_CTRL_8822B, u1b_tmp);
590
591 u4b_tmp = odm_read_4byte(dm, REG_SND_PTCL_CTRL_8822B);
592 u4b_tmp = ((u4b_tmp & 0xFF0000FF) | 0x020200); /* Set [23:8] to 0x0202*/
593 odm_write_4byte(dm, REG_SND_PTCL_CTRL_8822B, u4b_tmp);
594
595 /* Set 0x6A0[14] = 1 to accept action_no_ack */
596 u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP0_8822B + 1);
597 u1b_tmp |= 0x40;
598 odm_write_1byte(dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
599 /* @End of MAC registers setting */
600
601 hal_txbf_8822b_rf_mode(dm, beamforming_info, bfee_idx);
602 #if (SUPPORT_MU_BF == 1)
603 /*Special for plugfest*/
604 delay_ms(50); /* wait for 4-way handshake ending*/
605 send_sw_vht_gid_mgnt_frame(dm, p_beamformee_entry->mac_addr, bfee_idx);
606 #endif
607
608 phydm_beamforming_notify(dm);
609 #if 1
610 {
611 u32 ctrl_info_offset, index;
612 /*Set Ctrl Info*/
613 odm_write_2byte(dm, 0x140, 0x660);
614 ctrl_info_offset = 0x8000 + 32 * p_beamformee_entry->mac_id;
615 /*Reset Ctrl Info*/
616 for (index = 0; index < 8; index++)
617 odm_write_4byte(dm, ctrl_info_offset + index * 4, 0);
618
619 odm_write_4byte(dm, ctrl_info_offset, (p_beamformee_entry->mu_reg_index + 1) << 16);
620 odm_write_1byte(dm, 0x81, 0x80); /*RPTBUF ready*/
621
622 PHYDM_DBG(dm, DBG_TXBF,
623 "@%s, mac_id = %d, ctrl_info_offset = 0x%x, mu_reg_index = %x\n",
624 __func__, p_beamformee_entry->mac_id,
625 ctrl_info_offset,
626 p_beamformee_entry->mu_reg_index);
627 }
628 #endif
629 }
630 }
631
hal_txbf_8822b_leave(void * dm_void,u8 idx)632 void hal_txbf_8822b_leave(
633 void *dm_void,
634 u8 idx)
635 {
636 struct dm_struct *dm = (struct dm_struct *)dm_void;
637 struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
638 struct _RT_BEAMFORMER_ENTRY *beamformer_entry;
639 struct _RT_BEAMFORMEE_ENTRY *p_beamformee_entry;
640 u32 mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
641
642 if (idx < BEAMFORMER_ENTRY_NUM) {
643 beamformer_entry = &beamforming_info->beamformer_entry[idx];
644 p_beamformee_entry = &beamforming_info->beamformee_entry[idx];
645 } else
646 return;
647
648 /*@Clear P_AID of Beamformee*/
649 /*@Clear MAC address of Beamformer*/
650 /*@Clear Associated Bfmee Sel*/
651
652 if (beamformer_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
653 odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xD8);
654 if (beamformer_entry->is_mu_ap == 0) { /*SU BFer */
655 if (beamformer_entry->su_reg_index == 0) {
656 odm_write_4byte(dm, REG_ASSOCIATED_BFMER0_INFO_8822B, 0);
657 odm_write_2byte(dm, REG_ASSOCIATED_BFMER0_INFO_8822B + 4, 0);
658 odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B, 0);
659 } else {
660 odm_write_4byte(dm, REG_ASSOCIATED_BFMER1_INFO_8822B, 0);
661 odm_write_2byte(dm, REG_ASSOCIATED_BFMER1_INFO_8822B + 4, 0);
662 odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, 0);
663 }
664 beamforming_info->beamformer_su_reg_maping &= ~(BIT(beamformer_entry->su_reg_index));
665 beamformer_entry->su_reg_index = 0xFF;
666 } else { /*@MU BFer */
667 /*set validity of MU STA0 and MU STA1*/
668 beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
669 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
670
671 odm_memory_set(dm, beamformer_entry->gid_valid, 0, 8);
672 odm_memory_set(dm, beamformer_entry->user_position, 0, 16);
673 beamformer_entry->is_mu_ap = false;
674 }
675 }
676
677 if (p_beamformee_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
678 hal_txbf_8822b_rf_mode(dm, beamforming_info, idx);
679 if (p_beamformee_entry->is_mu_sta == 0) { /*SU BFee*/
680 if (p_beamformee_entry->su_reg_index == 0) {
681 odm_write_2byte(dm, REG_TXBF_CTRL_8822B, 0x0);
682 odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
683 odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B, 0);
684 } else {
685 odm_write_2byte(dm, REG_TXBF_CTRL_8822B + 2, 0x0 | BIT(14) | BIT(15) | BIT(12));
686
687 odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2,
688 odm_read_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2) & 0x60);
689 }
690 beamforming_info->beamformee_su_reg_maping &= ~(BIT(p_beamformee_entry->su_reg_index));
691 p_beamformee_entry->su_reg_index = 0xFF;
692 } else { /*@MU BFee */
693 /*@Disable sending NDPA & BF-rpt-poll to this BFee*/
694 odm_write_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index], 0);
695 /*set validity of MU STA*/
696 beamforming_info->reg_mu_tx_ctrl &= ~(BIT(p_beamformee_entry->mu_reg_index));
697 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
698
699 p_beamformee_entry->is_mu_sta = false;
700 beamforming_info->beamformee_mu_reg_maping &= ~(BIT(p_beamformee_entry->mu_reg_index));
701 p_beamformee_entry->mu_reg_index = 0xFF;
702 }
703 }
704 }
705
706 /***********SU & MU BFee Entry Only when souding done****************/
hal_txbf_8822b_status(void * dm_void,u8 beamform_idx)707 void hal_txbf_8822b_status(
708 void *dm_void,
709 u8 beamform_idx)
710 {
711 struct dm_struct *dm = (struct dm_struct *)dm_void;
712 u16 beam_ctrl_val, tmp_val;
713 u32 beam_ctrl_reg;
714 struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
715 struct _RT_BEAMFORMEE_ENTRY *beamform_entry;
716 boolean is_mu_sounding = beamforming_info->is_mu_sounding, is_bitmap_ready = false;
717 u16 bitmap;
718 u8 idx, gid, i;
719 u8 id1, id0;
720 u32 gid_valid[6] = {0};
721 u32 value32;
722 boolean is_sounding_success[6] = {false};
723
724 if (beamform_idx < BEAMFORMEE_ENTRY_NUM)
725 beamform_entry = &beamforming_info->beamformee_entry[beamform_idx];
726 else
727 return;
728
729 /*SU sounding done */
730 if (is_mu_sounding == false) {
731 if (phydm_acting_determine(dm, phydm_acting_as_ibss))
732 beam_ctrl_val = beamform_entry->mac_id;
733 else
734 beam_ctrl_val = beamform_entry->p_aid;
735
736 PHYDM_DBG(dm, DBG_TXBF,
737 "@%s, beamform_entry.beamform_entry_state = %d",
738 __func__, beamform_entry->beamform_entry_state);
739
740 if (beamform_entry->su_reg_index == 0)
741 beam_ctrl_reg = REG_TXBF_CTRL_8822B;
742 else {
743 beam_ctrl_reg = REG_TXBF_CTRL_8822B + 2;
744 beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
745 }
746
747 if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
748 if (beamform_entry->sound_bw == CHANNEL_WIDTH_20)
749 beam_ctrl_val |= BIT(9);
750 else if (beamform_entry->sound_bw == CHANNEL_WIDTH_40)
751 beam_ctrl_val |= (BIT(9) | BIT(10));
752 else if (beamform_entry->sound_bw == CHANNEL_WIDTH_80)
753 beam_ctrl_val |= (BIT(9) | BIT(10) | BIT(11));
754 } else {
755 PHYDM_DBG(dm, DBG_TXBF, "@%s, Don't apply Vmatrix",
756 __func__);
757 beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
758 }
759
760 odm_write_2byte(dm, beam_ctrl_reg, beam_ctrl_val);
761 /*@disable NDP packet use beamforming */
762 tmp_val = odm_read_2byte(dm, REG_TXBF_CTRL_8822B);
763 odm_write_2byte(dm, REG_TXBF_CTRL_8822B, tmp_val | BIT(15));
764 } else {
765 PHYDM_DBG(dm, DBG_TXBF, "@%s, MU Sounding Done\n", __func__);
766 /*@MU sounding done */
767 if (1) { /* @(beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) { */
768 PHYDM_DBG(dm, DBG_TXBF,
769 "@%s, BEAMFORMING_ENTRY_STATE_PROGRESSED\n",
770 __func__);
771
772 value32 = odm_get_bb_reg(dm, R_0x1684, MASKDWORD);
773 is_sounding_success[0] = (value32 & BIT(10)) ? 1 : 0;
774 is_sounding_success[1] = (value32 & BIT(26)) ? 1 : 0;
775 value32 = odm_get_bb_reg(dm, R_0x1688, MASKDWORD);
776 is_sounding_success[2] = (value32 & BIT(10)) ? 1 : 0;
777 is_sounding_success[3] = (value32 & BIT(26)) ? 1 : 0;
778 value32 = odm_get_bb_reg(dm, R_0x168c, MASKDWORD);
779 is_sounding_success[4] = (value32 & BIT(10)) ? 1 : 0;
780 is_sounding_success[5] = (value32 & BIT(26)) ? 1 : 0;
781
782 PHYDM_DBG(dm, DBG_TXBF,
783 "@%s, is_sounding_success STA1:%d, STA2:%d, STA3:%d, STA4:%d, STA5:%d, STA6:%d\n",
784 __func__, is_sounding_success[0],
785 is_sounding_success[1],
786 is_sounding_success[2],
787 is_sounding_success[3],
788 is_sounding_success[4],
789 is_sounding_success[5]);
790
791 value32 = odm_get_bb_reg(dm, R_0xf4c, 0xFFFF0000);
792 /* odm_set_bb_reg(dm, R_0x19e0, MASKHWORD, 0xFFFF);Let MAC ignore bitmap */
793
794 is_bitmap_ready = (boolean)((value32 & BIT(15)) >> 15);
795 bitmap = (u16)(value32 & 0x3FFF);
796
797 for (idx = 0; idx < 15; idx++) {
798 if (idx < 5) { /*@bit0~4*/
799 id0 = 0;
800 id1 = (u8)(idx + 1);
801 } else if (idx < 9) { /*@bit5~8*/
802 id0 = 1;
803 id1 = (u8)(idx - 3);
804 } else if (idx < 12) { /*@bit9~11*/
805 id0 = 2;
806 id1 = (u8)(idx - 6);
807 } else if (idx < 14) { /*@bit12~13*/
808 id0 = 3;
809 id1 = (u8)(idx - 8);
810 } else { /*@bit14*/
811 id0 = 4;
812 id1 = (u8)(idx - 9);
813 }
814 if (bitmap & BIT(idx)) {
815 /*Pair 1*/
816 gid = (idx << 1) + 1;
817 gid_valid[id0] |= (BIT(gid));
818 gid_valid[id1] |= (BIT(gid));
819 /*Pair 2*/
820 gid += 1;
821 gid_valid[id0] |= (BIT(gid));
822 gid_valid[id1] |= (BIT(gid));
823 } else {
824 /*Pair 1*/
825 gid = (idx << 1) + 1;
826 gid_valid[id0] &= ~(BIT(gid));
827 gid_valid[id1] &= ~(BIT(gid));
828 /*Pair 2*/
829 gid += 1;
830 gid_valid[id0] &= ~(BIT(gid));
831 gid_valid[id1] &= ~(BIT(gid));
832 }
833 }
834
835 for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
836 beamform_entry = &beamforming_info->beamformee_entry[i];
837 if (beamform_entry->is_mu_sta && beamform_entry->mu_reg_index < 6) {
838 value32 = gid_valid[beamform_entry->mu_reg_index];
839 for (idx = 0; idx < 4; idx++) {
840 beamform_entry->gid_valid[idx] = (u8)(value32 & 0xFF);
841 value32 = (value32 >> 8);
842 }
843 }
844 }
845
846 for (idx = 0; idx < 6; idx++) {
847 beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
848 beamforming_info->reg_mu_tx_ctrl |= ((idx << 8) & (BIT(8) | BIT(9) | BIT(10)));
849 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
850 odm_set_mac_reg(dm, R_0x14c4, MASKDWORD, gid_valid[idx]); /*set MU STA gid valid table*/
851 }
852
853 /*@Enable TxMU PPDU*/
854 if (beamforming_info->dbg_disable_mu_tx == false)
855 beamforming_info->reg_mu_tx_ctrl |= BIT(7);
856 else
857 beamforming_info->reg_mu_tx_ctrl &= ~BIT(7);
858 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
859 }
860 }
861 }
862
863 /*Only used for MU BFer Entry when get GID management frame (self is as MU STA)*/
hal_txbf_8822b_config_gtab(void * dm_void)864 void hal_txbf_8822b_config_gtab(
865 void *dm_void)
866 {
867 struct dm_struct *dm = (struct dm_struct *)dm_void;
868 struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
869 struct _RT_BEAMFORMER_ENTRY *beamformer_entry = NULL;
870 u32 gid_valid = 0, user_position_l = 0, user_position_h = 0, i;
871
872 if (beamforming_info->mu_ap_index < BEAMFORMER_ENTRY_NUM)
873 beamformer_entry = &beamforming_info->beamformer_entry[beamforming_info->mu_ap_index];
874 else
875 return;
876
877 PHYDM_DBG(dm, DBG_TXBF, "%s==>\n", __func__);
878
879 /*@For GID 0~31*/
880 for (i = 0; i < 4; i++)
881 gid_valid |= (beamformer_entry->gid_valid[i] << (i << 3));
882 for (i = 0; i < 8; i++) {
883 if (i < 4)
884 user_position_l |= (beamformer_entry->user_position[i] << (i << 3));
885 else
886 user_position_h |= (beamformer_entry->user_position[i] << ((i - 4) << 3));
887 }
888 /*select MU STA0 table*/
889 beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
890 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
891 odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, gid_valid);
892 odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
893 odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
894
895 PHYDM_DBG(dm, DBG_TXBF,
896 "%s: STA0: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
897 __func__, gid_valid, user_position_l, user_position_h);
898
899 gid_valid = 0;
900 user_position_l = 0;
901 user_position_h = 0;
902
903 /*@For GID 32~64*/
904 for (i = 4; i < 8; i++)
905 gid_valid |= (beamformer_entry->gid_valid[i] << ((i - 4) << 3));
906 for (i = 8; i < 16; i++) {
907 if (i < 4)
908 user_position_l |= (beamformer_entry->user_position[i] << ((i - 8) << 3));
909 else
910 user_position_h |= (beamformer_entry->user_position[i] << ((i - 12) << 3));
911 }
912 /*select MU STA1 table*/
913 beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
914 beamforming_info->reg_mu_tx_ctrl |= BIT(8);
915 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
916 odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, gid_valid);
917 odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
918 odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
919
920 PHYDM_DBG(dm, DBG_TXBF,
921 "%s: STA1: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
922 __func__, gid_valid, user_position_l, user_position_h);
923
924 /* Set validity of MU STA0 and MU STA1*/
925 beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
926 beamforming_info->reg_mu_tx_ctrl |= 0x3; /* STA0, STA1*/
927 odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
928 }
929
930 #if 0
931 /*This function translate the bitmap to GTAB*/
932 void
933 haltxbf8822b_gtab_translation(
934 struct dm_struct *dm
935 )
936 {
937 u8 idx, gid;
938 u8 id1, id0;
939 u32 gid_valid[6] = {0};
940 u32 user_position_lsb[6] = {0};
941 u32 user_position_msb[6] = {0};
942
943 for (idx = 0; idx < 15; idx++) {
944 if (idx < 5) {/*@bit0~4*/
945 id0 = 0;
946 id1 = (u8)(idx + 1);
947 } else if (idx < 9) { /*@bit5~8*/
948 id0 = 1;
949 id1 = (u8)(idx - 3);
950 } else if (idx < 12) { /*@bit9~11*/
951 id0 = 2;
952 id1 = (u8)(idx - 6);
953 } else if (idx < 14) { /*@bit12~13*/
954 id0 = 3;
955 id1 = (u8)(idx - 8);
956 } else { /*@bit14*/
957 id0 = 4;
958 id1 = (u8)(idx - 9);
959 }
960
961 /*Pair 1*/
962 gid = (idx << 1) + 1;
963 gid_valid[id0] |= (1 << gid);
964 gid_valid[id1] |= (1 << gid);
965 if (gid < 16) {
966 /*user_position_lsb[id0] |= (0 << (gid << 1));*/
967 user_position_lsb[id1] |= (1 << (gid << 1));
968 } else {
969 /*user_position_msb[id0] |= (0 << ((gid - 16) << 1));*/
970 user_position_msb[id1] |= (1 << ((gid - 16) << 1));
971 }
972
973 /*Pair 2*/
974 gid += 1;
975 gid_valid[id0] |= (1 << gid);
976 gid_valid[id1] |= (1 << gid);
977 if (gid < 16) {
978 user_position_lsb[id0] |= (1 << (gid << 1));
979 /*user_position_lsb[id1] |= (0 << (gid << 1));*/
980 } else {
981 user_position_msb[id0] |= (1 << ((gid - 16) << 1));
982 /*user_position_msb[id1] |= (0 << ((gid - 16) << 1));*/
983 }
984 }
985
986
987 for (idx = 0; idx < 6; idx++) {
988 /*@dbg_print("gid_valid[%d] = 0x%x\n", idx, gid_valid[idx]);
989 dbg_print("user_position[%d] = 0x%x %x\n", idx, user_position_msb[idx], user_position_lsb[idx]);*/
990 }
991 }
992 #endif
993
hal_txbf_8822b_fw_txbf(void * dm_void,u8 idx)994 void hal_txbf_8822b_fw_txbf(
995 void *dm_void,
996 u8 idx)
997 {
998 #if 0
999 struct _RT_BEAMFORMING_INFO *beam_info = GET_BEAMFORM_INFO(adapter);
1000 struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = beam_info->beamformee_entry + idx;
1001
1002 if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
1003 hal_txbf_8822b_download_ndpa(adapter, idx);
1004
1005 hal_txbf_8822b_fw_txbf_cmd(adapter);
1006 #endif
1007 }
1008
1009 #endif
1010
1011 #if (defined(CONFIG_BB_TXBF_API))
1012 /*this function is only used for BFer*/
phydm_8822btxbf_rfmode(void * dm_void,u8 su_bfee_cnt,u8 mu_bfee_cnt)1013 void phydm_8822btxbf_rfmode(void *dm_void, u8 su_bfee_cnt, u8 mu_bfee_cnt)
1014 {
1015 struct dm_struct *dm = (struct dm_struct *)dm_void;
1016 u8 i;
1017
1018 if (dm->rf_type == RF_1T1R)
1019 return;
1020
1021 if (su_bfee_cnt > 0 || mu_bfee_cnt > 0) {
1022 for (i = RF_PATH_A; i <= RF_PATH_B; i++) {
1023 odm_set_rf_reg(dm, (enum rf_path)i, RF_0xef, BIT(19), 0x1); /*RF mode table write enable*/
1024 odm_set_rf_reg(dm, (enum rf_path)i, RF_0x33, 0xF, 3); /*Select RX mode*/
1025 odm_set_rf_reg(dm, (enum rf_path)i, RF_0x3e, 0xfffff, 0x00036); /*Set Table data*/
1026 odm_set_rf_reg(dm, (enum rf_path)i, RF_0x3f, 0xfffff, 0x5AFCE); /*Set Table data*/
1027 odm_set_rf_reg(dm, (enum rf_path)i, RF_0xef, BIT(19), 0x0); /*RF mode table write disable*/
1028 }
1029 }
1030
1031 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(30), 1); /*@if Nsts > Nc, don't apply V matrix*/
1032
1033 if (su_bfee_cnt > 0 || mu_bfee_cnt > 0) {
1034 /*@for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
1035 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2); /*@enable BB TxBF ant mapping register*/
1036 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1); /*@ignore user since 8822B only 2Tx*/
1037
1038 /*Nsts = 2 AB*/
1039 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
1040 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
1041
1042 } else {
1043 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x0); /*@enable BB TxBF ant mapping register*/
1044 odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 0); /*@ignore user since 8822B only 2Tx*/
1045
1046 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*@1SS by path-A*/
1047 odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*@2SS by path-A,B*/
1048 }
1049 }
1050
1051 /*this function is for BFer bug workaround*/
phydm_8822b_sutxbfer_workaroud(void * dm_void,boolean enable_su_bfer,u8 nc,u8 nr,u8 ng,u8 CB,u8 BW,boolean is_vht)1052 void phydm_8822b_sutxbfer_workaroud(void *dm_void, boolean enable_su_bfer,
1053 u8 nc, u8 nr, u8 ng, u8 CB, u8 BW,
1054 boolean is_vht)
1055 {
1056 struct dm_struct *dm = (struct dm_struct *)dm_void;
1057
1058 if (enable_su_bfer) {
1059 odm_set_bb_reg(dm, R_0x19f8, BIT(22) | BIT(21) | BIT(20), 0x1);
1060 odm_set_bb_reg(dm, R_0x19f8, BIT(25) | BIT(24) | BIT(23), 0x0);
1061 odm_set_bb_reg(dm, R_0x19f8, BIT(16), 0x1);
1062
1063 if (is_vht)
1064 odm_set_bb_reg(dm, R_0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x1f);
1065 else
1066 odm_set_bb_reg(dm, R_0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x22);
1067
1068 odm_set_bb_reg(dm, R_0x19f0, BIT(7) | BIT(6), nc);
1069 odm_set_bb_reg(dm, R_0x19f0, BIT(9) | BIT(8), nr);
1070 odm_set_bb_reg(dm, R_0x19f0, BIT(11) | BIT(10), ng);
1071 odm_set_bb_reg(dm, R_0x19f0, BIT(13) | BIT(12), CB);
1072
1073 odm_set_bb_reg(dm, R_0xb58, BIT(3) | BIT(2), BW);
1074 odm_set_bb_reg(dm, R_0xb58, BIT(7) | BIT(6) | BIT(5) | BIT(4), 0x0);
1075 odm_set_bb_reg(dm, R_0xb58, BIT(9) | BIT(8), BW);
1076 odm_set_bb_reg(dm, R_0xb58, BIT(13) | BIT(12) | BIT(11) | BIT(10), 0x0);
1077 } else {
1078 odm_set_bb_reg(dm, R_0x19f8, BIT(16), 0x0);
1079 }
1080
1081 PHYDM_DBG(dm, DBG_TXBF, "[%s] enable_su_bfer = %d, is_vht = %d\n",
1082 __func__, enable_su_bfer, is_vht);
1083 PHYDM_DBG(dm, DBG_TXBF,
1084 "[%s] nc = %d, nr = %d, ng = %d, CB = %d, BW = %d\n",
1085 __func__, nc, nr, ng, CB, BW);
1086 }
1087 #endif
1088 #endif /* @(RTL8822B_SUPPORT == 1)*/
1089